Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
9f30c3e7
Commit
9f30c3e7
authored
Jan 05, 2021
by
Nicolò Maria Mezzopera
Committed by
Olena Horal-Koretska
Jan 05, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new data points to graphql query
- query - mock datra
parent
0f8007bd
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
284 additions
and
34 deletions
+284
-34
app/assets/javascripts/registry/explorer/components/details_page/details_header.vue
...istry/explorer/components/details_page/details_header.vue
+56
-3
app/assets/javascripts/registry/explorer/constants/details.js
...assets/javascripts/registry/explorer/constants/details.js
+21
-0
app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_details.query.graphql
...ql/queries/get_container_repository_details.query.graphql
+5
-0
app/assets/javascripts/registry/explorer/pages/details.vue
app/assets/javascripts/registry/explorer/pages/details.vue
+6
-2
app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
...ascripts/vue_shared/components/registry/metadata_item.vue
+13
-2
app/assets/javascripts/vue_shared/components/registry/title_area.vue
...javascripts/vue_shared/components/registry/title_area.vue
+2
-2
changelogs/unreleased/276900-use-the-expiration_policy_cleanup_status-to-report-the-cleanup-pol.yml
...ation_policy_cleanup_status-to-report-the-cleanup-pol.yml
+5
-0
locale/gitlab.pot
locale/gitlab.pot
+27
-0
spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap
...tails/components/__snapshots__/package_title_spec.js.snap
+6
-2
spec/frontend/registry/explorer/components/details_page/details_header_spec.js
...y/explorer/components/details_page/details_header_spec.js
+105
-16
spec/frontend/registry/explorer/mock_data.js
spec/frontend/registry/explorer/mock_data.js
+5
-0
spec/frontend/registry/explorer/pages/details_spec.js
spec/frontend/registry/explorer/pages/details_spec.js
+12
-7
spec/frontend/vue_shared/components/registry/metadata_item_spec.js
...tend/vue_shared/components/registry/metadata_item_spec.js
+21
-0
No files found.
app/assets/javascripts/registry/explorer/components/details_page/details_header.vue
View file @
9f30c3e7
<
script
>
<
script
>
import
{
GlSprintf
}
from
'
@gitlab/ui
'
;
import
{
GlSprintf
}
from
'
@gitlab/ui
'
;
import
{
sprintf
}
from
'
~/locale
'
;
import
{
sprintf
,
n__
}
from
'
~/locale
'
;
import
TitleArea
from
'
~/vue_shared/components/registry/title_area.vue
'
;
import
TitleArea
from
'
~/vue_shared/components/registry/title_area.vue
'
;
import
MetadataItem
from
'
~/vue_shared/components/registry/metadata_item.vue
'
;
import
MetadataItem
from
'
~/vue_shared/components/registry/metadata_item.vue
'
;
import
timeagoMixin
from
'
~/vue_shared/mixins/timeago
'
;
import
timeagoMixin
from
'
~/vue_shared/mixins/timeago
'
;
import
{
DETAILS_PAGE_TITLE
,
UPDATED_AT
}
from
'
../../constants/index
'
;
import
{
DETAILS_PAGE_TITLE
,
UPDATED_AT
,
CLEANUP_UNSCHEDULED_TEXT
,
CLEANUP_SCHEDULED_TEXT
,
CLEANUP_ONGOING_TEXT
,
CLEANUP_UNFINISHED_TEXT
,
CLEANUP_DISABLED_TEXT
,
CLEANUP_SCHEDULED_TOOLTIP
,
CLEANUP_ONGOING_TOOLTIP
,
CLEANUP_UNFINISHED_TOOLTIP
,
CLEANUP_DISABLED_TOOLTIP
,
UNFINISHED_STATUS
,
UNSCHEDULED_STATUS
,
SCHEDULED_STATUS
,
ONGOING_STATUS
,
}
from
'
../../constants/index
'
;
export
default
{
export
default
{
name
:
'
DetailsHeader
'
,
name
:
'
DetailsHeader
'
,
...
@@ -15,6 +31,11 @@ export default {
...
@@ -15,6 +31,11 @@ export default {
type
:
Object
,
type
:
Object
,
required
:
true
,
required
:
true
,
},
},
metadataLoading
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
},
computed
:
{
computed
:
{
visibilityIcon
()
{
visibilityIcon
()
{
...
@@ -26,6 +47,24 @@ export default {
...
@@ -26,6 +47,24 @@ export default {
updatedText
()
{
updatedText
()
{
return
sprintf
(
UPDATED_AT
,
{
time
:
this
.
timeAgo
});
return
sprintf
(
UPDATED_AT
,
{
time
:
this
.
timeAgo
});
},
},
tagCountText
()
{
return
n__
(
'
%d tag
'
,
'
%d tags
'
,
this
.
image
.
tagsCount
);
},
cleanupTextAndTooltip
()
{
if
(
!
this
.
image
.
project
.
containerExpirationPolicy
?.
enabled
)
{
return
{
text
:
CLEANUP_DISABLED_TEXT
,
tooltip
:
CLEANUP_DISABLED_TOOLTIP
};
}
return
{
[
UNSCHEDULED_STATUS
]:
{
text
:
sprintf
(
CLEANUP_UNSCHEDULED_TEXT
,
{
time
:
this
.
timeFormatted
(
this
.
image
.
project
.
containerExpirationPolicy
.
nextRunAt
),
}),
},
[
SCHEDULED_STATUS
]:
{
text
:
CLEANUP_SCHEDULED_TEXT
,
tooltip
:
CLEANUP_SCHEDULED_TOOLTIP
},
[
ONGOING_STATUS
]:
{
text
:
CLEANUP_ONGOING_TEXT
,
tooltip
:
CLEANUP_ONGOING_TOOLTIP
},
[
UNFINISHED_STATUS
]:
{
text
:
CLEANUP_UNFINISHED_TEXT
,
tooltip
:
CLEANUP_UNFINISHED_TOOLTIP
},
}[
this
.
image
?.
expirationPolicyCleanupStatus
];
},
},
},
i18n
:
{
i18n
:
{
DETAILS_PAGE_TITLE
,
DETAILS_PAGE_TITLE
,
...
@@ -34,7 +73,7 @@ export default {
...
@@ -34,7 +73,7 @@ export default {
</
script
>
</
script
>
<
template
>
<
template
>
<title-area>
<title-area
:metadata-loading=
"metadataLoading"
>
<template
#title
>
<template
#title
>
<gl-sprintf
:message=
"$options.i18n.DETAILS_PAGE_TITLE"
>
<gl-sprintf
:message=
"$options.i18n.DETAILS_PAGE_TITLE"
>
<template
#imageName
>
<template
#imageName
>
...
@@ -42,6 +81,20 @@ export default {
...
@@ -42,6 +81,20 @@ export default {
</
template
>
</
template
>
</gl-sprintf>
</gl-sprintf>
</template>
</template>
<
template
#metadata-tags-count
>
<metadata-item
icon=
"tag"
:text=
"tagCountText"
data-testid=
"tags-count"
/>
</
template
>
<
template
#metadata-cleanup
>
<metadata-item
icon=
"expire"
:text=
"cleanupTextAndTooltip.text"
:text-tooltip=
"cleanupTextAndTooltip.tooltip"
size=
"xl"
data-testid=
"cleanup"
/>
</
template
>
<
template
#metadata-updated
>
<
template
#metadata-updated
>
<metadata-item
<metadata-item
:icon=
"visibilityIcon"
:icon=
"visibilityIcon"
...
...
app/assets/javascripts/registry/explorer/constants/details.js
View file @
9f30c3e7
...
@@ -60,6 +60,22 @@ export const UPDATED_AT = s__('ContainerRegistry|Last updated %{time}');
...
@@ -60,6 +60,22 @@ export const UPDATED_AT = s__('ContainerRegistry|Last updated %{time}');
export
const
NOT_AVAILABLE_TEXT
=
__
(
'
N/A
'
);
export
const
NOT_AVAILABLE_TEXT
=
__
(
'
N/A
'
);
export
const
NOT_AVAILABLE_SIZE
=
__
(
'
0 bytes
'
);
export
const
NOT_AVAILABLE_SIZE
=
__
(
'
0 bytes
'
);
export
const
CLEANUP_UNSCHEDULED_TEXT
=
s__
(
'
ContainerRegistry|Cleanup will run %{time}
'
);
export
const
CLEANUP_SCHEDULED_TEXT
=
s__
(
'
ContainerRegistry|Cleanup pending
'
);
export
const
CLEANUP_ONGOING_TEXT
=
s__
(
'
ContainerRegistry|Cleanup in progress
'
);
export
const
CLEANUP_UNFINISHED_TEXT
=
s__
(
'
ContainerRegistry|Cleanup incomplete
'
);
export
const
CLEANUP_DISABLED_TEXT
=
s__
(
'
ContainerRegistry|Cleanup disabled
'
);
export
const
CLEANUP_SCHEDULED_TOOLTIP
=
s__
(
'
ContainerRegistry|Cleanup will run soon
'
);
export
const
CLEANUP_ONGOING_TOOLTIP
=
s__
(
'
ContainerRegistry|Cleanup is currently removing tags
'
);
export
const
CLEANUP_UNFINISHED_TOOLTIP
=
s__
(
'
ContainerRegistry|Cleanup ran but some tags were not removed
'
,
);
export
const
CLEANUP_DISABLED_TOOLTIP
=
s__
(
'
ContainerRegistry|Cleanup is disabled for this project
'
,
);
// Parameters
// Parameters
export
const
DEFAULT_PAGE
=
1
;
export
const
DEFAULT_PAGE
=
1
;
...
@@ -76,3 +92,8 @@ export const ALERT_MESSAGES = {
...
@@ -76,3 +92,8 @@ export const ALERT_MESSAGES = {
[
ALERT_SUCCESS_TAGS
]:
DELETE_TAGS_SUCCESS_MESSAGE
,
[
ALERT_SUCCESS_TAGS
]:
DELETE_TAGS_SUCCESS_MESSAGE
,
[
ALERT_DANGER_TAGS
]:
DELETE_TAGS_ERROR_MESSAGE
,
[
ALERT_DANGER_TAGS
]:
DELETE_TAGS_ERROR_MESSAGE
,
};
};
export
const
UNFINISHED_STATUS
=
'
UNFINISHED
'
;
export
const
UNSCHEDULED_STATUS
=
'
UNSCHEDULED
'
;
export
const
SCHEDULED_STATUS
=
'
SCHEDULED
'
;
export
const
ONGOING_STATUS
=
'
ONGOING
'
;
app/assets/javascripts/registry/explorer/graphql/queries/get_container_repository_details.query.graphql
View file @
9f30c3e7
...
@@ -18,6 +18,7 @@ query getContainerRepositoryDetails(
...
@@ -18,6 +18,7 @@ query getContainerRepositoryDetails(
updatedAt
updatedAt
tagsCount
tagsCount
expirationPolicyStartedAt
expirationPolicyStartedAt
expirationPolicyCleanupStatus
tags
(
after
:
$after
,
before
:
$before
,
first
:
$first
,
last
:
$last
)
{
tags
(
after
:
$after
,
before
:
$before
,
first
:
$first
,
last
:
$last
)
{
nodes
{
nodes
{
digest
digest
...
@@ -36,6 +37,10 @@ query getContainerRepositoryDetails(
...
@@ -36,6 +37,10 @@ query getContainerRepositoryDetails(
}
}
project
{
project
{
visibility
visibility
containerExpirationPolicy
{
enabled
nextRunAt
}
}
}
}
}
}
}
app/assets/javascripts/registry/explorer/pages/details.vue
View file @
9f30c3e7
...
@@ -22,6 +22,7 @@ import {
...
@@ -22,6 +22,7 @@ import {
ALERT_DANGER_TAGS
,
ALERT_DANGER_TAGS
,
GRAPHQL_PAGE_SIZE
,
GRAPHQL_PAGE_SIZE
,
FETCH_IMAGES_LIST_ERROR_MESSAGE
,
FETCH_IMAGES_LIST_ERROR_MESSAGE
,
UNFINISHED_STATUS
,
}
from
'
../constants/index
'
;
}
from
'
../constants/index
'
;
export
default
{
export
default
{
...
@@ -84,7 +85,10 @@ export default {
...
@@ -84,7 +85,10 @@ export default {
return
this
.
image
?.
tags
?.
nodes
||
[];
return
this
.
image
?.
tags
?.
nodes
||
[];
},
},
showPartialCleanupWarning
()
{
showPartialCleanupWarning
()
{
return
this
.
image
?.
expirationPolicyStartedAt
&&
!
this
.
dismissPartialCleanupWarning
;
return
(
this
.
image
?.
expirationPolicyCleanupStatus
===
UNFINISHED_STATUS
&&
!
this
.
dismissPartialCleanupWarning
);
},
},
tracking
()
{
tracking
()
{
return
{
return
{
...
@@ -184,7 +188,7 @@ export default {
...
@@ -184,7 +188,7 @@ export default {
@
dismiss=
"dismissPartialCleanupWarning = true"
@
dismiss=
"dismissPartialCleanupWarning = true"
/>
/>
<details-header
:image=
"image"
/>
<details-header
:image=
"image"
:metadata-loading=
"isLoading"
/>
<tags-loader
v-if=
"isLoading"
/>
<tags-loader
v-if=
"isLoading"
/>
<template
v-else
>
<template
v-else
>
...
...
app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
View file @
9f30c3e7
<
script
>
<
script
>
import
{
GlIcon
,
GlLink
}
from
'
@gitlab/ui
'
;
import
{
GlIcon
,
GlLink
,
GlTooltipDirective
}
from
'
@gitlab/ui
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
export
default
{
export
default
{
...
@@ -9,6 +9,9 @@ export default {
...
@@ -9,6 +9,9 @@ export default {
GlLink
,
GlLink
,
TooltipOnTruncate
,
TooltipOnTruncate
,
},
},
directives
:
{
GlTooltip
:
GlTooltipDirective
,
},
props
:
{
props
:
{
icon
:
{
icon
:
{
type
:
String
,
type
:
String
,
...
@@ -32,6 +35,11 @@ export default {
...
@@ -32,6 +35,11 @@ export default {
return
!
value
||
[
'
xs
'
,
'
s
'
,
'
m
'
,
'
l
'
,
'
xl
'
].
includes
(
value
);
return
!
value
||
[
'
xs
'
,
'
s
'
,
'
m
'
,
'
l
'
,
'
xl
'
].
includes
(
value
);
},
},
},
},
textTooltip
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
},
},
computed
:
{
computed
:
{
sizeClass
()
{
sizeClass
()
{
...
@@ -55,9 +63,12 @@ export default {
...
@@ -55,9 +63,12 @@ export default {
class=
"gl-font-weight-bold gl-display-inline-flex"
class=
"gl-font-weight-bold gl-display-inline-flex"
:class=
"sizeClass"
:class=
"sizeClass"
>
>
<tooltip-on-truncate
:title=
"text"
class=
"gl-text-truncate"
>
<tooltip-on-truncate
v-if=
"!textTooltip"
:title=
"text"
class=
"gl-text-truncate"
>
{{
text
}}
{{
text
}}
</tooltip-on-truncate>
</tooltip-on-truncate>
<span
v-else
v-gl-tooltip=
"
{ title: textTooltip }" data-testid="text-tooltip-container">
{{
text
}}
</span
>
</div>
</div>
</div>
</div>
</
template
>
</
template
>
app/assets/javascripts/vue_shared/components/registry/title_area.vue
View file @
9f30c3e7
...
@@ -50,7 +50,7 @@ export default {
...
@@ -50,7 +50,7 @@ export default {
<
template
>
<
template
>
<div
class=
"gl-display-flex gl-flex-direction-column"
>
<div
class=
"gl-display-flex gl-flex-direction-column"
>
<div
class=
"gl-display-flex gl-justify-content-space-between gl-py-3"
>
<div
class=
"gl-display-flex gl-justify-content-space-between gl-py-3"
>
<div
class=
"gl-flex-direction-column"
>
<div
class=
"gl-flex-direction-column
gl-flex-grow-1
"
>
<div
class=
"gl-display-flex"
>
<div
class=
"gl-display-flex"
>
<gl-avatar
<gl-avatar
v-if=
"avatar"
v-if=
"avatar"
...
@@ -85,7 +85,7 @@ export default {
...
@@ -85,7 +85,7 @@ export default {
</
template
>
</
template
>
<
template
v-else
>
<
template
v-else
>
<div
class=
"gl-w-full"
>
<div
class=
"gl-w-full"
>
<gl-skeleton-loader
:width=
"
20
0"
:height=
"16"
preserve-aspect-ratio=
"xMinYMax meet"
>
<gl-skeleton-loader
:width=
"
96
0"
:height=
"16"
preserve-aspect-ratio=
"xMinYMax meet"
>
<circle
cx=
"6"
cy=
"8"
r=
"6"
/>
<circle
cx=
"6"
cy=
"8"
r=
"6"
/>
<rect
x=
"16"
y=
"4"
width=
"200"
height=
"8"
rx=
"4"
/>
<rect
x=
"16"
y=
"4"
width=
"200"
height=
"8"
rx=
"4"
/>
</gl-skeleton-loader>
</gl-skeleton-loader>
...
...
changelogs/unreleased/276900-use-the-expiration_policy_cleanup_status-to-report-the-cleanup-pol.yml
0 → 100644
View file @
9f30c3e7
---
title
:
Add tags count and cleanup status to registry details
merge_request
:
50756
author
:
type
:
changed
locale/gitlab.pot
View file @
9f30c3e7
...
@@ -7471,15 +7471,42 @@ msgstr ""
...
@@ -7471,15 +7471,42 @@ msgstr ""
msgid "ContainerRegistry|CLI Commands"
msgid "ContainerRegistry|CLI Commands"
msgstr ""
msgstr ""
msgid "ContainerRegistry|Cleanup disabled"
msgstr ""
msgid "ContainerRegistry|Cleanup in progress"
msgstr ""
msgid "ContainerRegistry|Cleanup incomplete"
msgstr ""
msgid "ContainerRegistry|Cleanup is currently removing tags"
msgstr ""
msgid "ContainerRegistry|Cleanup is disabled for this project"
msgstr ""
msgid "ContainerRegistry|Cleanup pending"
msgstr ""
msgid "ContainerRegistry|Cleanup policy for tags is disabled"
msgid "ContainerRegistry|Cleanup policy for tags is disabled"
msgstr ""
msgstr ""
msgid "ContainerRegistry|Cleanup policy successfully saved."
msgid "ContainerRegistry|Cleanup policy successfully saved."
msgstr ""
msgstr ""
msgid "ContainerRegistry|Cleanup ran but some tags were not removed"
msgstr ""
msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
msgstr ""
msgstr ""
msgid "ContainerRegistry|Cleanup will run %{time}"
msgstr ""
msgid "ContainerRegistry|Cleanup will run soon"
msgstr ""
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
msgstr ""
...
...
spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap
View file @
9f30c3e7
...
@@ -9,7 +9,7 @@ exports[`PackageTitle renders with tags 1`] = `
...
@@ -9,7 +9,7 @@ exports[`PackageTitle renders with tags 1`] = `
class="gl-display-flex gl-justify-content-space-between gl-py-3"
class="gl-display-flex gl-justify-content-space-between gl-py-3"
>
>
<div
<div
class="gl-flex-direction-column"
class="gl-flex-direction-column
gl-flex-grow-1
"
>
>
<div
<div
class="gl-display-flex"
class="gl-display-flex"
...
@@ -54,6 +54,7 @@ exports[`PackageTitle renders with tags 1`] = `
...
@@ -54,6 +54,7 @@ exports[`PackageTitle renders with tags 1`] = `
link=""
link=""
size="s"
size="s"
text="maven"
text="maven"
texttooltip=""
/>
/>
</div>
</div>
<div
<div
...
@@ -65,6 +66,7 @@ exports[`PackageTitle renders with tags 1`] = `
...
@@ -65,6 +66,7 @@ exports[`PackageTitle renders with tags 1`] = `
link=""
link=""
size="s"
size="s"
text="300 bytes"
text="300 bytes"
texttooltip=""
/>
/>
</div>
</div>
<div
<div
...
@@ -95,7 +97,7 @@ exports[`PackageTitle renders without tags 1`] = `
...
@@ -95,7 +97,7 @@ exports[`PackageTitle renders without tags 1`] = `
class="gl-display-flex gl-justify-content-space-between gl-py-3"
class="gl-display-flex gl-justify-content-space-between gl-py-3"
>
>
<div
<div
class="gl-flex-direction-column"
class="gl-flex-direction-column
gl-flex-grow-1
"
>
>
<div
<div
class="gl-display-flex"
class="gl-display-flex"
...
@@ -140,6 +142,7 @@ exports[`PackageTitle renders without tags 1`] = `
...
@@ -140,6 +142,7 @@ exports[`PackageTitle renders without tags 1`] = `
link=""
link=""
size="s"
size="s"
text="maven"
text="maven"
texttooltip=""
/>
/>
</div>
</div>
<div
<div
...
@@ -151,6 +154,7 @@ exports[`PackageTitle renders without tags 1`] = `
...
@@ -151,6 +154,7 @@ exports[`PackageTitle renders without tags 1`] = `
link=""
link=""
size="s"
size="s"
text="300 bytes"
text="300 bytes"
texttooltip=""
/>
/>
</div>
</div>
</div>
</div>
...
...
spec/frontend/registry/explorer/components/details_page/details_header_spec.js
View file @
9f30c3e7
...
@@ -3,7 +3,18 @@ import { GlSprintf } from '@gitlab/ui';
...
@@ -3,7 +3,18 @@ import { GlSprintf } from '@gitlab/ui';
import
{
useFakeDate
}
from
'
helpers/fake_date
'
;
import
{
useFakeDate
}
from
'
helpers/fake_date
'
;
import
TitleArea
from
'
~/vue_shared/components/registry/title_area.vue
'
;
import
TitleArea
from
'
~/vue_shared/components/registry/title_area.vue
'
;
import
component
from
'
~/registry/explorer/components/details_page/details_header.vue
'
;
import
component
from
'
~/registry/explorer/components/details_page/details_header.vue
'
;
import
{
DETAILS_PAGE_TITLE
}
from
'
~/registry/explorer/constants
'
;
import
{
DETAILS_PAGE_TITLE
,
UNSCHEDULED_STATUS
,
SCHEDULED_STATUS
,
ONGOING_STATUS
,
UNFINISHED_STATUS
,
CLEANUP_DISABLED_TEXT
,
CLEANUP_DISABLED_TOOLTIP
,
CLEANUP_SCHEDULED_TOOLTIP
,
CLEANUP_ONGOING_TOOLTIP
,
CLEANUP_UNFINISHED_TOOLTIP
,
}
from
'
~/registry/explorer/constants
'
;
describe
(
'
Details Header
'
,
()
=>
{
describe
(
'
Details Header
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
...
@@ -11,15 +22,22 @@ describe('Details Header', () => {
...
@@ -11,15 +22,22 @@ describe('Details Header', () => {
const
defaultImage
=
{
const
defaultImage
=
{
name
:
'
foo
'
,
name
:
'
foo
'
,
updatedAt
:
'
2020-11-03T13:29:21Z
'
,
updatedAt
:
'
2020-11-03T13:29:21Z
'
,
tagsCount
:
10
,
project
:
{
project
:
{
visibility
:
'
public
'
,
visibility
:
'
public
'
,
containerExpirationPolicy
:
{
enabled
:
false
,
},
},
},
};
};
// set the date to Dec 4, 2020
// set the date to Dec 4, 2020
useFakeDate
(
2020
,
11
,
4
);
useFakeDate
(
2020
,
11
,
4
);
const
findByTestId
=
(
testId
)
=>
wrapper
.
find
(
`[data-testid="
${
testId
}
"]`
);
const
findLastUpdatedAndVisibility
=
()
=>
wrapper
.
find
(
'
[data-testid="updated-and-visibility"]
'
);
const
findLastUpdatedAndVisibility
=
()
=>
findByTestId
(
'
updated-and-visibility
'
);
const
findTagsCount
=
()
=>
findByTestId
(
'
tags-count
'
);
const
findCleanup
=
()
=>
findByTestId
(
'
cleanup
'
);
const
waitForMetadataItems
=
async
()
=>
{
const
waitForMetadataItems
=
async
()
=>
{
// Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available
// Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available
...
@@ -54,25 +72,96 @@ describe('Details Header', () => {
...
@@ -54,25 +72,96 @@ describe('Details Header', () => {
expect
(
wrapper
.
text
()).
toContain
(
'
foo
'
);
expect
(
wrapper
.
text
()).
toContain
(
'
foo
'
);
});
});
it
(
'
has a metadata item with last updated text
'
,
async
()
=>
{
describe
(
'
metadata items
'
,
()
=>
{
mountComponent
();
describe
(
'
tags count
'
,
()
=>
{
await
waitForMetadataItems
();
it
(
'
when there is more than one tag has the correct text
'
,
async
()
=>
{
mountComponent
();
await
waitForMetadataItems
();
expect
(
findLastUpdatedAndVisibility
().
props
(
'
text
'
)).
toBe
(
'
Last updated 1 month ago
'
);
expect
(
findTagsCount
().
props
(
'
text
'
)).
toBe
(
'
10 tags
'
);
});
});
it
(
'
when there is one tag has the correct text
'
,
async
()
=>
{
mountComponent
({
...
defaultImage
,
tagsCount
:
1
});
await
waitForMetadataItems
();
expect
(
findTagsCount
().
props
(
'
text
'
)).
toBe
(
'
1 tag
'
);
});
it
(
'
has the correct icon
'
,
async
()
=>
{
mountComponent
();
await
waitForMetadataItems
();
expect
(
findTagsCount
().
props
(
'
icon
'
)).
toBe
(
'
tag
'
);
});
});
describe
(
'
visibility icon
'
,
()
=>
{
describe
(
'
cleanup metadata item
'
,
()
=>
{
it
(
'
shows an eye when the project is public
'
,
async
()
=>
{
it
(
'
has the correct icon
'
,
async
()
=>
{
mountComponent
();
mountComponent
();
await
waitForMetadataItems
();
await
waitForMetadataItems
();
expect
(
findLastUpdatedAndVisibility
().
props
(
'
icon
'
)).
toBe
(
'
eye
'
);
expect
(
findCleanup
().
props
(
'
icon
'
)).
toBe
(
'
expire
'
);
});
it
(
'
when the expiration policy is disabled
'
,
async
()
=>
{
mountComponent
();
await
waitForMetadataItems
();
expect
(
findCleanup
().
props
()).
toMatchObject
({
text
:
CLEANUP_DISABLED_TEXT
,
textTooltip
:
CLEANUP_DISABLED_TOOLTIP
,
});
});
it
.
each
`
status | text | tooltip
${
UNSCHEDULED_STATUS
}
|
${
'
Cleanup will run in 1 month
'
}
|
${
''
}
${
SCHEDULED_STATUS
}
|
${
'
Cleanup pending
'
}
|
${
CLEANUP_SCHEDULED_TOOLTIP
}
${
ONGOING_STATUS
}
|
${
'
Cleanup in progress
'
}
|
${
CLEANUP_ONGOING_TOOLTIP
}
${
UNFINISHED_STATUS
}
|
${
'
Cleanup incomplete
'
}
|
${
CLEANUP_UNFINISHED_TOOLTIP
}
`
(
'
when the status is $status the text is $text and the tooltip is $tooltip
'
,
async
({
status
,
text
,
tooltip
})
=>
{
mountComponent
({
...
defaultImage
,
expirationPolicyCleanupStatus
:
status
,
project
:
{
containerExpirationPolicy
:
{
enabled
:
true
,
nextRunAt
:
'
2021-01-03T14:29:21Z
'
},
},
});
await
waitForMetadataItems
();
expect
(
findCleanup
().
props
()).
toMatchObject
({
text
,
textTooltip
:
tooltip
,
});
},
);
});
});
it
(
'
shows an eye slashed when the project is not public
'
,
async
()
=>
{
mountComponent
({
...
defaultImage
,
project
:
{
visibility
:
'
private
'
}
});
await
waitForMetadataItems
();
expect
(
findLastUpdatedAndVisibility
().
props
(
'
icon
'
)).
toBe
(
'
eye-slash
'
);
describe
(
'
visibility and updated at
'
,
()
=>
{
it
(
'
has last updated text
'
,
async
()
=>
{
mountComponent
();
await
waitForMetadataItems
();
expect
(
findLastUpdatedAndVisibility
().
props
(
'
text
'
)).
toBe
(
'
Last updated 1 month ago
'
);
});
describe
(
'
visibility icon
'
,
()
=>
{
it
(
'
shows an eye when the project is public
'
,
async
()
=>
{
mountComponent
();
await
waitForMetadataItems
();
expect
(
findLastUpdatedAndVisibility
().
props
(
'
icon
'
)).
toBe
(
'
eye
'
);
});
it
(
'
shows an eye slashed when the project is not public
'
,
async
()
=>
{
mountComponent
({
...
defaultImage
,
project
:
{
visibility
:
'
private
'
}
});
await
waitForMetadataItems
();
expect
(
findLastUpdatedAndVisibility
().
props
(
'
icon
'
)).
toBe
(
'
eye-slash
'
);
});
});
});
});
});
});
});
});
spec/frontend/registry/explorer/mock_data.js
View file @
9f30c3e7
...
@@ -117,8 +117,13 @@ export const containerRepositoryMock = {
...
@@ -117,8 +117,13 @@ export const containerRepositoryMock = {
updatedAt
:
'
2020-11-03T13:29:21Z
'
,
updatedAt
:
'
2020-11-03T13:29:21Z
'
,
tagsCount
:
13
,
tagsCount
:
13
,
expirationPolicyStartedAt
:
null
,
expirationPolicyStartedAt
:
null
,
expirationPolicyCleanupStatus
:
'
UNSCHEDULED
'
,
project
:
{
project
:
{
visibility
:
'
public
'
,
visibility
:
'
public
'
,
containerExpirationPolicy
:
{
enabled
:
false
,
nextRunAt
:
'
2020-11-27T08:59:27Z
'
,
},
__typename
:
'
Project
'
,
__typename
:
'
Project
'
,
},
},
};
};
...
...
spec/frontend/registry/explorer/pages/details_spec.js
View file @
9f30c3e7
...
@@ -15,6 +15,8 @@ import EmptyTagsState from '~/registry/explorer/components/details_page/empty_ta
...
@@ -15,6 +15,8 @@ import EmptyTagsState from '~/registry/explorer/components/details_page/empty_ta
import
getContainerRepositoryDetailsQuery
from
'
~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql
'
;
import
getContainerRepositoryDetailsQuery
from
'
~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql
'
;
import
deleteContainerRepositoryTagsMutation
from
'
~/registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql
'
;
import
deleteContainerRepositoryTagsMutation
from
'
~/registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql
'
;
import
{
UNFINISHED_STATUS
}
from
'
~/registry/explorer/constants/index
'
;
import
{
import
{
graphQLImageDetailsMock
,
graphQLImageDetailsMock
,
graphQLImageDetailsEmptyTagsMock
,
graphQLImageDetailsEmptyTagsMock
,
...
@@ -353,10 +355,13 @@ describe('Details Page', () => {
...
@@ -353,10 +355,13 @@ describe('Details Page', () => {
mountComponent
();
mountComponent
();
await
waitForApolloRequestRender
();
await
waitForApolloRequestRender
();
expect
(
findDetailsHeader
().
props
(
'
image
'
)).
toMatchObject
({
expect
(
findDetailsHeader
().
props
()).
toMatchObject
({
name
:
containerRepositoryMock
.
name
,
metadataLoading
:
false
,
project
:
{
image
:
{
visibility
:
containerRepositoryMock
.
project
.
visibility
,
name
:
containerRepositoryMock
.
name
,
project
:
{
visibility
:
containerRepositoryMock
.
project
.
visibility
,
},
},
},
});
});
});
});
...
@@ -398,13 +403,13 @@ describe('Details Page', () => {
...
@@ -398,13 +403,13 @@ describe('Details Page', () => {
cleanupPoliciesHelpPagePath
:
'
bar
'
,
cleanupPoliciesHelpPagePath
:
'
bar
'
,
};
};
describe
(
'
when expiration_policy_started is not null
'
,
()
=>
{
describe
(
`when expirationPolicyCleanupStatus is
${
UNFINISHED_STATUS
}
`
,
()
=>
{
let
resolver
;
let
resolver
;
beforeEach
(()
=>
{
beforeEach
(()
=>
{
resolver
=
jest
.
fn
().
mockResolvedValue
(
resolver
=
jest
.
fn
().
mockResolvedValue
(
graphQLImageDetailsMock
({
graphQLImageDetailsMock
({
expirationPolicy
StartedAt
:
Date
.
now
().
toString
()
,
expirationPolicy
CleanupStatus
:
UNFINISHED_STATUS
,
}),
}),
);
);
});
});
...
@@ -439,7 +444,7 @@ describe('Details Page', () => {
...
@@ -439,7 +444,7 @@ describe('Details Page', () => {
});
});
});
});
describe
(
'
when expiration_policy_started is null
'
,
()
=>
{
describe
(
`when expirationPolicyCleanupStatus is not
${
UNFINISHED_STATUS
}
`
,
()
=>
{
it
(
'
the component is hidden
'
,
async
()
=>
{
it
(
'
the component is hidden
'
,
async
()
=>
{
mountComponent
();
mountComponent
();
await
waitForApolloRequestRender
();
await
waitForApolloRequestRender
();
...
...
spec/frontend/vue_shared/components/registry/metadata_item_spec.js
View file @
9f30c3e7
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
GlIcon
,
GlLink
}
from
'
@gitlab/ui
'
;
import
{
GlIcon
,
GlLink
}
from
'
@gitlab/ui
'
;
import
{
createMockDirective
,
getBinding
}
from
'
helpers/vue_mock_directive
'
;
import
component
from
'
~/vue_shared/components/registry/metadata_item.vue
'
;
import
component
from
'
~/vue_shared/components/registry/metadata_item.vue
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
...
@@ -12,6 +13,9 @@ describe('Metadata Item', () => {
...
@@ -12,6 +13,9 @@ describe('Metadata Item', () => {
const
mountComponent
=
(
propsData
=
defaultProps
)
=>
{
const
mountComponent
=
(
propsData
=
defaultProps
)
=>
{
wrapper
=
shallowMount
(
component
,
{
wrapper
=
shallowMount
(
component
,
{
propsData
,
propsData
,
directives
:
{
GlTooltip
:
createMockDirective
(),
},
});
});
};
};
...
@@ -24,6 +28,7 @@ describe('Metadata Item', () => {
...
@@ -24,6 +28,7 @@ describe('Metadata Item', () => {
const
findLink
=
(
w
=
wrapper
)
=>
w
.
find
(
GlLink
);
const
findLink
=
(
w
=
wrapper
)
=>
w
.
find
(
GlLink
);
const
findText
=
()
=>
wrapper
.
find
(
'
[data-testid="metadata-item-text"]
'
);
const
findText
=
()
=>
wrapper
.
find
(
'
[data-testid="metadata-item-text"]
'
);
const
findTooltipOnTruncate
=
(
w
=
wrapper
)
=>
w
.
find
(
TooltipOnTruncate
);
const
findTooltipOnTruncate
=
(
w
=
wrapper
)
=>
w
.
find
(
TooltipOnTruncate
);
const
findTextTooltip
=
()
=>
wrapper
.
find
(
'
[data-testid="text-tooltip-container"]
'
);
describe
.
each
([
'
xs
'
,
'
s
'
,
'
m
'
,
'
l
'
,
'
xl
'
])(
'
size class
'
,
(
size
)
=>
{
describe
.
each
([
'
xs
'
,
'
s
'
,
'
m
'
,
'
l
'
,
'
xl
'
])(
'
size class
'
,
(
size
)
=>
{
const
className
=
`mw-
${
size
}
`
;
const
className
=
`mw-
${
size
}
`
;
...
@@ -55,6 +60,22 @@ describe('Metadata Item', () => {
...
@@ -55,6 +60,22 @@ describe('Metadata Item', () => {
expect
(
tooltip
.
exists
()).
toBe
(
true
);
expect
(
tooltip
.
exists
()).
toBe
(
true
);
expect
(
tooltip
.
attributes
(
'
title
'
)).
toBe
(
defaultProps
.
text
);
expect
(
tooltip
.
attributes
(
'
title
'
)).
toBe
(
defaultProps
.
text
);
});
});
describe
(
'
with tooltip prop set to something
'
,
()
=>
{
const
textTooltip
=
'
foo
'
;
it
(
'
hides tooltip_on_truncate
'
,
()
=>
{
mountComponent
({
...
defaultProps
,
textTooltip
});
expect
(
findTooltipOnTruncate
(
findText
()).
exists
()).
toBe
(
false
);
});
it
(
'
set the tooltip on the text
'
,
()
=>
{
mountComponent
({
...
defaultProps
,
textTooltip
});
const
tooltip
=
getBinding
(
findTextTooltip
().
element
,
'
gl-tooltip
'
);
expect
(
tooltip
.
value
.
title
).
toBe
(
textTooltip
);
});
});
});
});
describe
(
'
link
'
,
()
=>
{
describe
(
'
link
'
,
()
=>
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment