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.snap63
-rw-r--r--spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js116
-rw-r--r--spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js79
-rw-r--r--spec/frontend/registry/explorer/components/details_page/details_header_spec.js32
-rw-r--r--spec/frontend/registry/explorer/components/details_page/empty_tags_state.js43
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js49
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_table_spec.js286
-rw-r--r--spec/frontend/registry/explorer/components/image_list_spec.js74
-rw-r--r--spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap (renamed from spec/frontend/registry/explorer/components/__snapshots__/group_empty_state_spec.js.snap)0
-rw-r--r--spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap (renamed from spec/frontend/registry/explorer/components/__snapshots__/project_empty_state_spec.js.snap)2
-rw-r--r--spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js (renamed from spec/frontend/registry/explorer/components/quickstart_dropdown_spec.js)4
-rw-r--r--spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js (renamed from spec/frontend/registry/explorer/components/group_empty_state_spec.js)4
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js140
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_spec.js62
-rw-r--r--spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js (renamed from spec/frontend/registry/explorer/components/project_empty_state_spec.js)4
-rw-r--r--spec/frontend/registry/explorer/components/list_page/registry_header_spec.js221
-rw-r--r--spec/frontend/registry/explorer/components/project_policy_alert_spec.js132
17 files changed, 1098 insertions, 213 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
new file mode 100644
index 00000000000..aeb49f88770
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap
@@ -0,0 +1,63 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`TagsLoader component has the correct markup 1`] = `
+<div>
+ <div
+ preserve-aspect-ratio="xMinYMax meet"
+ >
+ <rect
+ height="15"
+ rx="4"
+ width="15"
+ x="0"
+ y="12.5"
+ />
+
+ <rect
+ height="20"
+ rx="4"
+ width="250"
+ x="25"
+ y="10"
+ />
+
+ <circle
+ cx="290"
+ cy="20"
+ r="10"
+ />
+
+ <rect
+ height="20"
+ rx="4"
+ width="100"
+ x="315"
+ y="10"
+ />
+
+ <rect
+ height="20"
+ rx="4"
+ width="100"
+ x="500"
+ y="10"
+ />
+
+ <rect
+ height="20"
+ rx="4"
+ width="100"
+ x="630"
+ y="10"
+ />
+
+ <rect
+ height="40"
+ rx="4"
+ width="40"
+ x="960"
+ y="0"
+ />
+ </div>
+</div>
+`;
diff --git a/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js b/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js
new file mode 100644
index 00000000000..5d54986978b
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js
@@ -0,0 +1,116 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlAlert, GlSprintf, GlLink } from '@gitlab/ui';
+import component from '~/registry/explorer/components/details_page/delete_alert.vue';
+import {
+ DELETE_TAG_SUCCESS_MESSAGE,
+ DELETE_TAG_ERROR_MESSAGE,
+ DELETE_TAGS_SUCCESS_MESSAGE,
+ DELETE_TAGS_ERROR_MESSAGE,
+ ADMIN_GARBAGE_COLLECTION_TIP,
+} from '~/registry/explorer/constants';
+
+describe('Delete alert', () => {
+ let wrapper;
+
+ const findAlert = () => wrapper.find(GlAlert);
+ const findLink = () => wrapper.find(GlLink);
+
+ const mountComponent = propsData => {
+ wrapper = shallowMount(component, { stubs: { GlSprintf }, propsData });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when deleteAlertType is null', () => {
+ it('does not show the alert', () => {
+ mountComponent();
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ describe('when deleteAlertType is not null', () => {
+ describe('success states', () => {
+ describe.each`
+ deleteAlertType | message
+ ${'success_tag'} | ${DELETE_TAG_SUCCESS_MESSAGE}
+ ${'success_tags'} | ${DELETE_TAGS_SUCCESS_MESSAGE}
+ `('when deleteAlertType is $deleteAlertType', ({ deleteAlertType, message }) => {
+ it('alert exists', () => {
+ mountComponent({ deleteAlertType });
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ describe('when the user is an admin', () => {
+ beforeEach(() => {
+ mountComponent({
+ deleteAlertType,
+ isAdmin: true,
+ garbageCollectionHelpPagePath: 'foo',
+ });
+ });
+
+ it(`alert title is ${message}`, () => {
+ expect(findAlert().attributes('title')).toBe(message);
+ });
+
+ it('alert body contains admin tip', () => {
+ expect(findAlert().text()).toMatchInterpolatedText(ADMIN_GARBAGE_COLLECTION_TIP);
+ });
+
+ it('alert body contains link', () => {
+ const alertLink = findLink();
+ expect(alertLink.exists()).toBe(true);
+ expect(alertLink.attributes('href')).toBe('foo');
+ });
+ });
+
+ describe('when the user is not an admin', () => {
+ it('alert exist and text is appropriate', () => {
+ mountComponent({ deleteAlertType });
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(message);
+ });
+ });
+ });
+ });
+ describe('error states', () => {
+ describe.each`
+ deleteAlertType | message
+ ${'danger_tag'} | ${DELETE_TAG_ERROR_MESSAGE}
+ ${'danger_tags'} | ${DELETE_TAGS_ERROR_MESSAGE}
+ `('when deleteAlertType is $deleteAlertType', ({ deleteAlertType, message }) => {
+ it('alert exists', () => {
+ mountComponent({ deleteAlertType });
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ describe('when the user is an admin', () => {
+ it('alert exist and text is appropriate', () => {
+ mountComponent({ deleteAlertType });
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(message);
+ });
+ });
+
+ describe('when the user is not an admin', () => {
+ it('alert exist and text is appropriate', () => {
+ mountComponent({ deleteAlertType });
+ expect(findAlert().exists()).toBe(true);
+ expect(findAlert().text()).toBe(message);
+ });
+ });
+ });
+ });
+
+ describe('dismissing alert', () => {
+ it('GlAlert dismiss event triggers a change event', () => {
+ mountComponent({ deleteAlertType: 'success_tags' });
+ findAlert().vm.$emit('dismiss');
+ expect(wrapper.emitted('change')).toEqual([[null]]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js b/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js
new file mode 100644
index 00000000000..c77f7a54d34
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js
@@ -0,0 +1,79 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlSprintf } from '@gitlab/ui';
+import component from '~/registry/explorer/components/details_page/delete_modal.vue';
+import {
+ REMOVE_TAG_CONFIRMATION_TEXT,
+ REMOVE_TAGS_CONFIRMATION_TEXT,
+} from '~/registry/explorer/constants';
+import { GlModal } from '../../stubs';
+
+describe('Delete Modal', () => {
+ let wrapper;
+
+ const findModal = () => wrapper.find(GlModal);
+ const findDescription = () => wrapper.find('[data-testid="description"]');
+
+ const mountComponent = propsData => {
+ wrapper = shallowMount(component, {
+ propsData,
+ stubs: {
+ GlSprintf,
+ GlModal,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('contains a GlModal', () => {
+ mountComponent();
+ expect(findModal().exists()).toBe(true);
+ });
+
+ describe('events', () => {
+ it.each`
+ glEvent | localEvent
+ ${'ok'} | ${'confirmDelete'}
+ ${'cancel'} | ${'cancelDelete'}
+ `('GlModal $glEvent emits $localEvent', ({ glEvent, localEvent }) => {
+ mountComponent();
+ findModal().vm.$emit(glEvent);
+ expect(wrapper.emitted(localEvent)).toBeTruthy();
+ });
+ });
+
+ describe('methods', () => {
+ it('show calls gl-modal show', () => {
+ mountComponent();
+ wrapper.vm.show();
+ expect(GlModal.methods.show).toHaveBeenCalled();
+ });
+ });
+
+ describe('itemsToBeDeleted contains one element', () => {
+ beforeEach(() => {
+ mountComponent({ itemsToBeDeleted: [{ path: 'foo' }] });
+ });
+ it(`has the correct description`, () => {
+ expect(findDescription().text()).toBe(REMOVE_TAG_CONFIRMATION_TEXT.replace('%{item}', 'foo'));
+ });
+ it('has the correct action', () => {
+ expect(wrapper.text()).toContain('Remove tag');
+ });
+ });
+
+ describe('itemsToBeDeleted contains more than element', () => {
+ beforeEach(() => {
+ mountComponent({ itemsToBeDeleted: [{ path: 'foo' }, { path: 'bar' }] });
+ });
+ it(`has the correct description`, () => {
+ expect(findDescription().text()).toBe(REMOVE_TAGS_CONFIRMATION_TEXT.replace('%{item}', '2'));
+ });
+ it('has the correct action', () => {
+ expect(wrapper.text()).toContain('Remove tags');
+ });
+ });
+});
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
new file mode 100644
index 00000000000..cb31efa428f
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
@@ -0,0 +1,32 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlSprintf } from '@gitlab/ui';
+import component from '~/registry/explorer/components/details_page/details_header.vue';
+import { DETAILS_PAGE_TITLE } from '~/registry/explorer/constants';
+
+describe('Details Header', () => {
+ let wrapper;
+
+ const mountComponent = propsData => {
+ wrapper = shallowMount(component, {
+ propsData,
+ stubs: {
+ GlSprintf,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('has the correct title ', () => {
+ mountComponent();
+ expect(wrapper.text()).toMatchInterpolatedText(DETAILS_PAGE_TITLE);
+ });
+
+ it('shows imageName in the title', () => {
+ mountComponent({ imageName: 'foo' });
+ expect(wrapper.text()).toContain('foo');
+ });
+});
diff --git a/spec/frontend/registry/explorer/components/details_page/empty_tags_state.js b/spec/frontend/registry/explorer/components/details_page/empty_tags_state.js
new file mode 100644
index 00000000000..da80c75a26a
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/details_page/empty_tags_state.js
@@ -0,0 +1,43 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlEmptyState } from '@gitlab/ui';
+import component from '~/registry/explorer/components/details_page/empty_tags_state.vue';
+import {
+ EMPTY_IMAGE_REPOSITORY_TITLE,
+ EMPTY_IMAGE_REPOSITORY_MESSAGE,
+} from '~/registry/explorer/constants';
+
+describe('EmptyTagsState component', () => {
+ let wrapper;
+
+ const findEmptyState = () => wrapper.find(GlEmptyState);
+
+ const mountComponent = () => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ GlEmptyState,
+ },
+ propsData: {
+ noContainersImage: 'foo',
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('contains gl-empty-state', () => {
+ mountComponent();
+ expect(findEmptyState().exist()).toBe(true);
+ });
+
+ it('has the correct props', () => {
+ mountComponent();
+ expect(findEmptyState().props()).toMatchObject({
+ title: EMPTY_IMAGE_REPOSITORY_TITLE,
+ description: EMPTY_IMAGE_REPOSITORY_MESSAGE,
+ svgPath: 'foo',
+ });
+ });
+});
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js
new file mode 100644
index 00000000000..b27d3e2c042
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js
@@ -0,0 +1,49 @@
+import { shallowMount } from '@vue/test-utils';
+import component from '~/registry/explorer/components/details_page/tags_loader.vue';
+import { GlSkeletonLoader } from '../../stubs';
+
+describe('TagsLoader component', () => {
+ let wrapper;
+
+ const findGlSkeletonLoaders = () => wrapper.findAll(GlSkeletonLoader);
+
+ const mountComponent = () => {
+ wrapper = shallowMount(component, {
+ stubs: {
+ GlSkeletonLoader,
+ },
+ // set the repeat to 1 to avoid a long and verbose snapshot
+ loader: {
+ ...component.loader,
+ repeat: 1,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('produces the correct amount of loaders ', () => {
+ mountComponent();
+ expect(findGlSkeletonLoaders().length).toBe(1);
+ });
+
+ it('has the correct props', () => {
+ mountComponent();
+ expect(
+ findGlSkeletonLoaders()
+ .at(0)
+ .props(),
+ ).toMatchObject({
+ width: component.loader.width,
+ height: component.loader.height,
+ });
+ });
+
+ it('has the correct markup', () => {
+ mountComponent();
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_table_spec.js b/spec/frontend/registry/explorer/components/details_page/tags_table_spec.js
new file mode 100644
index 00000000000..a60a362dcfe
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/details_page/tags_table_spec.js
@@ -0,0 +1,286 @@
+import { mount } from '@vue/test-utils';
+import stubChildren from 'helpers/stub_children';
+import component from '~/registry/explorer/components/details_page/tags_table.vue';
+import { tagsListResponse } from '../../mock_data';
+
+describe('tags_table', () => {
+ let wrapper;
+ const tags = [...tagsListResponse.data];
+
+ const findMainCheckbox = () => wrapper.find('[data-testid="mainCheckbox"]');
+ const findFirstRowItem = testid => wrapper.find(`[data-testid="${testid}"]`);
+ const findBulkDeleteButton = () => wrapper.find('[data-testid="bulkDeleteButton"]');
+ const findAllDeleteButtons = () => wrapper.findAll('[data-testid="singleDeleteButton"]');
+ const findAllCheckboxes = () => wrapper.findAll('[data-testid="rowCheckbox"]');
+ const findCheckedCheckboxes = () => findAllCheckboxes().filter(c => c.attributes('checked'));
+ const findFirsTagColumn = () => wrapper.find('.js-tag-column');
+ const findFirstTagNameText = () => wrapper.find('[data-testid="rowNameText"]');
+
+ const findLoaderSlot = () => wrapper.find('[data-testid="loaderSlot"]');
+ const findEmptySlot = () => wrapper.find('[data-testid="emptySlot"]');
+
+ const mountComponent = (propsData = { tags, isDesktop: true }) => {
+ wrapper = mount(component, {
+ stubs: {
+ ...stubChildren(component),
+ GlTable: false,
+ },
+ propsData,
+ slots: {
+ loader: '<div data-testid="loaderSlot"></div>',
+ empty: '<div data-testid="emptySlot"></div>',
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it.each([
+ 'rowCheckbox',
+ 'rowName',
+ 'rowShortRevision',
+ 'rowSize',
+ 'rowTime',
+ 'singleDeleteButton',
+ ])('%s exist in the table', element => {
+ mountComponent();
+
+ expect(findFirstRowItem(element).exists()).toBe(true);
+ });
+
+ describe('header checkbox', () => {
+ it('exists', () => {
+ mountComponent();
+ expect(findMainCheckbox().exists()).toBe(true);
+ });
+
+ it('if selected selects all the rows', () => {
+ mountComponent();
+ findMainCheckbox().vm.$emit('change');
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findMainCheckbox().attributes('checked')).toBeTruthy();
+ expect(findCheckedCheckboxes()).toHaveLength(tags.length);
+ });
+ });
+
+ it('if deselect deselects all the row', () => {
+ mountComponent();
+ findMainCheckbox().vm.$emit('change');
+ return wrapper.vm
+ .$nextTick()
+ .then(() => {
+ expect(findMainCheckbox().attributes('checked')).toBeTruthy();
+ findMainCheckbox().vm.$emit('change');
+ return wrapper.vm.$nextTick();
+ })
+ .then(() => {
+ expect(findMainCheckbox().attributes('checked')).toBe(undefined);
+ expect(findCheckedCheckboxes()).toHaveLength(0);
+ });
+ });
+ });
+
+ describe('row checkbox', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('selecting and deselecting the checkbox works as intended', () => {
+ findFirstRowItem('rowCheckbox').vm.$emit('change');
+ return wrapper.vm
+ .$nextTick()
+ .then(() => {
+ expect(wrapper.vm.selectedItems).toEqual([tags[0].name]);
+ expect(findFirstRowItem('rowCheckbox').attributes('checked')).toBeTruthy();
+ findFirstRowItem('rowCheckbox').vm.$emit('change');
+ return wrapper.vm.$nextTick();
+ })
+ .then(() => {
+ expect(wrapper.vm.selectedItems.length).toBe(0);
+ expect(findFirstRowItem('rowCheckbox').attributes('checked')).toBe(undefined);
+ });
+ });
+ });
+
+ describe('header delete button', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('exists', () => {
+ expect(findBulkDeleteButton().exists()).toBe(true);
+ });
+
+ it('is disabled if no item is selected', () => {
+ expect(findBulkDeleteButton().attributes('disabled')).toBe('true');
+ });
+
+ it('is enabled if at least one item is selected', () => {
+ expect(findBulkDeleteButton().attributes('disabled')).toBe('true');
+ findFirstRowItem('rowCheckbox').vm.$emit('change');
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findBulkDeleteButton().attributes('disabled')).toBeFalsy();
+ });
+ });
+
+ describe('on click', () => {
+ it('when one item is selected', () => {
+ findFirstRowItem('rowCheckbox').vm.$emit('change');
+ findBulkDeleteButton().vm.$emit('click');
+ expect(wrapper.emitted('delete')).toEqual([[['centos6']]]);
+ });
+
+ it('when multiple items are selected', () => {
+ findMainCheckbox().vm.$emit('change');
+ findBulkDeleteButton().vm.$emit('click');
+
+ expect(wrapper.emitted('delete')).toEqual([[tags.map(t => t.name)]]);
+ });
+ });
+ });
+
+ describe('row delete button', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('exists', () => {
+ expect(
+ findAllDeleteButtons()
+ .at(0)
+ .exists(),
+ ).toBe(true);
+ });
+
+ it('is disabled if the item has no destroy_path', () => {
+ expect(
+ findAllDeleteButtons()
+ .at(1)
+ .attributes('disabled'),
+ ).toBe('true');
+ });
+
+ it('on click', () => {
+ findAllDeleteButtons()
+ .at(0)
+ .vm.$emit('click');
+
+ expect(wrapper.emitted('delete')).toEqual([[['centos6']]]);
+ });
+ });
+
+ describe('name cell', () => {
+ it('tag column has a tooltip with the tag name', () => {
+ mountComponent();
+ expect(findFirstTagNameText().attributes('title')).toBe(tagsListResponse.data[0].name);
+ });
+
+ describe('on desktop viewport', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('table header has class w-25', () => {
+ expect(findFirsTagColumn().classes()).toContain('w-25');
+ });
+
+ it('tag column has the mw-m class', () => {
+ expect(findFirstRowItem('rowName').classes()).toContain('mw-m');
+ });
+ });
+
+ describe('on mobile viewport', () => {
+ beforeEach(() => {
+ mountComponent({ tags, isDesktop: false });
+ });
+
+ it('table header does not have class w-25', () => {
+ expect(findFirsTagColumn().classes()).not.toContain('w-25');
+ });
+
+ it('tag column has the gl-justify-content-end class', () => {
+ expect(findFirstRowItem('rowName').classes()).toContain('gl-justify-content-end');
+ });
+ });
+ });
+
+ describe('last updated cell', () => {
+ let timeCell;
+
+ beforeEach(() => {
+ mountComponent();
+ timeCell = findFirstRowItem('rowTime');
+ });
+
+ it('displays the time in string format', () => {
+ expect(timeCell.text()).toBe('2 years ago');
+ });
+
+ it('has a tooltip timestamp', () => {
+ expect(timeCell.attributes('title')).toBe('Sep 19, 2017 1:45pm GMT+0000');
+ });
+ });
+
+ describe('empty state slot', () => {
+ describe('when the table is empty', () => {
+ beforeEach(() => {
+ mountComponent({ tags: [], isDesktop: true });
+ });
+
+ it('does not show table rows', () => {
+ expect(findFirstTagNameText().exists()).toBe(false);
+ });
+
+ it('has the empty state slot', () => {
+ expect(findEmptySlot().exists()).toBe(true);
+ });
+ });
+
+ describe('when the table is not empty', () => {
+ beforeEach(() => {
+ mountComponent({ tags, isDesktop: true });
+ });
+
+ it('does show table rows', () => {
+ expect(findFirstTagNameText().exists()).toBe(true);
+ });
+
+ it('does not show the empty state', () => {
+ expect(findEmptySlot().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('loader slot', () => {
+ describe('when the data is loading', () => {
+ beforeEach(() => {
+ mountComponent({ isLoading: true, tags });
+ });
+
+ it('show the loader', () => {
+ expect(findLoaderSlot().exists()).toBe(true);
+ });
+
+ it('does not show the table rows', () => {
+ expect(findFirstTagNameText().exists()).toBe(false);
+ });
+ });
+
+ describe('when the data is not loading', () => {
+ beforeEach(() => {
+ mountComponent({ isLoading: false, tags });
+ });
+
+ it('does not show the loader', () => {
+ expect(findLoaderSlot().exists()).toBe(false);
+ });
+
+ it('shows the table rows', () => {
+ expect(findFirstTagNameText().exists()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/registry/explorer/components/image_list_spec.js b/spec/frontend/registry/explorer/components/image_list_spec.js
deleted file mode 100644
index 12f0fbe0c87..00000000000
--- a/spec/frontend/registry/explorer/components/image_list_spec.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlPagination } from '@gitlab/ui';
-import Component from '~/registry/explorer/components/image_list.vue';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import { RouterLink } from '../stubs';
-import { imagesListResponse, imagePagination } from '../mock_data';
-
-describe('Image List', () => {
- let wrapper;
-
- const firstElement = imagesListResponse.data[0];
-
- const findDeleteBtn = () => wrapper.find('[data-testid="deleteImageButton"]');
- const findRowItems = () => wrapper.findAll('[data-testid="rowItem"]');
- const findDetailsLink = () => wrapper.find('[data-testid="detailsLink"]');
- const findClipboardButton = () => wrapper.find(ClipboardButton);
- const findPagination = () => wrapper.find(GlPagination);
-
- const mountComponent = () => {
- wrapper = shallowMount(Component, {
- stubs: {
- RouterLink,
- },
- propsData: {
- images: imagesListResponse.data,
- pagination: imagePagination,
- },
- });
- };
-
- beforeEach(() => {
- mountComponent();
- });
-
- it('contains one list element for each image', () => {
- expect(findRowItems().length).toBe(imagesListResponse.data.length);
- });
-
- it('contains a link to the details page', () => {
- const link = findDetailsLink();
- expect(link.html()).toContain(firstElement.path);
- expect(link.props('to').name).toBe('details');
- });
-
- it('contains a clipboard button', () => {
- const button = findClipboardButton();
- expect(button.exists()).toBe(true);
- expect(button.props('text')).toBe(firstElement.location);
- expect(button.props('title')).toBe(firstElement.location);
- });
-
- it('should be possible to delete a repo', () => {
- const deleteBtn = findDeleteBtn();
- expect(deleteBtn.exists()).toBe(true);
- });
-
- describe('pagination', () => {
- it('exists', () => {
- 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('emits a pageChange event when the page change', () => {
- wrapper.setData({ currentPage: 2 });
- expect(wrapper.emitted('pageChange')).toEqual([[2]]);
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/__snapshots__/group_empty_state_spec.js.snap b/spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap
index 3761369c944..3761369c944 100644
--- a/spec/frontend/registry/explorer/components/__snapshots__/group_empty_state_spec.js.snap
+++ b/spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap
diff --git a/spec/frontend/registry/explorer/components/__snapshots__/project_empty_state_spec.js.snap b/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
index 19767aefd1a..d8ec9c3ca4d 100644
--- a/spec/frontend/registry/explorer/components/__snapshots__/project_empty_state_spec.js.snap
+++ b/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
@@ -19,7 +19,7 @@ exports[`Registry Project Empty state to match the default snapshot 1`] = `
</p>
<h5>
- Quick Start
+ CLI Commands
</h5>
<p
diff --git a/spec/frontend/registry/explorer/components/quickstart_dropdown_spec.js b/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
index 0c3baefbc58..a556be12089 100644
--- a/spec/frontend/registry/explorer/components/quickstart_dropdown_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
@@ -3,7 +3,7 @@ import { mount, createLocalVue } from '@vue/test-utils';
import { GlDropdown, GlFormGroup, GlFormInputGroup } from '@gitlab/ui';
import Tracking from '~/tracking';
import * as getters from '~/registry/explorer/stores/getters';
-import QuickstartDropdown from '~/registry/explorer/components/quickstart_dropdown.vue';
+import QuickstartDropdown from '~/registry/explorer/components/list_page/cli_commands.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import {
@@ -19,7 +19,7 @@ import {
const localVue = createLocalVue();
localVue.use(Vuex);
-describe('quickstart_dropdown', () => {
+describe('cli_commands', () => {
let wrapper;
let store;
diff --git a/spec/frontend/registry/explorer/components/group_empty_state_spec.js b/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js
index 1b4de534317..2f51e875672 100644
--- a/spec/frontend/registry/explorer/components/group_empty_state_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js
@@ -1,8 +1,8 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
-import { GlEmptyState } from '../stubs';
-import groupEmptyState from '~/registry/explorer/components/group_empty_state.vue';
+import { GlEmptyState } from '../../stubs';
+import groupEmptyState from '~/registry/explorer/components/list_page/group_empty_state.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
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
new file mode 100644
index 00000000000..78de35ae1dc
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js
@@ -0,0 +1,140 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlIcon, GlSprintf } from '@gitlab/ui';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import Component from '~/registry/explorer/components/list_page/image_list_row.vue';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import {
+ ROW_SCHEDULED_FOR_DELETION,
+ LIST_DELETE_BUTTON_DISABLED,
+} 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 findDeleteBtn = () => wrapper.find('[data-testid="deleteImageButton"]');
+ const findDetailsLink = () => wrapper.find('[data-testid="detailsLink"]');
+ const findTagsCount = () => wrapper.find('[data-testid="tagsCount"]');
+ const findDeleteButtonWrapper = () => wrapper.find('[data-testid="deleteButtonWrapper"]');
+ const findClipboardButton = () => wrapper.find(ClipboardButton);
+
+ const mountComponent = props => {
+ wrapper = shallowMount(Component, {
+ stubs: {
+ RouterLink,
+ GlSprintf,
+ },
+ propsData: {
+ item,
+ ...props,
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ 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 } });
+ const tooltip = getBinding(wrapper.element, 'gl-tooltip');
+ expect(tooltip.value.disabled).toBe(false);
+ });
+ });
+
+ 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').name).toBe('details');
+ });
+
+ it('contains a clipboard button', () => {
+ mountComponent();
+ const button = findClipboardButton();
+ expect(button.exists()).toBe(true);
+ expect(button.props('text')).toBe(item.location);
+ expect(button.props('title')).toBe(item.location);
+ });
+ });
+
+ describe('delete button wrapper', () => {
+ it('has a tooltip', () => {
+ mountComponent();
+ const tooltip = getBinding(findDeleteButtonWrapper().element, 'gl-tooltip');
+ expect(tooltip).toBeDefined();
+ expect(tooltip.value.title).toBe(LIST_DELETE_BUTTON_DISABLED);
+ });
+ it('tooltip is enabled when destroy_path is falsy', () => {
+ mountComponent({ item: { ...item, destroy_path: null } });
+ const tooltip = getBinding(findDeleteButtonWrapper().element, 'gl-tooltip');
+ expect(tooltip.value.disabled).toBeFalsy();
+ });
+ });
+
+ describe('delete button', () => {
+ it('exists', () => {
+ mountComponent();
+ expect(findDeleteBtn().exists()).toBe(true);
+ });
+
+ it('emits a delete event', () => {
+ mountComponent();
+ findDeleteBtn().vm.$emit('click');
+ expect(wrapper.emitted('delete')).toEqual([[item]]);
+ });
+
+ it.each`
+ destroy_path | deleting | state
+ ${null} | ${null} | ${'true'}
+ ${null} | ${true} | ${'true'}
+ ${'foo'} | ${true} | ${'true'}
+ ${'foo'} | ${false} | ${undefined}
+ `(
+ '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);
+ },
+ );
+ });
+
+ describe('tags count', () => {
+ it('exists', () => {
+ mountComponent();
+ expect(findTagsCount().exists()).toBe(true);
+ });
+
+ it('contains a tag icon', () => {
+ mountComponent();
+ const icon = findTagsCount().find(GlIcon);
+ expect(icon.exists()).toBe(true);
+ expect(icon.props('name')).toBe('tag');
+ });
+
+ describe('tags count text', () => {
+ it('with one tag in the image', () => {
+ mountComponent({ item: { ...item, tags_count: 1 } });
+ expect(findTagsCount().text()).toMatchInterpolatedText('1 Tag');
+ });
+ it('with more than one tag in the image', () => {
+ mountComponent({ item: { ...item, tags_count: 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
new file mode 100644
index 00000000000..03ba6ad7f80
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/list_page/image_list_spec.js
@@ -0,0 +1,62 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlPagination } 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';
+
+describe('Image List', () => {
+ let wrapper;
+
+ const findRow = () => wrapper.findAll(ImageListRow);
+ const findPagination = () => wrapper.find(GlPagination);
+
+ const mountComponent = () => {
+ wrapper = shallowMount(Component, {
+ propsData: {
+ images: imagesListResponse.data,
+ pagination: imagePagination,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('list', () => {
+ it('contains one list element for each image', () => {
+ expect(findRow().length).toBe(imagesListResponse.data.length);
+ });
+
+ it('when delete event is emitted on the row it emits up a delete event', () => {
+ findRow()
+ .at(0)
+ .vm.$emit('delete', 'foo');
+ expect(wrapper.emitted('delete')).toEqual([['foo']]);
+ });
+ });
+
+ describe('pagination', () => {
+ it('exists', () => {
+ 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('emits a pageChange event when the page change', () => {
+ findPagination().vm.$emit(GlPagination.model.event, 2);
+ expect(wrapper.emitted('pageChange')).toEqual([[2]]);
+ });
+ });
+});
diff --git a/spec/frontend/registry/explorer/components/project_empty_state_spec.js b/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js
index 4b209646da9..73746c545cb 100644
--- a/spec/frontend/registry/explorer/components/project_empty_state_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js
@@ -1,8 +1,8 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
-import { GlEmptyState } from '../stubs';
-import projectEmptyState from '~/registry/explorer/components/project_empty_state.vue';
+import { GlEmptyState } from '../../stubs';
+import projectEmptyState from '~/registry/explorer/components/list_page/project_empty_state.vue';
import * as getters from '~/registry/explorer/stores/getters';
const localVue = createLocalVue();
diff --git a/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js b/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
new file mode 100644
index 00000000000..7484fccbea7
--- /dev/null
+++ b/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
@@ -0,0 +1,221 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlSprintf, GlLink } from '@gitlab/ui';
+import Component from '~/registry/explorer/components/list_page/registry_header.vue';
+import {
+ CONTAINER_REGISTRY_TITLE,
+ LIST_INTRO_TEXT,
+ EXPIRATION_POLICY_DISABLED_MESSAGE,
+ EXPIRATION_POLICY_DISABLED_TEXT,
+ EXPIRATION_POLICY_WILL_RUN_IN,
+} from '~/registry/explorer/constants';
+
+jest.mock('~/lib/utils/datetime_utility', () => ({
+ approximateDuration: jest.fn(),
+ calculateRemainingMilliseconds: jest.fn(),
+}));
+
+describe('registry_header', () => {
+ let wrapper;
+
+ const findHeader = () => wrapper.find('[data-testid="header"]');
+ const findTitle = () => wrapper.find('[data-testid="title"]');
+ const findCommandsSlot = () => wrapper.find('[data-testid="commands-slot"]');
+ const findInfoArea = () => wrapper.find('[data-testid="info-area"]');
+ const findIntroText = () => wrapper.find('[data-testid="default-intro"]');
+ const findSubHeader = () => wrapper.find('[data-testid="subheader"]');
+ const findImagesCountSubHeader = () => wrapper.find('[data-testid="images-count"]');
+ const findExpirationPolicySubHeader = () => wrapper.find('[data-testid="expiration-policy"]');
+ const findDisabledExpirationPolicyMessage = () =>
+ wrapper.find('[data-testid="expiration-disabled-message"]');
+
+ const mountComponent = (propsData, slots) => {
+ wrapper = shallowMount(Component, {
+ stubs: {
+ GlSprintf,
+ },
+ propsData,
+ slots,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('header', () => {
+ it('exists', () => {
+ mountComponent();
+ expect(findHeader().exists()).toBe(true);
+ });
+
+ it('contains the title of the page', () => {
+ mountComponent();
+ const title = findTitle();
+ expect(title.exists()).toBe(true);
+ expect(title.text()).toBe(CONTAINER_REGISTRY_TITLE);
+ });
+
+ it('has a commands slot', () => {
+ mountComponent(null, { commands: 'baz' });
+ expect(findCommandsSlot().text()).toBe('baz');
+ });
+ });
+
+ describe('subheader', () => {
+ describe('when there are no images', () => {
+ it('is hidden ', () => {
+ mountComponent();
+ expect(findSubHeader().exists()).toBe(false);
+ });
+ });
+
+ describe('when there are images', () => {
+ it('is visible', () => {
+ mountComponent({ imagesCount: 1 });
+ expect(findSubHeader().exists()).toBe(true);
+ });
+
+ describe('sub header parts', () => {
+ describe('images count', () => {
+ it('exists', () => {
+ mountComponent({ imagesCount: 1 });
+ expect(findImagesCountSubHeader().exists()).toBe(true);
+ });
+
+ it('when there is one image', () => {
+ mountComponent({ imagesCount: 1 });
+ expect(findImagesCountSubHeader().text()).toMatchInterpolatedText('1 Image repository');
+ });
+
+ it('when there is more than one image', () => {
+ mountComponent({ imagesCount: 3 });
+ expect(findImagesCountSubHeader().text()).toMatchInterpolatedText(
+ '3 Image repositories',
+ );
+ });
+ });
+
+ describe('expiration policy', () => {
+ it('when is disabled', () => {
+ mountComponent({
+ expirationPolicy: { enabled: false },
+ expirationPolicyHelpPagePath: 'foo',
+ imagesCount: 1,
+ });
+ const text = findExpirationPolicySubHeader();
+ expect(text.exists()).toBe(true);
+ expect(text.text()).toMatchInterpolatedText(EXPIRATION_POLICY_DISABLED_TEXT);
+ });
+
+ it('when is enabled', () => {
+ mountComponent({
+ expirationPolicy: { enabled: true },
+ expirationPolicyHelpPagePath: 'foo',
+ imagesCount: 1,
+ });
+ const text = findExpirationPolicySubHeader();
+ expect(text.exists()).toBe(true);
+ expect(text.text()).toMatchInterpolatedText(EXPIRATION_POLICY_WILL_RUN_IN);
+ });
+ it('when the expiration policy is completely disabled', () => {
+ mountComponent({
+ expirationPolicy: { enabled: true },
+ expirationPolicyHelpPagePath: 'foo',
+ imagesCount: 1,
+ hideExpirationPolicyData: true,
+ });
+ const text = findExpirationPolicySubHeader();
+ expect(text.exists()).toBe(false);
+ });
+ });
+ });
+ });
+ });
+
+ describe('info area', () => {
+ it('exists', () => {
+ mountComponent();
+ expect(findInfoArea().exists()).toBe(true);
+ });
+
+ describe('default message', () => {
+ beforeEach(() => {
+ mountComponent({ helpPagePath: 'bar' });
+ });
+
+ it('exists', () => {
+ expect(findIntroText().exists()).toBe(true);
+ });
+
+ it('has the correct copy', () => {
+ expect(findIntroText().text()).toMatchInterpolatedText(LIST_INTRO_TEXT);
+ });
+
+ it('has the correct link', () => {
+ expect(
+ findIntroText()
+ .find(GlLink)
+ .attributes('href'),
+ ).toBe('bar');
+ });
+ });
+
+ describe('expiration policy info message', () => {
+ describe('when there are no images', () => {
+ it('is hidden', () => {
+ mountComponent();
+ expect(findDisabledExpirationPolicyMessage().exists()).toBe(false);
+ });
+ });
+
+ describe('when there are images', () => {
+ describe('when expiration policy is disabled', () => {
+ beforeEach(() => {
+ mountComponent({
+ expirationPolicy: { enabled: false },
+ expirationPolicyHelpPagePath: 'foo',
+ imagesCount: 1,
+ });
+ });
+ it('message exist', () => {
+ expect(findDisabledExpirationPolicyMessage().exists()).toBe(true);
+ });
+ it('has the correct copy', () => {
+ expect(findDisabledExpirationPolicyMessage().text()).toMatchInterpolatedText(
+ EXPIRATION_POLICY_DISABLED_MESSAGE,
+ );
+ });
+
+ it('has the correct link', () => {
+ expect(
+ findDisabledExpirationPolicyMessage()
+ .find(GlLink)
+ .attributes('href'),
+ ).toBe('foo');
+ });
+ });
+
+ describe('when expiration policy is enabled', () => {
+ it('message does not exist', () => {
+ mountComponent({
+ expirationPolicy: { enabled: true },
+ imagesCount: 1,
+ });
+ expect(findDisabledExpirationPolicyMessage().exists()).toBe(false);
+ });
+ });
+ describe('when the expiration policy is completely disabled', () => {
+ it('message does not exist', () => {
+ mountComponent({
+ expirationPolicy: { enabled: true },
+ imagesCount: 1,
+ hideExpirationPolicyData: true,
+ });
+ expect(findDisabledExpirationPolicyMessage().exists()).toBe(false);
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/registry/explorer/components/project_policy_alert_spec.js b/spec/frontend/registry/explorer/components/project_policy_alert_spec.js
deleted file mode 100644
index 89c37e55398..00000000000
--- a/spec/frontend/registry/explorer/components/project_policy_alert_spec.js
+++ /dev/null
@@ -1,132 +0,0 @@
-import Vuex from 'vuex';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlSprintf, GlAlert, GlLink } from '@gitlab/ui';
-import * as dateTimeUtils from '~/lib/utils/datetime_utility';
-import component from '~/registry/explorer/components/project_policy_alert.vue';
-import {
- EXPIRATION_POLICY_ALERT_TITLE,
- EXPIRATION_POLICY_ALERT_PRIMARY_BUTTON,
-} from '~/registry/explorer/constants';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('Project Policy Alert', () => {
- let wrapper;
- let store;
-
- const defaultState = {
- config: {
- expirationPolicy: {
- enabled: true,
- },
- settingsPath: 'foo',
- expirationPolicyHelpPagePath: 'bar',
- },
- images: [],
- isLoading: false,
- };
-
- const findAlert = () => wrapper.find(GlAlert);
- const findLink = () => wrapper.find(GlLink);
-
- const createComponent = (state = defaultState) => {
- store = new Vuex.Store({
- state,
- });
- wrapper = shallowMount(component, {
- localVue,
- store,
- stubs: {
- GlSprintf,
- },
- });
- };
-
- const documentationExpectation = () => {
- it('contain a documentation link', () => {
- createComponent();
- expect(findLink().attributes('href')).toBe(defaultState.config.expirationPolicyHelpPagePath);
- expect(findLink().text()).toBe('documentation');
- });
- };
-
- beforeEach(() => {
- jest.spyOn(dateTimeUtils, 'approximateDuration').mockReturnValue('1 day');
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('is hidden', () => {
- it('when expiration policy does not exist', () => {
- createComponent({ config: {} });
- expect(findAlert().exists()).toBe(false);
- });
-
- it('when expiration policy exist but is disabled', () => {
- createComponent({
- ...defaultState,
- config: {
- expirationPolicy: {
- enabled: false,
- },
- },
- });
- expect(findAlert().exists()).toBe(false);
- });
- });
-
- describe('is visible', () => {
- it('when expiration policy exists and is enabled', () => {
- createComponent();
- expect(findAlert().exists()).toBe(true);
- });
- });
-
- describe('full info alert', () => {
- beforeEach(() => {
- createComponent({ ...defaultState, images: [1] });
- });
-
- it('has a primary button', () => {
- const alert = findAlert();
- expect(alert.props('primaryButtonText')).toBe(EXPIRATION_POLICY_ALERT_PRIMARY_BUTTON);
- expect(alert.props('primaryButtonLink')).toBe(defaultState.config.settingsPath);
- });
-
- it('has a title', () => {
- const alert = findAlert();
- expect(alert.props('title')).toBe(EXPIRATION_POLICY_ALERT_TITLE);
- });
-
- it('has the full message', () => {
- expect(findAlert().html()).toContain('<strong>1 day</strong>');
- });
-
- documentationExpectation();
- });
-
- describe('compact info alert', () => {
- beforeEach(() => {
- createComponent({ ...defaultState, images: [] });
- });
-
- it('does not have a button', () => {
- const alert = findAlert();
- expect(alert.props('primaryButtonText')).toBe(null);
- });
-
- it('does not have a title', () => {
- const alert = findAlert();
- expect(alert.props('title')).toBe(null);
- });
-
- it('has the short message', () => {
- expect(findAlert().html()).not.toContain('<strong>1 day</strong>');
- });
-
- documentationExpectation();
- });
-});