summaryrefslogtreecommitdiff
path: root/spec/frontend/registry/explorer
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 08:27:35 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-19 08:27:35 +0000
commit7e9c479f7de77702622631cff2628a9c8dcbc627 (patch)
treec8f718a08e110ad7e1894510980d2155a6549197 /spec/frontend/registry/explorer
parente852b0ae16db4052c1c567d9efa4facc81146e88 (diff)
downloadgitlab-ce-7e9c479f7de77702622631cff2628a9c8dcbc627.tar.gz
Add latest changes from gitlab-org/gitlab@13-6-stable-eev13.6.0-rc42
Diffstat (limited to 'spec/frontend/registry/explorer')
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js4
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_spec.js24
-rw-r--r--spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js4
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js9
-rw-r--r--spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js11
-rw-r--r--spec/frontend/registry/explorer/mock_data.js11
-rw-r--r--spec/frontend/registry/explorer/pages/details_spec.js41
-rw-r--r--spec/frontend/registry/explorer/stores/actions_spec.js79
-rw-r--r--spec/frontend/registry/explorer/stores/mutations_spec.js9
-rw-r--r--spec/frontend/registry/explorer/utils_spec.js45
10 files changed, 179 insertions, 58 deletions
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 ef22979ca7d..3276ef911e3 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
@@ -22,7 +22,7 @@ describe('tags list row', () => {
let wrapper;
const [tag] = [...tagsListResponse.data];
- const defaultProps = { tag, isDesktop: true, index: 0 };
+ const defaultProps = { tag, isMobile: false, index: 0 };
const findCheckbox = () => wrapper.find(GlFormCheckbox);
const findName = () => wrapper.find('[data-testid="name"]');
@@ -114,7 +114,7 @@ describe('tags list row', () => {
});
it('on mobile has mw-s class', () => {
- mountComponent({ ...defaultProps, isDesktop: false });
+ mountComponent({ ...defaultProps, isMobile: true });
expect(findName().classes('mw-s')).toBe(true);
});
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 401202026bb..ebeaa8ff870 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
@@ -14,7 +14,7 @@ describe('Tags List', () => {
const findDeleteButton = () => wrapper.find(GlButton);
const findListTitle = () => wrapper.find('[data-testid="list-title"]');
- const mountComponent = (propsData = { tags, isDesktop: true }) => {
+ const mountComponent = (propsData = { tags, isMobile: false }) => {
wrapper = shallowMount(component, {
propsData,
});
@@ -41,15 +41,15 @@ describe('Tags List', () => {
describe('delete button', () => {
it.each`
- inputTags | isDesktop | isVisible
- ${tags} | ${true} | ${true}
- ${tags} | ${false} | ${false}
- ${readOnlyTags} | ${true} | ${false}
- ${readOnlyTags} | ${false} | ${false}
+ inputTags | isMobile | isVisible
+ ${tags} | ${false} | ${true}
+ ${tags} | ${true} | ${false}
+ ${readOnlyTags} | ${false} | ${false}
+ ${readOnlyTags} | ${true} | ${false}
`(
- 'is $isVisible that delete button exists when tags is $inputTags and isDesktop is $isDesktop',
- ({ inputTags, isDesktop, isVisible }) => {
- mountComponent({ tags: inputTags, isDesktop });
+ 'is $isVisible that delete button exists when tags is $inputTags and isMobile is $isMobile',
+ ({ inputTags, isMobile, isVisible }) => {
+ mountComponent({ tags: inputTags, isMobile });
expect(findDeleteButton().exists()).toBe(isVisible);
},
@@ -110,12 +110,6 @@ describe('Tags List', () => {
expect(rows.at(0).attributes()).toMatchObject({
first: 'true',
- isdesktop: 'true',
- });
-
- // The list has only two tags and for some reasons .at(-1) does not work
- expect(rows.at(1).attributes()).toMatchObject({
- isdesktop: 'true',
});
});
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 b4471ab8122..551d1eee68d 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
@@ -1,6 +1,6 @@
import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
-import { GlDeprecatedDropdown } from '@gitlab/ui';
+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';
@@ -23,7 +23,7 @@ describe('cli_commands', () => {
let wrapper;
let store;
- const findDropdownButton = () => wrapper.find(GlDeprecatedDropdown);
+ const findDropdownButton = () => wrapper.find(GlDropdown);
const findCodeInstruction = () => wrapper.findAll(CodeInstruction);
const mountComponent = () => {
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 ce446e6d93e..9f7a2758ae1 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
@@ -19,7 +19,7 @@ describe('Image List Row', () => {
let wrapper;
const item = imagesListResponse.data[0];
- const findDetailsLink = () => wrapper.find('[data-testid="detailsLink"]');
+ const findDetailsLink = () => wrapper.find('[data-testid="details-link"]');
const findTagsCount = () => wrapper.find('[data-testid="tagsCount"]');
const findDeleteBtn = () => wrapper.find(DeleteButton);
const findClipboardButton = () => wrapper.find(ClipboardButton);
@@ -67,7 +67,12 @@ describe('Image List Row', () => {
mountComponent();
const link = findDetailsLink();
expect(link.html()).toContain(item.path);
- expect(link.props('to').name).toBe('details');
+ expect(link.props('to')).toMatchObject({
+ name: 'details',
+ params: {
+ id: item.id,
+ },
+ });
});
it('contains a clipboard button', () => {
diff --git a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js b/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
index b906e44a4f7..d730bfcde24 100644
--- a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
+++ b/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
@@ -32,6 +32,10 @@ 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' });
@@ -52,6 +56,9 @@ describe('Registry Breadcrumb', () => {
routes,
},
},
+ $store: {
+ state,
+ },
},
});
};
@@ -80,7 +87,7 @@ describe('Registry Breadcrumb', () => {
});
it('the link text is calculated by nameGenerator', () => {
- expect(nameGenerator).toHaveBeenCalledWith(routes[0]);
+ expect(nameGenerator).toHaveBeenCalledWith(state);
expect(nameGenerator).toHaveBeenCalledTimes(1);
});
});
@@ -104,7 +111,7 @@ describe('Registry Breadcrumb', () => {
});
it('the link text is calculated by nameGenerator', () => {
- expect(nameGenerator).toHaveBeenCalledWith(routes[1]);
+ expect(nameGenerator).toHaveBeenCalledWith(state);
expect(nameGenerator).toHaveBeenCalledTimes(2);
});
});
diff --git a/spec/frontend/registry/explorer/mock_data.js b/spec/frontend/registry/explorer/mock_data.js
index a7ffed4c9fd..da5f1840b5c 100644
--- a/spec/frontend/registry/explorer/mock_data.js
+++ b/spec/frontend/registry/explorer/mock_data.js
@@ -97,3 +97,14 @@ export const imagePagination = {
totalPages: 2,
nextPage: 2,
};
+
+export const imageDetailsMock = {
+ id: 1,
+ name: 'rails-32309',
+ path: 'gitlab-org/gitlab-test/rails-32309',
+ project_id: 1,
+ location: '0.0.0.0:5000/gitlab-org/gitlab-test/rails-32309',
+ created_at: '2020-06-29T10:23:47.838Z',
+ cleanup_policy_started_at: null,
+ delete_api_path: 'http://0.0.0.0:3000/api/v4/projects/1/registry/repositories/1',
+};
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/registry/explorer/pages/details_spec.js
index 86b52c4f06a..c09b7e0c067 100644
--- a/spec/frontend/registry/explorer/pages/details_spec.js
+++ b/spec/frontend/registry/explorer/pages/details_spec.js
@@ -14,9 +14,10 @@ import {
SET_TAGS_LIST_SUCCESS,
SET_TAGS_PAGINATION,
SET_INITIAL_STATE,
+ SET_IMAGE_DETAILS,
} from '~/registry/explorer/stores/mutation_types';
-import { tagsListResponse } from '../mock_data';
+import { tagsListResponse, imageDetailsMock } from '../mock_data';
import { DeleteModal } from '../stubs';
describe('Details Page', () => {
@@ -33,8 +34,7 @@ describe('Details Page', () => {
const findEmptyTagsState = () => wrapper.find(EmptyTagsState);
const findPartialCleanupAlert = () => wrapper.find(PartialCleanupAlert);
- const routeIdGenerator = override =>
- window.btoa(JSON.stringify({ name: 'foo', tags_path: 'bar', ...override }));
+ const routeId = 1;
const tagsArrayToSelectedTags = tags =>
tags.reduce((acc, c) => {
@@ -42,7 +42,7 @@ describe('Details Page', () => {
return acc;
}, {});
- const mountComponent = ({ options, routeParams } = {}) => {
+ const mountComponent = ({ options } = {}) => {
wrapper = shallowMount(component, {
store,
stubs: {
@@ -51,7 +51,7 @@ describe('Details Page', () => {
mocks: {
$route: {
params: {
- id: routeIdGenerator(routeParams),
+ id: routeId,
},
},
},
@@ -65,6 +65,7 @@ describe('Details Page', () => {
dispatchSpy.mockResolvedValue();
store.commit(SET_TAGS_LIST_SUCCESS, tagsListResponse.data);
store.commit(SET_TAGS_PAGINATION, tagsListResponse.headers);
+ store.commit(SET_IMAGE_DETAILS, imageDetailsMock);
jest.spyOn(Tracking, 'event');
});
@@ -73,6 +74,13 @@ describe('Details Page', () => {
wrapper = null;
});
+ describe('lifecycle events', () => {
+ it('calls the appropriate action on mount', () => {
+ mountComponent();
+ expect(dispatchSpy).toHaveBeenCalledWith('requestImageDetailsAndTagsList', routeId);
+ });
+ });
+
describe('when isLoading is true', () => {
beforeEach(() => {
store.commit(SET_MAIN_LOADING, true);
@@ -124,7 +132,7 @@ describe('Details Page', () => {
it('has the correct props bound', () => {
expect(findTagsList().props()).toMatchObject({
- isDesktop: true,
+ isMobile: false,
tags: store.state.tags,
});
});
@@ -194,8 +202,7 @@ describe('Details Page', () => {
dispatchSpy.mockResolvedValue();
findPagination().vm.$emit(GlPagination.model.event, 2);
expect(store.dispatch).toHaveBeenCalledWith('requestTagsList', {
- params: wrapper.vm.$route.params.id,
- pagination: { page: 2 },
+ page: 2,
});
});
});
@@ -227,7 +234,6 @@ describe('Details Page', () => {
findDeleteModal().vm.$emit('confirmDelete');
expect(dispatchSpy).toHaveBeenCalledWith('requestDeleteTag', {
tag: store.state.tags[0],
- params: routeIdGenerator(),
});
});
});
@@ -242,7 +248,6 @@ describe('Details Page', () => {
findDeleteModal().vm.$emit('confirmDelete');
expect(dispatchSpy).toHaveBeenCalledWith('requestDeleteTags', {
ids: store.state.tags.map(t => t.name),
- params: routeIdGenerator(),
});
});
});
@@ -257,7 +262,7 @@ describe('Details Page', () => {
it('has the correct props', () => {
mountComponent();
- expect(findDetailsHeader().props()).toEqual({ imageName: 'foo' });
+ expect(findDetailsHeader().props()).toEqual({ imageName: imageDetailsMock.name });
});
});
@@ -293,10 +298,14 @@ describe('Details Page', () => {
};
describe('when expiration_policy_started is not null', () => {
- const routeParams = { cleanup_policy_started_at: Date.now().toString() };
-
+ beforeEach(() => {
+ store.commit(SET_IMAGE_DETAILS, {
+ ...imageDetailsMock,
+ cleanup_policy_started_at: Date.now().toString(),
+ });
+ });
it('exists', () => {
- mountComponent({ routeParams });
+ mountComponent();
expect(findPartialCleanupAlert().exists()).toBe(true);
});
@@ -304,13 +313,13 @@ describe('Details Page', () => {
it('has the correct props', () => {
store.commit(SET_INITIAL_STATE, { ...config });
- mountComponent({ routeParams });
+ mountComponent();
expect(findPartialCleanupAlert().props()).toEqual({ ...config });
});
it('dismiss hides the component', async () => {
- mountComponent({ routeParams });
+ mountComponent();
expect(findPartialCleanupAlert().exists()).toBe(true);
findPartialCleanupAlert().vm.$emit('dismiss');
diff --git a/spec/frontend/registry/explorer/stores/actions_spec.js b/spec/frontend/registry/explorer/stores/actions_spec.js
index fb93ab06ca8..dcd4d8015a4 100644
--- a/spec/frontend/registry/explorer/stores/actions_spec.js
+++ b/spec/frontend/registry/explorer/stores/actions_spec.js
@@ -1,18 +1,29 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
+import createFlash from '~/flash';
+import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
import * as actions from '~/registry/explorer/stores/actions';
import * as types from '~/registry/explorer/stores/mutation_types';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
import { reposServerResponse, registryServerResponse } from '../mock_data';
+import * as utils from '~/registry/explorer/utils';
+import {
+ FETCH_IMAGES_LIST_ERROR_MESSAGE,
+ FETCH_TAGS_LIST_ERROR_MESSAGE,
+ FETCH_IMAGE_DETAILS_ERROR_MESSAGE,
+} from '~/registry/explorer/constants/index';
jest.mock('~/flash.js');
+jest.mock('~/registry/explorer/utils');
describe('Actions RegistryExplorer Store', () => {
let mock;
const endpoint = `${TEST_HOST}/endpoint.json`;
+ const url = `${endpoint}/1}`;
+ jest.spyOn(utils, 'pathGenerator').mockReturnValue(url);
+
beforeEach(() => {
mock = new MockAdapter(axios);
});
@@ -123,7 +134,7 @@ describe('Actions RegistryExplorer Store', () => {
],
[],
() => {
- expect(createFlash).toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalledWith({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
done();
},
);
@@ -131,15 +142,12 @@ describe('Actions RegistryExplorer Store', () => {
});
describe('fetch tags list', () => {
- const url = `${endpoint}/1}`;
- const params = window.btoa(JSON.stringify({ tags_path: `${endpoint}/1}` }));
-
it('sets the tagsList', done => {
mock.onGet(url).replyOnce(200, registryServerResponse, {});
testAction(
actions.requestTagsList,
- { params },
+ {},
{},
[
{ type: types.SET_MAIN_LOADING, payload: true },
@@ -158,7 +166,7 @@ describe('Actions RegistryExplorer Store', () => {
it('should create flash on error', done => {
testAction(
actions.requestTagsList,
- { params },
+ {},
{},
[
{ type: types.SET_MAIN_LOADING, payload: true },
@@ -166,7 +174,7 @@ describe('Actions RegistryExplorer Store', () => {
],
[],
() => {
- expect(createFlash).toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalledWith({ message: FETCH_TAGS_LIST_ERROR_MESSAGE });
done();
},
);
@@ -176,8 +184,6 @@ describe('Actions RegistryExplorer Store', () => {
describe('request delete single tag', () => {
it('successfully performs the delete request', done => {
const deletePath = 'delete/path';
- const params = window.btoa(JSON.stringify({ tags_path: `${endpoint}/1}`, id: 1 }));
-
mock.onDelete(deletePath).replyOnce(200);
testAction(
@@ -186,7 +192,6 @@ describe('Actions RegistryExplorer Store', () => {
tag: {
destroy_path: deletePath,
},
- params,
},
{
tagsPagination: {},
@@ -202,7 +207,7 @@ describe('Actions RegistryExplorer Store', () => {
},
{
type: 'requestTagsList',
- payload: { pagination: {}, params },
+ payload: {},
},
],
done,
@@ -227,18 +232,55 @@ describe('Actions RegistryExplorer Store', () => {
});
});
- describe('request delete multiple tags', () => {
- const url = `project-path/registry/repository/foo/tags`;
- const params = window.btoa(JSON.stringify({ tags_path: `${url}?format=json` }));
+ describe('requestImageDetailsAndTagsList', () => {
+ it('sets the imageDetails and dispatch requestTagsList', done => {
+ const resolvedValue = { foo: 'bar' };
+ jest.spyOn(Api, 'containerRegistryDetails').mockResolvedValue({ data: resolvedValue });
+
+ testAction(
+ actions.requestImageDetailsAndTagsList,
+ 1,
+ {},
+ [
+ { type: types.SET_MAIN_LOADING, payload: true },
+ { type: types.SET_IMAGE_DETAILS, payload: resolvedValue },
+ ],
+ [
+ {
+ type: 'requestTagsList',
+ },
+ ],
+ done,
+ );
+ });
+
+ it('should create flash on error', done => {
+ jest.spyOn(Api, 'containerRegistryDetails').mockRejectedValue();
+ testAction(
+ actions.requestImageDetailsAndTagsList,
+ 1,
+ {},
+ [
+ { type: types.SET_MAIN_LOADING, payload: true },
+ { type: types.SET_MAIN_LOADING, payload: false },
+ ],
+ [],
+ () => {
+ expect(createFlash).toHaveBeenCalledWith({ message: FETCH_IMAGE_DETAILS_ERROR_MESSAGE });
+ done();
+ },
+ );
+ });
+ });
+ describe('request delete multiple tags', () => {
it('successfully performs the delete request', done => {
- mock.onDelete(`${url}/bulk_destroy`).replyOnce(200);
+ mock.onDelete(url).replyOnce(200);
testAction(
actions.requestDeleteTags,
{
ids: [1, 2],
- params,
},
{
tagsPagination: {},
@@ -254,7 +296,7 @@ describe('Actions RegistryExplorer Store', () => {
},
{
type: 'requestTagsList',
- payload: { pagination: {}, params },
+ payload: {},
},
],
done,
@@ -268,7 +310,6 @@ describe('Actions RegistryExplorer Store', () => {
actions.requestDeleteTags,
{
ids: [1, 2],
- params,
},
{
tagsPagination: {},
diff --git a/spec/frontend/registry/explorer/stores/mutations_spec.js b/spec/frontend/registry/explorer/stores/mutations_spec.js
index 4ca0211cdc3..1908d3f0350 100644
--- a/spec/frontend/registry/explorer/stores/mutations_spec.js
+++ b/spec/frontend/registry/explorer/stores/mutations_spec.js
@@ -121,4 +121,13 @@ describe('Mutations Registry Explorer Store', () => {
expect(mockState).toEqual(expectedState);
});
});
+
+ describe('SET_IMAGE_DETAILS', () => {
+ it('should set imageDetails', () => {
+ const expectedState = { ...mockState, imageDetails: { foo: 'bar' } };
+ mutations[types.SET_IMAGE_DETAILS](mockState, { foo: 'bar' });
+
+ expect(mockState).toEqual(expectedState);
+ });
+ });
});
diff --git a/spec/frontend/registry/explorer/utils_spec.js b/spec/frontend/registry/explorer/utils_spec.js
new file mode 100644
index 00000000000..0cd4a1cec29
--- /dev/null
+++ b/spec/frontend/registry/explorer/utils_spec.js
@@ -0,0 +1,45 @@
+import { pathGenerator } from '~/registry/explorer/utils';
+
+describe('Utils', () => {
+ describe('pathGenerator', () => {
+ const imageDetails = {
+ path: 'foo/bar/baz',
+ name: 'baz',
+ id: 1,
+ };
+
+ it('returns the fetch url when no ending is passed', () => {
+ expect(pathGenerator(imageDetails)).toBe('/foo/bar/registry/repository/1/tags?format=json');
+ });
+
+ it('returns the url with an ending when is passed', () => {
+ expect(pathGenerator(imageDetails, '/foo')).toBe('/foo/bar/registry/repository/1/tags/foo');
+ });
+
+ it.each`
+ path | name | result
+ ${'foo/foo'} | ${''} | ${'/foo/foo/registry/repository/1/tags?format=json'}
+ ${'foo/foo/foo'} | ${'foo'} | ${'/foo/foo/registry/repository/1/tags?format=json'}
+ ${'baz/foo/foo/foo'} | ${'foo'} | ${'/baz/foo/foo/registry/repository/1/tags?format=json'}
+ ${'baz/foo/foo/foo'} | ${'foo'} | ${'/baz/foo/foo/registry/repository/1/tags?format=json'}
+ ${'foo/foo/baz/foo/foo'} | ${'foo/foo'} | ${'/foo/foo/baz/registry/repository/1/tags?format=json'}
+ ${'foo/foo/baz/foo/bar'} | ${'foo/bar'} | ${'/foo/foo/baz/registry/repository/1/tags?format=json'}
+ ${'baz/foo/foo'} | ${'foo'} | ${'/baz/foo/registry/repository/1/tags?format=json'}
+ ${'baz/foo/bar'} | ${'foo'} | ${'/baz/foo/bar/registry/repository/1/tags?format=json'}
+ `('returns the correct path when path is $path and name is $name', ({ name, path, result }) => {
+ expect(pathGenerator({ id: 1, name, path })).toBe(result);
+ });
+
+ it('returns the url unchanged when imageDetails have no name', () => {
+ const imageDetailsWithoutName = {
+ path: 'foo/bar/baz',
+ name: '',
+ id: 1,
+ };
+
+ expect(pathGenerator(imageDetailsWithoutName)).toBe(
+ '/foo/bar/baz/registry/repository/1/tags?format=json',
+ );
+ });
+ });
+});