Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-03-31 18:08:50 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-31 18:08:50 +0300
commitccab6fb4df8bc12220334618e56d911c4d0e447c (patch)
treea8c7bb66fb4c36c97e7e1b4f27744fcd93c3bcf3 /spec/frontend/packages_and_registries
parent820c5f6d5c816ba4b742f2ae2e08cc548314531a (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/packages_and_registries')
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js289
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js119
2 files changed, 273 insertions, 135 deletions
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
index 09d0370efbf..0cbb9eab018 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
@@ -4,13 +4,15 @@ import { GlEmptyState } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-
+import Tracking from '~/tracking';
import component from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue';
import TagsListRow from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue';
import TagsLoader from '~/packages_and_registries/shared/components/tags_loader.vue';
import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
import getContainerRepositoryTagsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql';
+import deleteContainerRepositoryTagsMutation from '~/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql';
+
import {
GRAPHQL_PAGE_SIZE,
NO_TAGS_TITLE,
@@ -19,7 +21,13 @@ import {
NO_TAGS_MATCHING_FILTERS_DESCRIPTION,
} from '~/packages_and_registries/container_registry/explorer/constants/index';
import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
-import { tagsMock, imageTagsMock, tagsPageInfo } from '../../mock_data';
+import {
+ graphQLDeleteImageRepositoryTagsMock,
+ tagsMock,
+ imageTagsMock,
+ tagsPageInfo,
+} from '../../mock_data';
+import { DeleteModal } from '../../stubs';
describe('Tags List', () => {
let wrapper;
@@ -31,6 +39,7 @@ describe('Tags List', () => {
noContainersImage: 'noContainersImage',
};
+ const findDeleteModal = () => wrapper.findComponent(DeleteModal);
const findPersistedSearch = () => wrapper.findComponent(PersistedSearch);
const findTagsListRow = () => wrapper.findAllComponents(TagsListRow);
const findRegistryList = () => wrapper.findComponent(RegistryList);
@@ -42,20 +51,23 @@ describe('Tags List', () => {
};
const waitForApolloRequestRender = async () => {
+ fireFirstSortUpdate();
await waitForPromises();
- await nextTick();
};
- const mountComponent = ({ propsData = { isMobile: false, id: 1 } } = {}) => {
+ const mountComponent = ({ propsData = { isMobile: false, id: 1 }, mutationResolver } = {}) => {
Vue.use(VueApollo);
- const requestHandlers = [[getContainerRepositoryTagsQuery, resolver]];
+ const requestHandlers = [
+ [getContainerRepositoryTagsQuery, resolver],
+ [deleteContainerRepositoryTagsMutation, mutationResolver],
+ ];
apolloProvider = createMockApollo(requestHandlers);
wrapper = shallowMount(component, {
apolloProvider,
propsData,
- stubs: { RegistryList },
+ stubs: { RegistryList, DeleteModal },
provide() {
return {
config: defaultConfig,
@@ -66,12 +78,12 @@ describe('Tags List', () => {
beforeEach(() => {
resolver = jest.fn().mockResolvedValue(imageTagsMock());
+ jest.spyOn(Tracking, 'event');
});
describe('registry list', () => {
beforeEach(async () => {
mountComponent();
- fireFirstSortUpdate();
await waitForApolloRequestRender();
});
@@ -126,11 +138,46 @@ describe('Tags List', () => {
});
});
- it('emits a delete event when list emits delete', () => {
- const eventPayload = 'foo';
- findRegistryList().vm.$emit('delete', eventPayload);
+ describe('delete event', () => {
+ describe('single item', () => {
+ beforeEach(() => {
+ findRegistryList().vm.$emit('delete', [tags[0]]);
+ });
+
+ it('opens the modal', () => {
+ expect(DeleteModal.methods.show).toHaveBeenCalled();
+ });
+
+ it('sets modal props', () => {
+ expect(findDeleteModal().props('itemsToBeDeleted')).toMatchObject([tags[0]]);
+ });
+
+ it('tracks a single delete event', () => {
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
+ label: 'registry_tag_delete',
+ });
+ });
+ });
+
+ describe('multiple items', () => {
+ beforeEach(() => {
+ findRegistryList().vm.$emit('delete', tags);
+ });
+
+ it('opens the modal', () => {
+ expect(DeleteModal.methods.show).toHaveBeenCalled();
+ });
- expect(wrapper.emitted('delete')).toEqual([[eventPayload]]);
+ it('sets modal props', () => {
+ expect(findDeleteModal().props('itemsToBeDeleted')).toMatchObject(tags);
+ });
+
+ it('tracks multiple delete event', () => {
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
+ label: 'bulk_registry_tag_delete',
+ });
+ });
+ });
});
});
});
@@ -138,7 +185,6 @@ describe('Tags List', () => {
describe('list rows', () => {
it('one row exist for each tag', async () => {
mountComponent();
- fireFirstSortUpdate();
await waitForApolloRequestRender();
@@ -147,7 +193,6 @@ describe('Tags List', () => {
it('the correct props are bound to it', async () => {
mountComponent({ propsData: { disabled: true, id: 1 } });
- fireFirstSortUpdate();
await waitForApolloRequestRender();
@@ -162,7 +207,6 @@ describe('Tags List', () => {
describe('events', () => {
it('select event update the selected items', async () => {
mountComponent();
- fireFirstSortUpdate();
await waitForApolloRequestRender();
findTagsListRow().at(0).vm.$emit('select');
@@ -172,13 +216,44 @@ describe('Tags List', () => {
expect(findTagsListRow().at(0).attributes('selected')).toBe('true');
});
- it('delete event emit a delete event', async () => {
- mountComponent();
- fireFirstSortUpdate();
- await waitForApolloRequestRender();
+ describe('delete event', () => {
+ let mutationResolver;
+
+ beforeEach(async () => {
+ mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
+ resolver = jest.fn().mockResolvedValue(imageTagsMock());
+ mountComponent({ mutationResolver });
- findTagsListRow().at(0).vm.$emit('delete');
- expect(wrapper.emitted('delete')[0][0][0].name).toBe(tags[0].name);
+ await waitForApolloRequestRender();
+ findTagsListRow().at(0).vm.$emit('delete');
+ });
+
+ it('opens the modal', () => {
+ expect(DeleteModal.methods.show).toHaveBeenCalled();
+ });
+
+ it('tracks a single delete event', () => {
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
+ label: 'registry_tag_delete',
+ });
+ });
+
+ it('confirmDelete event calls apollo mutation with the right parameters and refetches the tags list query', async () => {
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: [tags[0].name] }),
+ );
+
+ await waitForPromises();
+
+ expect(resolver).toHaveBeenLastCalledWith({
+ first: GRAPHQL_PAGE_SIZE,
+ name: '',
+ sort: 'NAME_ASC',
+ id: '1',
+ });
+ });
});
});
});
@@ -187,7 +262,6 @@ describe('Tags List', () => {
it('sets registry list hiddenDelete prop to true', async () => {
resolver = jest.fn().mockResolvedValue(imageTagsMock({ canDelete: false }));
mountComponent();
- fireFirstSortUpdate();
await waitForApolloRequestRender();
expect(findRegistryList().props('hiddenDelete')).toBe(true);
@@ -198,7 +272,6 @@ describe('Tags List', () => {
beforeEach(async () => {
resolver = jest.fn().mockResolvedValue(imageTagsMock({ nodes: [] }));
mountComponent();
- fireFirstSortUpdate();
await waitForApolloRequestRender();
});
@@ -225,7 +298,7 @@ describe('Tags List', () => {
filters: [{ type: FILTERED_SEARCH_TERM, value: { data: 'foo' } }],
});
- await waitForApolloRequestRender();
+ await waitForPromises();
expect(findEmptyState().props()).toMatchObject({
svgPath: defaultConfig.noContainersImage,
@@ -236,6 +309,175 @@ describe('Tags List', () => {
});
});
+ describe('modal', () => {
+ it('exists', async () => {
+ mountComponent();
+ await waitForApolloRequestRender();
+
+ expect(findDeleteModal().exists()).toBe(true);
+ });
+
+ describe('cancel event', () => {
+ it('tracks cancel_delete', async () => {
+ mountComponent();
+ await waitForApolloRequestRender();
+
+ findDeleteModal().vm.$emit('cancel');
+
+ expect(Tracking.event).toHaveBeenCalledWith(undefined, 'cancel_delete', {
+ label: 'registry_tag_delete',
+ });
+ });
+ });
+
+ describe('confirmDelete event', () => {
+ let mutationResolver;
+
+ describe('when mutation', () => {
+ beforeEach(() => {
+ mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
+ mountComponent({ mutationResolver });
+
+ return waitForApolloRequestRender();
+ });
+
+ it('is started renders loader', async () => {
+ findRegistryList().vm.$emit('delete', [tags[0]]);
+
+ findDeleteModal().vm.$emit('confirmDelete');
+ await nextTick();
+
+ expect(findTagsLoader().exists()).toBe(true);
+ expect(findTagsListRow().exists()).toBe(false);
+ });
+
+ it('ends, loader is hidden', async () => {
+ findRegistryList().vm.$emit('delete', [tags[0]]);
+
+ findDeleteModal().vm.$emit('confirmDelete');
+ await waitForPromises();
+
+ expect(findTagsLoader().exists()).toBe(false);
+ expect(findTagsListRow().exists()).toBe(true);
+ });
+ });
+
+ describe.each([
+ {
+ description: 'rejection',
+ mutationMock: jest.fn().mockRejectedValue(),
+ },
+ {
+ description: 'error',
+ mutationMock: jest.fn().mockResolvedValue({
+ data: {
+ destroyContainerRepositoryTags: {
+ errors: [new Error()],
+ },
+ },
+ }),
+ },
+ ])('when mutation fails with $description', ({ mutationMock }) => {
+ beforeEach(() => {
+ mutationResolver = mutationMock;
+ mountComponent({ mutationResolver });
+
+ return waitForApolloRequestRender();
+ });
+
+ it('when one item is selected to be deleted calls apollo mutation with the right parameters and emits delete event with right arguments', async () => {
+ findRegistryList().vm.$emit('delete', [tags[0]]);
+
+ resolver.mockClear();
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: [tags[0].name] }),
+ );
+
+ expect(resolver).not.toHaveBeenCalled();
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('delete')).toHaveLength(1);
+ expect(wrapper.emitted('delete')[0][0]).toEqual('danger_tag');
+ });
+
+ it('when more than one item is selected to be deleted calls apollo mutation with the right parameters and emits delete event with right arguments', async () => {
+ findRegistryList().vm.$emit('delete', tagsMock);
+ resolver.mockClear();
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: tagsMock.map((t) => t.name) }),
+ );
+
+ expect(resolver).not.toHaveBeenCalled();
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('delete')).toHaveLength(1);
+ expect(wrapper.emitted('delete')[0][0]).toEqual('danger_tags');
+ });
+ });
+
+ describe('when mutation is successful', () => {
+ beforeEach(() => {
+ mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
+ mountComponent({ mutationResolver });
+
+ return waitForApolloRequestRender();
+ });
+
+ it('and one item is selected to be deleted calls apollo mutation with the right parameters and refetches the tags list query', async () => {
+ findRegistryList().vm.$emit('delete', [tags[0]]);
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: [tags[0].name] }),
+ );
+
+ expect(resolver).toHaveBeenLastCalledWith({
+ first: GRAPHQL_PAGE_SIZE,
+ name: '',
+ sort: 'NAME_ASC',
+ id: '1',
+ });
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('delete')).toHaveLength(1);
+ expect(wrapper.emitted('delete')[0][0]).toEqual('success_tag');
+ });
+
+ it('and more than one item is selected to be deleted calls apollo mutation with the right parameters and refetches the tags list query', async () => {
+ findRegistryList().vm.$emit('delete', tagsMock);
+
+ findDeleteModal().vm.$emit('confirmDelete');
+
+ expect(mutationResolver).toHaveBeenCalledWith(
+ expect.objectContaining({ tagNames: tagsMock.map((t) => t.name) }),
+ );
+
+ expect(resolver).toHaveBeenLastCalledWith({
+ first: GRAPHQL_PAGE_SIZE,
+ name: '',
+ sort: 'NAME_ASC',
+ id: '1',
+ });
+
+ await waitForPromises();
+
+ expect(wrapper.emitted('delete')).toHaveLength(1);
+ expect(wrapper.emitted('delete')[0][0]).toEqual('success_tags');
+ });
+ });
+ });
+ });
+
describe('loading state', () => {
it.each`
isImageLoading | queryExecuting | loadingVisible
@@ -247,7 +489,6 @@ describe('Tags List', () => {
'when the isImageLoading is $isImageLoading, and is $queryExecuting that the query is still executing is $loadingVisible that the loader is shown',
async ({ isImageLoading, queryExecuting, loadingVisible }) => {
mountComponent({ propsData: { isImageLoading, isMobile: false, id: 1 } });
- fireFirstSortUpdate();
if (!queryExecuting) {
await waitForApolloRequestRender();
}
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
index 888c3e5bffa..7fed81acead 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
@@ -22,22 +22,15 @@ import {
MISSING_OR_DELETED_IMAGE_TITLE,
MISSING_OR_DELETED_IMAGE_MESSAGE,
} from '~/packages_and_registries/container_registry/explorer/constants';
-import deleteContainerRepositoryTagsMutation from '~/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql';
import getContainerRepositoryDetailsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
-import getContainerRepositoryTagsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql';
-import getContainerRepositoriesDetails from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql';
import component from '~/packages_and_registries/container_registry/explorer/pages/details.vue';
import Tracking from '~/tracking';
import {
graphQLImageDetailsMock,
- graphQLDeleteImageRepositoryTagsMock,
- graphQLProjectImageRepositoriesDetailsMock,
containerRepositoryMock,
graphQLEmptyImageDetailsMock,
- tagsMock,
- imageTagsMock,
} from '../mock_data';
import { DeleteModal } from '../stubs';
@@ -69,13 +62,6 @@ describe('Details Page', () => {
isGroupPage: false,
};
- const cleanTags = tagsMock.map((t) => {
- const result = { ...t };
- // eslint-disable-next-line no-underscore-dangle
- delete result.__typename;
- return result;
- });
-
const waitForApolloRequestRender = async () => {
await waitForPromises();
await nextTick();
@@ -83,20 +69,12 @@ describe('Details Page', () => {
const mountComponent = ({
resolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock()),
- mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock),
- tagsResolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock(imageTagsMock())),
- detailsResolver = jest.fn().mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock),
options,
config = defaultConfig,
} = {}) => {
Vue.use(VueApollo);
- const requestHandlers = [
- [getContainerRepositoryDetailsQuery, resolver],
- [deleteContainerRepositoryTagsMutation, mutationResolver],
- [getContainerRepositoryTagsQuery, tagsResolver],
- [getContainerRepositoriesDetails, detailsResolver],
- ];
+ const requestHandlers = [[getContainerRepositoryDetailsQuery, resolver]];
apolloProvider = createMockApollo(requestHandlers);
@@ -184,50 +162,6 @@ describe('Details Page', () => {
isMobile: false,
});
});
-
- describe('deleteEvent', () => {
- describe('single item', () => {
- let tagToBeDeleted;
- beforeEach(async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- [tagToBeDeleted] = cleanTags;
- findTagsList().vm.$emit('delete', [tagToBeDeleted]);
- });
-
- it('open the modal', async () => {
- expect(DeleteModal.methods.show).toHaveBeenCalled();
- });
-
- it('tracks a single delete event', () => {
- expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
- label: 'registry_tag_delete',
- });
- });
- });
-
- describe('multiple items', () => {
- beforeEach(async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- findTagsList().vm.$emit('delete', cleanTags);
- });
-
- it('open the modal', () => {
- expect(DeleteModal.methods.show).toHaveBeenCalled();
- });
-
- it('tracks a single delete event', () => {
- expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
- label: 'bulk_registry_tag_delete',
- });
- });
- });
- });
});
describe('modal', () => {
@@ -248,61 +182,24 @@ describe('Details Page', () => {
findDeleteModal().vm.$emit('cancel');
expect(Tracking.event).toHaveBeenCalledWith(undefined, 'cancel_delete', {
- label: 'registry_tag_delete',
+ label: 'registry_image_delete',
});
});
});
- describe('confirmDelete event', () => {
- let mutationResolver;
- let tagsResolver;
- let detailsResolver;
-
+ describe('tags list delete event', () => {
beforeEach(() => {
- mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
- tagsResolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock(imageTagsMock()));
- detailsResolver = jest.fn().mockResolvedValue(graphQLProjectImageRepositoriesDetailsMock);
- mountComponent({ mutationResolver, tagsResolver, detailsResolver });
+ mountComponent();
return waitForApolloRequestRender();
});
- describe('when one item is selected to be deleted', () => {
- it('calls apollo mutation with the right parameters and refetches the tags list query', async () => {
- findTagsList().vm.$emit('delete', [cleanTags[0]]);
-
- await nextTick();
-
- findDeleteModal().vm.$emit('confirmDelete');
-
- expect(mutationResolver).toHaveBeenCalledWith(
- expect.objectContaining({ tagNames: [cleanTags[0].name] }),
- );
-
- await waitForPromises();
-
- expect(tagsResolver).toHaveBeenCalled();
- expect(detailsResolver).toHaveBeenCalled();
- });
- });
-
- describe('when more than one item is selected to be deleted', () => {
- it('calls apollo mutation with the right parameters and refetches the tags list query', async () => {
- findTagsList().vm.$emit('delete', tagsMock);
-
- await nextTick();
+ it('sets delete alert modal deleteAlertType value', async () => {
+ findTagsList().vm.$emit('delete', 'success_tag');
- findDeleteModal().vm.$emit('confirmDelete');
-
- expect(mutationResolver).toHaveBeenCalledWith(
- expect.objectContaining({ tagNames: tagsMock.map((t) => t.name) }),
- );
-
- await waitForPromises();
+ await nextTick();
- expect(tagsResolver).toHaveBeenCalled();
- expect(detailsResolver).toHaveBeenCalled();
- });
+ expect(findDeleteAlert().props('deleteAlertType')).toBe('success_tag');
});
});
});