summaryrefslogtreecommitdiff
path: root/spec/frontend/registry/explorer/components
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/registry/explorer/components')
-rw-r--r--spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap4
-rw-r--r--spec/frontend/registry/explorer/components/details_page/details_header_spec.js48
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js55
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_spec.js10
-rw-r--r--spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap5
-rw-r--r--spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap11
-rw-r--r--spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js41
-rw-r--r--spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js17
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js61
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_spec.js60
-rw-r--r--spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js31
-rw-r--r--spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js9
12 files changed, 201 insertions, 151 deletions
diff --git a/spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap b/spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap
index aeb49f88770..5f191ef5561 100644
--- a/spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap
+++ b/spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap
@@ -2,9 +2,7 @@
exports[`TagsLoader component has the correct markup 1`] = `
<div>
- <div
- preserve-aspect-ratio="xMinYMax meet"
- >
+ <div>
<rect
height="15"
rx="4"
diff --git a/spec/frontend/registry/explorer/components/details_page/details_header_spec.js b/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
index fc93e9094c9..ec883886026 100644
--- a/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
@@ -7,9 +7,27 @@ import { DETAILS_PAGE_TITLE } from '~/registry/explorer/constants';
describe('Details Header', () => {
let wrapper;
- const mountComponent = propsData => {
+ const defaultImage = {
+ name: 'foo',
+ updatedAt: '2020-11-03T13:29:21Z',
+ project: {
+ visibility: 'public',
+ },
+ };
+
+ const findLastUpdatedAndVisibility = () => wrapper.find('[data-testid="updated-and-visibility"]');
+
+ const waitForMetadataItems = async () => {
+ // Metadata items are printed by a loop in the title-area and it takes two ticks for them to be available
+ await wrapper.vm.$nextTick();
+ await wrapper.vm.$nextTick();
+ };
+
+ const mountComponent = (image = defaultImage) => {
wrapper = shallowMount(component, {
- propsData,
+ propsData: {
+ image,
+ },
stubs: {
GlSprintf,
TitleArea,
@@ -23,12 +41,34 @@ describe('Details Header', () => {
});
it('has the correct title ', () => {
- mountComponent();
+ mountComponent({ ...defaultImage, name: '' });
expect(wrapper.text()).toMatchInterpolatedText(DETAILS_PAGE_TITLE);
});
it('shows imageName in the title', () => {
- mountComponent({ imageName: 'foo' });
+ mountComponent();
expect(wrapper.text()).toContain('foo');
});
+
+ it('has a metadata item with 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');
+ });
+ });
});
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
index 3276ef911e3..e1b75636735 100644
--- a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
@@ -15,12 +15,12 @@ import {
NOT_AVAILABLE_SIZE,
} from '~/registry/explorer/constants/index';
-import { tagsListResponse } from '../../mock_data';
+import { tagsMock } from '../../mock_data';
import { ListItem } from '../../stubs';
describe('tags list row', () => {
let wrapper;
- const [tag] = [...tagsListResponse.data];
+ const [tag] = [...tagsMock];
const defaultProps = { tag, isMobile: false, index: 0 };
@@ -65,7 +65,7 @@ describe('tags list row', () => {
});
it("does not exist when the row can't be deleted", () => {
- const customTag = { ...tag, destroy_path: '' };
+ const customTag = { ...tag, canDelete: false };
mountComponent({ ...defaultProps, tag: customTag });
@@ -137,8 +137,8 @@ describe('tags list row', () => {
mountComponent();
expect(findClipboardButton().attributes()).toMatchObject({
- text: 'location',
- title: 'location',
+ text: tag.location,
+ title: tag.location,
});
});
});
@@ -171,26 +171,26 @@ describe('tags list row', () => {
expect(findSize().exists()).toBe(true);
});
- it('contains the total_size and layers', () => {
- mountComponent({ ...defaultProps, tag: { ...tag, total_size: 1024 } });
+ it('contains the totalSize and layers', () => {
+ mountComponent({ ...defaultProps, tag: { ...tag, totalSize: 1024, layers: 10 } });
expect(findSize().text()).toMatchInterpolatedText('1.00 KiB · 10 layers');
});
- it('when total_size is missing', () => {
- mountComponent();
+ it('when totalSize is missing', () => {
+ mountComponent({ ...defaultProps, tag: { ...tag, totalSize: 0, layers: 10 } });
expect(findSize().text()).toMatchInterpolatedText(`${NOT_AVAILABLE_SIZE} · 10 layers`);
});
it('when layers are missing', () => {
- mountComponent({ ...defaultProps, tag: { ...tag, total_size: 1024, layers: null } });
+ mountComponent({ ...defaultProps, tag: { ...tag, totalSize: 1024 } });
expect(findSize().text()).toMatchInterpolatedText('1.00 KiB');
});
it('when there is 1 layer', () => {
- mountComponent({ ...defaultProps, tag: { ...tag, layers: 1 } });
+ mountComponent({ ...defaultProps, tag: { ...tag, totalSize: 0, layers: 1 } });
expect(findSize().text()).toMatchInterpolatedText(`${NOT_AVAILABLE_SIZE} · 1 layer`);
});
@@ -218,7 +218,7 @@ describe('tags list row', () => {
it('pass the correct props to time ago tooltip', () => {
mountComponent();
- expect(findTimeAgoTooltip().attributes()).toMatchObject({ time: tag.created_at });
+ expect(findTimeAgoTooltip().attributes()).toMatchObject({ time: tag.createdAt });
});
});
@@ -232,7 +232,7 @@ describe('tags list row', () => {
it('has the correct text', () => {
mountComponent();
- expect(findShortRevision().text()).toMatchInterpolatedText('Digest: 1ab51d5');
+ expect(findShortRevision().text()).toMatchInterpolatedText('Digest: 2cf3d2f');
});
it(`displays ${NOT_AVAILABLE_TEXT} when digest is missing`, () => {
@@ -260,18 +260,15 @@ describe('tags list row', () => {
});
it.each`
- destroy_path | digest
- ${'foo'} | ${null}
- ${null} | ${'foo'}
- ${null} | ${null}
- `(
- 'is disabled when destroy_path is $destroy_path and digest is $digest',
- ({ destroy_path, digest }) => {
- mountComponent({ ...defaultProps, tag: { ...tag, destroy_path, digest } });
-
- expect(findDeleteButton().attributes('disabled')).toBe('true');
- },
- );
+ canDelete | digest
+ ${true} | ${null}
+ ${false} | ${'foo'}
+ ${false} | ${null}
+ `('is disabled when canDelete is $canDelete and digest is $digest', ({ canDelete, digest }) => {
+ mountComponent({ ...defaultProps, tag: { ...tag, canDelete, digest } });
+
+ expect(findDeleteButton().attributes('disabled')).toBe('true');
+ });
it('delete event emits delete', () => {
mountComponent();
@@ -295,10 +292,10 @@ describe('tags list row', () => {
});
describe.each`
- name | finderFunction | text | icon | clipboard
- ${'published date detail'} | ${findPublishedDateDetail} | ${'Published to the bar image repository at 10:23 GMT+0000 on 2020-06-29'} | ${'clock'} | ${false}
- ${'manifest detail'} | ${findManifestDetail} | ${'Manifest digest: sha256:1ab51d519f574b636ae7788051c60239334ae8622a9fd82a0cf7bae7786dfd5c'} | ${'log'} | ${true}
- ${'configuration detail'} | ${findConfigurationDetail} | ${'Configuration digest: sha256:b118ab5b0e90b7cb5127db31d5321ac14961d097516a8e0e72084b6cdc783b43'} | ${'cloud-gear'} | ${true}
+ name | finderFunction | text | icon | clipboard
+ ${'published date detail'} | ${findPublishedDateDetail} | ${'Published to the gitlab-org/gitlab-test/rails-12009 image repository at 01:29 GMT+0000 on 2020-11-03'} | ${'clock'} | ${false}
+ ${'manifest detail'} | ${findManifestDetail} | ${'Manifest digest: sha256:2cf3d2fdac1b04a14301d47d51cb88dcd26714c74f91440eeee99ce399089062'} | ${'log'} | ${true}
+ ${'configuration detail'} | ${findConfigurationDetail} | ${'Configuration digest: sha256:c2613843ab33aabf847965442b13a8b55a56ae28837ce182627c0716eb08c02b'} | ${'cloud-gear'} | ${true}
`('$name details row', ({ finderFunction, text, icon, clipboard }) => {
it(`has ${text} as text`, () => {
expect(finderFunction().text()).toMatchInterpolatedText(text);
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js
index ebeaa8ff870..035b59731c9 100644
--- a/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js
@@ -3,12 +3,12 @@ import { GlButton } from '@gitlab/ui';
import component from '~/registry/explorer/components/details_page/tags_list.vue';
import TagsListRow from '~/registry/explorer/components/details_page/tags_list_row.vue';
import { TAGS_LIST_TITLE, REMOVE_TAGS_BUTTON_TITLE } from '~/registry/explorer/constants/index';
-import { tagsListResponse } from '../../mock_data';
+import { tagsMock } from '../../mock_data';
describe('Tags List', () => {
let wrapper;
- const tags = [...tagsListResponse.data];
- const readOnlyTags = tags.map(t => ({ ...t, destroy_path: undefined }));
+ const tags = [...tagsMock];
+ const readOnlyTags = tags.map(t => ({ ...t, canDelete: false }));
const findTagsListRow = () => wrapper.findAll(TagsListRow);
const findDeleteButton = () => wrapper.find(GlButton);
@@ -92,7 +92,7 @@ describe('Tags List', () => {
.vm.$emit('select');
findDeleteButton().vm.$emit('click');
- expect(wrapper.emitted('delete')).toEqual([[{ centos6: true }]]);
+ expect(wrapper.emitted('delete')).toEqual([[{ 'beta-24753': true }]]);
});
});
@@ -132,7 +132,7 @@ describe('Tags List', () => {
findTagsListRow()
.at(0)
.vm.$emit('delete');
- expect(wrapper.emitted('delete')).toEqual([[{ centos6: true }]]);
+ expect(wrapper.emitted('delete')).toEqual([[{ 'beta-24753': true }]]);
});
});
});
diff --git a/spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap b/spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap
index a8412e2bde9..56579847468 100644
--- a/spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap
+++ b/spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap
@@ -1,10 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Registry Group Empty state to match the default snapshot 1`] = `
-<div
- svg-path="foo"
- title="There are no container images available in this group"
->
+<div>
<p>
With the Container Registry, every project can have its own space to store its Docker images. Push at least one Docker image in one of this group's projects in order to show up here.
<gl-link-stub
diff --git a/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap b/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
index 8413e17c7b2..bab6b25cc15 100644
--- a/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
+++ b/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
@@ -1,10 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Registry Project Empty state to match the default snapshot 1`] = `
-<div
- svg-path="bazFoo"
- title="There are no container images stored for this project"
->
+<div>
<p>
With the Container Registry, every project can have its own space to store its Docker images.
<gl-link-stub
@@ -46,7 +43,7 @@ exports[`Registry Project Empty state to match the default snapshot 1`] = `
class="gl-font-monospace!"
readonly=""
type="text"
- value="docker login bar"
+ value="bazbaz"
/>
</gl-form-input-group-stub>
@@ -67,7 +64,7 @@ exports[`Registry Project Empty state to match the default snapshot 1`] = `
class="gl-font-monospace!"
readonly=""
type="text"
- value="docker build -t foo ."
+ value="foofoo"
/>
</gl-form-input-group-stub>
@@ -79,7 +76,7 @@ exports[`Registry Project Empty state to match the default snapshot 1`] = `
class="gl-font-monospace!"
readonly=""
type="text"
- value="docker push foo"
+ value="barbar"
/>
</gl-form-input-group-stub>
</div>
diff --git a/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js b/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
index 551d1eee68d..74b9ea5fd96 100644
--- a/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
@@ -2,10 +2,8 @@ import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
import { GlDropdown } from '@gitlab/ui';
import Tracking from '~/tracking';
-import * as getters from '~/registry/explorer/stores/getters';
import QuickstartDropdown from '~/registry/explorer/components/list_page/cli_commands.vue';
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
-
import {
QUICK_START,
LOGIN_COMMAND_LABEL,
@@ -14,31 +12,33 @@ import {
COPY_BUILD_TITLE,
PUSH_COMMAND_LABEL,
COPY_PUSH_TITLE,
-} from '~/registry/explorer//constants';
+} from '~/registry/explorer/constants';
+
+import { dockerCommands } from '../../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('cli_commands', () => {
let wrapper;
- let store;
+
+ const config = {
+ repositoryUrl: 'foo',
+ registryHostUrlWithPort: 'bar',
+ };
const findDropdownButton = () => wrapper.find(GlDropdown);
const findCodeInstruction = () => wrapper.findAll(CodeInstruction);
const mountComponent = () => {
- store = new Vuex.Store({
- state: {
- config: {
- repositoryUrl: 'foo',
- registryHostUrlWithPort: 'bar',
- },
- },
- getters,
- });
wrapper = mount(QuickstartDropdown, {
localVue,
- store,
+ provide() {
+ return {
+ config,
+ ...dockerCommands,
+ };
+ },
});
};
@@ -50,7 +50,6 @@ describe('cli_commands', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
- store = null;
});
it('shows the correct text on the button', () => {
@@ -67,11 +66,11 @@ describe('cli_commands', () => {
});
describe.each`
- index | labelText | titleText | getter | trackedEvent
- ${0} | ${LOGIN_COMMAND_LABEL} | ${COPY_LOGIN_TITLE} | ${'dockerLoginCommand'} | ${'click_copy_login'}
- ${1} | ${BUILD_COMMAND_LABEL} | ${COPY_BUILD_TITLE} | ${'dockerBuildCommand'} | ${'click_copy_build'}
- ${2} | ${PUSH_COMMAND_LABEL} | ${COPY_PUSH_TITLE} | ${'dockerPushCommand'} | ${'click_copy_push'}
- `('code instructions at $index', ({ index, labelText, titleText, getter, trackedEvent }) => {
+ index | labelText | titleText | command | trackedEvent
+ ${0} | ${LOGIN_COMMAND_LABEL} | ${COPY_LOGIN_TITLE} | ${dockerCommands.dockerLoginCommand} | ${'click_copy_login'}
+ ${1} | ${BUILD_COMMAND_LABEL} | ${COPY_BUILD_TITLE} | ${dockerCommands.dockerBuildCommand} | ${'click_copy_build'}
+ ${2} | ${PUSH_COMMAND_LABEL} | ${COPY_PUSH_TITLE} | ${dockerCommands.dockerPushCommand} | ${'click_copy_push'}
+ `('code instructions at $index', ({ index, labelText, titleText, command, trackedEvent }) => {
let codeInstruction;
beforeEach(() => {
@@ -85,7 +84,7 @@ describe('cli_commands', () => {
it(`has the correct props`, () => {
expect(codeInstruction.props()).toMatchObject({
label: labelText,
- instruction: store.getters[getter],
+ instruction: command,
copyText: titleText,
trackingAction: trackedEvent,
trackingLabel: 'quickstart_dropdown',
diff --git a/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js b/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js
index 2f51e875672..1ba2036dc34 100644
--- a/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js
@@ -9,24 +9,21 @@ localVue.use(Vuex);
describe('Registry Group Empty state', () => {
let wrapper;
- let store;
+ const config = {
+ noContainersImage: 'foo',
+ helpPagePath: 'baz',
+ };
beforeEach(() => {
- store = new Vuex.Store({
- state: {
- config: {
- noContainersImage: 'foo',
- helpPagePath: 'baz',
- },
- },
- });
wrapper = shallowMount(groupEmptyState, {
localVue,
- store,
stubs: {
GlEmptyState,
GlSprintf,
},
+ provide() {
+ return { config };
+ },
});
});
diff --git a/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js b/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js
index 9f7a2758ae1..b9839d92f1d 100644
--- a/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js
@@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { GlIcon, GlSprintf } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import Component from '~/registry/explorer/components/list_page/image_list_row.vue';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
@@ -11,13 +12,15 @@ import {
REMOVE_REPOSITORY_LABEL,
ASYNC_DELETE_IMAGE_ERROR_MESSAGE,
CLEANUP_TIMED_OUT_ERROR_MESSAGE,
+ IMAGE_DELETE_SCHEDULED_STATUS,
+ IMAGE_FAILED_DELETED_STATUS,
} from '~/registry/explorer/constants';
import { RouterLink } from '../../stubs';
import { imagesListResponse } from '../../mock_data';
describe('Image List Row', () => {
let wrapper;
- const item = imagesListResponse.data[0];
+ const [item] = imagesListResponse;
const findDetailsLink = () => wrapper.find('[data-testid="details-link"]');
const findTagsCount = () => wrapper.find('[data-testid="tagsCount"]');
@@ -50,13 +53,15 @@ describe('Image List Row', () => {
describe('main tooltip', () => {
it(`the title is ${ROW_SCHEDULED_FOR_DELETION}`, () => {
mountComponent();
+
const tooltip = getBinding(wrapper.element, 'gl-tooltip');
expect(tooltip).toBeDefined();
expect(tooltip.value.title).toBe(ROW_SCHEDULED_FOR_DELETION);
});
it('is disabled when item is being deleted', () => {
- mountComponent({ item: { ...item, deleting: true } });
+ mountComponent({ item: { ...item, status: IMAGE_DELETE_SCHEDULED_STATUS } });
+
const tooltip = getBinding(wrapper.element, 'gl-tooltip');
expect(tooltip.value.disabled).toBe(false);
});
@@ -65,12 +70,13 @@ describe('Image List Row', () => {
describe('image title and path', () => {
it('contains a link to the details page', () => {
mountComponent();
+
const link = findDetailsLink();
expect(link.html()).toContain(item.path);
expect(link.props('to')).toMatchObject({
name: 'details',
params: {
- id: item.id,
+ id: getIdFromGraphQLId(item.id),
},
});
});
@@ -85,16 +91,18 @@ describe('Image List Row', () => {
describe('warning icon', () => {
it.each`
- failedDelete | cleanup_policy_started_at | shown | title
- ${true} | ${true} | ${true} | ${ASYNC_DELETE_IMAGE_ERROR_MESSAGE}
- ${false} | ${true} | ${true} | ${CLEANUP_TIMED_OUT_ERROR_MESSAGE}
- ${false} | ${false} | ${false} | ${''}
+ status | expirationPolicyStartedAt | shown | title
+ ${IMAGE_FAILED_DELETED_STATUS} | ${true} | ${true} | ${ASYNC_DELETE_IMAGE_ERROR_MESSAGE}
+ ${''} | ${true} | ${true} | ${CLEANUP_TIMED_OUT_ERROR_MESSAGE}
+ ${''} | ${false} | ${false} | ${''}
`(
- 'when failedDelete is $failedDelete and cleanup_policy_started_at is $cleanup_policy_started_at',
- ({ cleanup_policy_started_at, failedDelete, shown, title }) => {
- mountComponent({ item: { ...item, failedDelete, cleanup_policy_started_at } });
+ 'when status is $status and expirationPolicyStartedAt is $expirationPolicyStartedAt',
+ ({ expirationPolicyStartedAt, status, shown, title }) => {
+ mountComponent({ item: { ...item, status, expirationPolicyStartedAt } });
+
const icon = findWarningIcon();
expect(icon.exists()).toBe(shown);
+
if (shown) {
const tooltip = getBinding(icon.element, 'gl-tooltip');
expect(tooltip.value.title).toBe(title);
@@ -112,30 +120,33 @@ describe('Image List Row', () => {
it('has the correct props', () => {
mountComponent();
- expect(findDeleteBtn().attributes()).toMatchObject({
+
+ expect(findDeleteBtn().props()).toMatchObject({
title: REMOVE_REPOSITORY_LABEL,
- tooltipdisabled: `${Boolean(item.destroy_path)}`,
- tooltiptitle: LIST_DELETE_BUTTON_DISABLED,
+ tooltipDisabled: item.canDelete,
+ tooltipTitle: LIST_DELETE_BUTTON_DISABLED,
});
});
it('emits a delete event', () => {
mountComponent();
+
findDeleteBtn().vm.$emit('delete');
expect(wrapper.emitted('delete')).toEqual([[item]]);
});
it.each`
- destroy_path | deleting | state
- ${null} | ${null} | ${'true'}
- ${null} | ${true} | ${'true'}
- ${'foo'} | ${true} | ${'true'}
- ${'foo'} | ${false} | ${undefined}
+ canDelete | status | state
+ ${false} | ${''} | ${true}
+ ${false} | ${IMAGE_DELETE_SCHEDULED_STATUS} | ${true}
+ ${true} | ${IMAGE_DELETE_SCHEDULED_STATUS} | ${true}
+ ${true} | ${''} | ${false}
`(
- 'disabled is $state when destroy_path is $destroy_path and deleting is $deleting',
- ({ destroy_path, deleting, state }) => {
- mountComponent({ item: { ...item, destroy_path, deleting } });
- expect(findDeleteBtn().attributes('disabled')).toBe(state);
+ 'disabled is $state when canDelete is $canDelete and status is $status',
+ ({ canDelete, status, state }) => {
+ mountComponent({ item: { ...item, canDelete, status } });
+
+ expect(findDeleteBtn().props('disabled')).toBe(state);
},
);
});
@@ -155,11 +166,13 @@ describe('Image List Row', () => {
describe('tags count text', () => {
it('with one tag in the image', () => {
- mountComponent({ item: { ...item, tags_count: 1 } });
+ mountComponent({ item: { ...item, tagsCount: 1 } });
+
expect(findTagsCount().text()).toMatchInterpolatedText('1 Tag');
});
it('with more than one tag in the image', () => {
- mountComponent({ item: { ...item, tags_count: 3 } });
+ mountComponent({ item: { ...item, tagsCount: 3 } });
+
expect(findTagsCount().text()).toMatchInterpolatedText('3 Tags');
});
});
diff --git a/spec/frontend/registry/explorer/components/list_page/image_list_spec.js b/spec/frontend/registry/explorer/components/list_page/image_list_spec.js
index 03ba6ad7f80..54befc9973a 100644
--- a/spec/frontend/registry/explorer/components/list_page/image_list_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/image_list_spec.js
@@ -1,29 +1,25 @@
import { shallowMount } from '@vue/test-utils';
-import { GlPagination } from '@gitlab/ui';
+import { GlKeysetPagination } from '@gitlab/ui';
import Component from '~/registry/explorer/components/list_page/image_list.vue';
import ImageListRow from '~/registry/explorer/components/list_page/image_list_row.vue';
-import { imagesListResponse, imagePagination } from '../../mock_data';
+import { imagesListResponse, pageInfo as defaultPageInfo } from '../../mock_data';
describe('Image List', () => {
let wrapper;
const findRow = () => wrapper.findAll(ImageListRow);
- const findPagination = () => wrapper.find(GlPagination);
+ const findPagination = () => wrapper.find(GlKeysetPagination);
- const mountComponent = () => {
+ const mountComponent = (pageInfo = defaultPageInfo) => {
wrapper = shallowMount(Component, {
propsData: {
- images: imagesListResponse.data,
- pagination: imagePagination,
+ images: imagesListResponse,
+ pageInfo,
},
});
};
- beforeEach(() => {
- mountComponent();
- });
-
afterEach(() => {
wrapper.destroy();
wrapper = null;
@@ -31,10 +27,14 @@ describe('Image List', () => {
describe('list', () => {
it('contains one list element for each image', () => {
- expect(findRow().length).toBe(imagesListResponse.data.length);
+ mountComponent();
+
+ expect(findRow().length).toBe(imagesListResponse.length);
});
it('when delete event is emitted on the row it emits up a delete event', () => {
+ mountComponent();
+
findRow()
.at(0)
.vm.$emit('delete', 'foo');
@@ -44,19 +44,41 @@ describe('Image List', () => {
describe('pagination', () => {
it('exists', () => {
+ mountComponent();
+
expect(findPagination().exists()).toBe(true);
});
- it('is wired to the correct pagination props', () => {
- const pagination = findPagination();
- expect(pagination.props('perPage')).toBe(imagePagination.perPage);
- expect(pagination.props('totalItems')).toBe(imagePagination.total);
- expect(pagination.props('value')).toBe(imagePagination.page);
+ it.each`
+ hasNextPage | hasPreviousPage | isVisible
+ ${true} | ${true} | ${true}
+ ${true} | ${false} | ${true}
+ ${false} | ${true} | ${true}
+ `(
+ 'when hasNextPage is $hasNextPage and hasPreviousPage is $hasPreviousPage: is $isVisible that the component is visible',
+ ({ hasNextPage, hasPreviousPage, isVisible }) => {
+ mountComponent({ hasNextPage, hasPreviousPage });
+
+ expect(findPagination().exists()).toBe(isVisible);
+ expect(findPagination().props('hasPreviousPage')).toBe(hasPreviousPage);
+ expect(findPagination().props('hasNextPage')).toBe(hasNextPage);
+ },
+ );
+
+ it('emits "prev-page" when the user clicks the back page button', () => {
+ mountComponent({ hasPreviousPage: true });
+
+ findPagination().vm.$emit('prev');
+
+ expect(wrapper.emitted('prev-page')).toEqual([[]]);
});
- it('emits a pageChange event when the page change', () => {
- findPagination().vm.$emit(GlPagination.model.event, 2);
- expect(wrapper.emitted('pageChange')).toEqual([[2]]);
+ it('emits "next-page" when the user clicks the forward page button', () => {
+ mountComponent({ hasNextPage: true });
+
+ findPagination().vm.$emit('next');
+
+ expect(wrapper.emitted('next-page')).toEqual([[]]);
});
});
});
diff --git a/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js b/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js
index 73746c545cb..3a27cf1923c 100644
--- a/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js
@@ -3,36 +3,35 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
import { GlEmptyState } from '../../stubs';
import projectEmptyState from '~/registry/explorer/components/list_page/project_empty_state.vue';
-import * as getters from '~/registry/explorer/stores/getters';
+import { dockerCommands } from '../../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('Registry Project Empty state', () => {
let wrapper;
- let store;
+ const config = {
+ repositoryUrl: 'foo',
+ registryHostUrlWithPort: 'bar',
+ helpPagePath: 'baz',
+ twoFactorAuthHelpLink: 'barBaz',
+ personalAccessTokensHelpLink: 'fooBaz',
+ noContainersImage: 'bazFoo',
+ };
beforeEach(() => {
- store = new Vuex.Store({
- state: {
- config: {
- repositoryUrl: 'foo',
- registryHostUrlWithPort: 'bar',
- helpPagePath: 'baz',
- twoFactorAuthHelpLink: 'barBaz',
- personalAccessTokensHelpLink: 'fooBaz',
- noContainersImage: 'bazFoo',
- },
- },
- getters,
- });
wrapper = shallowMount(projectEmptyState, {
localVue,
- store,
stubs: {
GlEmptyState,
GlSprintf,
},
+ provide() {
+ return {
+ config,
+ ...dockerCommands,
+ };
+ },
});
});
diff --git a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js b/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
index d730bfcde24..fb0b98ba004 100644
--- a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
+++ b/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
@@ -32,10 +32,6 @@ describe('Registry Breadcrumb', () => {
{ name: 'baz', meta: { nameGenerator } },
];
- const state = {
- imageDetails: { foo: 'bar' },
- };
-
const findDivider = () => wrapper.find('.js-divider');
const findRootRoute = () => wrapper.find({ ref: 'rootRouteLink' });
const findChildRoute = () => wrapper.find({ ref: 'childRouteLink' });
@@ -56,9 +52,6 @@ describe('Registry Breadcrumb', () => {
routes,
},
},
- $store: {
- state,
- },
},
});
};
@@ -87,7 +80,6 @@ describe('Registry Breadcrumb', () => {
});
it('the link text is calculated by nameGenerator', () => {
- expect(nameGenerator).toHaveBeenCalledWith(state);
expect(nameGenerator).toHaveBeenCalledTimes(1);
});
});
@@ -111,7 +103,6 @@ describe('Registry Breadcrumb', () => {
});
it('the link text is calculated by nameGenerator', () => {
- expect(nameGenerator).toHaveBeenCalledWith(state);
expect(nameGenerator).toHaveBeenCalledTimes(2);
});
});