debian-mirror-gitlab/spec/frontend/registry/explorer/pages/details_spec.js

462 lines
12 KiB
JavaScript
Raw Normal View History

2021-02-22 17:27:13 +05:30
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlKeysetPagination } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import createMockApollo from 'jest/helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
2020-03-13 15:44:24 +05:30
import Tracking from '~/tracking';
import component from '~/registry/explorer/pages/details.vue';
2020-06-23 00:09:42 +05:30
import DeleteAlert from '~/registry/explorer/components/details_page/delete_alert.vue';
2021-01-03 14:25:43 +05:30
import PartialCleanupAlert from '~/registry/explorer/components/details_page/partial_cleanup_alert.vue';
2020-06-23 00:09:42 +05:30
import DetailsHeader from '~/registry/explorer/components/details_page/details_header.vue';
import TagsLoader from '~/registry/explorer/components/details_page/tags_loader.vue';
2020-07-28 23:09:34 +05:30
import TagsList from '~/registry/explorer/components/details_page/tags_list.vue';
2020-06-23 00:09:42 +05:30
import EmptyTagsState from '~/registry/explorer/components/details_page/empty_tags_state.vue';
2021-02-22 17:27:13 +05:30
import getContainerRepositoryDetailsQuery from '~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
import deleteContainerRepositoryTagsMutation from '~/registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql';
2020-05-24 23:13:21 +05:30
import {
2021-02-22 17:27:13 +05:30
graphQLImageDetailsMock,
graphQLImageDetailsEmptyTagsMock,
graphQLDeleteImageRepositoryTagsMock,
containerRepositoryMock,
tagsMock,
tagsPageInfo,
} from '../mock_data';
2020-07-28 23:09:34 +05:30
import { DeleteModal } from '../stubs';
2020-03-13 15:44:24 +05:30
2021-02-22 17:27:13 +05:30
const localVue = createLocalVue();
2020-03-13 15:44:24 +05:30
describe('Details Page', () => {
let wrapper;
2021-02-22 17:27:13 +05:30
let apolloProvider;
2020-03-13 15:44:24 +05:30
2020-06-23 00:09:42 +05:30
const findDeleteModal = () => wrapper.find(DeleteModal);
2021-02-22 17:27:13 +05:30
const findPagination = () => wrapper.find(GlKeysetPagination);
2020-06-23 00:09:42 +05:30
const findTagsLoader = () => wrapper.find(TagsLoader);
2020-07-28 23:09:34 +05:30
const findTagsList = () => wrapper.find(TagsList);
2020-06-23 00:09:42 +05:30
const findDeleteAlert = () => wrapper.find(DeleteAlert);
const findDetailsHeader = () => wrapper.find(DetailsHeader);
const findEmptyTagsState = () => wrapper.find(EmptyTagsState);
2021-01-03 14:25:43 +05:30
const findPartialCleanupAlert = () => wrapper.find(PartialCleanupAlert);
2020-03-13 15:44:24 +05:30
2021-01-29 00:20:46 +05:30
const routeId = 1;
2020-03-13 15:44:24 +05:30
2021-02-22 17:27:13 +05:30
const breadCrumbState = {
updateName: jest.fn(),
};
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 wrapper.vm.$nextTick();
};
2020-07-28 23:09:34 +05:30
const tagsArrayToSelectedTags = tags =>
tags.reduce((acc, c) => {
acc[c.name] = true;
return acc;
}, {});
2021-02-22 17:27:13 +05:30
const mountComponent = ({
resolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock()),
mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock),
options,
config = {},
} = {}) => {
localVue.use(VueApollo);
const requestHandlers = [
[getContainerRepositoryDetailsQuery, resolver],
[deleteContainerRepositoryTagsMutation, mutationResolver],
];
apolloProvider = createMockApollo(requestHandlers);
2020-06-23 00:09:42 +05:30
wrapper = shallowMount(component, {
2021-02-22 17:27:13 +05:30
localVue,
apolloProvider,
2020-03-13 15:44:24 +05:30
stubs: {
2020-06-23 00:09:42 +05:30
DeleteModal,
2020-03-13 15:44:24 +05:30
},
mocks: {
$route: {
params: {
2021-01-29 00:20:46 +05:30
id: routeId,
2020-03-13 15:44:24 +05:30
},
},
},
2021-02-22 17:27:13 +05:30
provide() {
return {
breadCrumbState,
config,
};
},
2020-04-22 19:07:51 +05:30
...options,
2020-03-13 15:44:24 +05:30
});
2020-04-22 19:07:51 +05:30
};
beforeEach(() => {
2020-03-13 15:44:24 +05:30
jest.spyOn(Tracking, 'event');
});
afterEach(() => {
wrapper.destroy();
2020-05-24 23:13:21 +05:30
wrapper = null;
2020-03-13 15:44:24 +05:30
});
describe('when isLoading is true', () => {
2021-02-22 17:27:13 +05:30
it('shows the loader', () => {
2020-07-28 23:09:34 +05:30
mountComponent();
2020-03-13 15:44:24 +05:30
2020-07-28 23:09:34 +05:30
expect(findTagsLoader().exists()).toBe(true);
});
it('does not show the list', () => {
2021-02-22 17:27:13 +05:30
mountComponent();
2020-07-28 23:09:34 +05:30
expect(findTagsList().exists()).toBe(false);
2020-03-13 15:44:24 +05:30
});
2020-04-22 19:07:51 +05:30
it('does not show pagination', () => {
2021-02-22 17:27:13 +05:30
mountComponent();
2020-04-22 19:07:51 +05:30
expect(findPagination().exists()).toBe(false);
});
2020-03-13 15:44:24 +05:30
});
2020-07-28 23:09:34 +05:30
describe('when the list of tags is empty', () => {
2021-02-22 17:27:13 +05:30
const resolver = jest.fn().mockResolvedValue(graphQLImageDetailsEmptyTagsMock);
it('has the empty state', async () => {
mountComponent({ resolver });
await waitForApolloRequestRender();
2020-04-22 19:07:51 +05:30
2020-06-23 00:09:42 +05:30
expect(findEmptyTagsState().exists()).toBe(true);
2020-03-13 15:44:24 +05:30
});
2021-02-22 17:27:13 +05:30
it('does not show the loader', async () => {
mountComponent({ resolver });
await waitForApolloRequestRender();
2020-07-28 23:09:34 +05:30
expect(findTagsLoader().exists()).toBe(false);
});
2021-02-22 17:27:13 +05:30
it('does not show the list', async () => {
mountComponent({ resolver });
await waitForApolloRequestRender();
2020-07-28 23:09:34 +05:30
expect(findTagsList().exists()).toBe(false);
2020-03-13 15:44:24 +05:30
});
2020-06-23 00:09:42 +05:30
});
2020-03-13 15:44:24 +05:30
2020-07-28 23:09:34 +05:30
describe('list', () => {
2021-02-22 17:27:13 +05:30
it('exists', async () => {
2020-06-23 00:09:42 +05:30
mountComponent();
2020-03-13 15:44:24 +05:30
2021-02-22 17:27:13 +05:30
await waitForApolloRequestRender();
2020-07-28 23:09:34 +05:30
expect(findTagsList().exists()).toBe(true);
2020-06-23 00:09:42 +05:30
});
2020-03-13 15:44:24 +05:30
2021-02-22 17:27:13 +05:30
it('has the correct props bound', async () => {
mountComponent();
await waitForApolloRequestRender();
2020-07-28 23:09:34 +05:30
expect(findTagsList().props()).toMatchObject({
2021-01-29 00:20:46 +05:30
isMobile: false,
2021-02-22 17:27:13 +05:30
tags: cleanTags,
2020-03-13 15:44:24 +05:30
});
2020-06-23 00:09:42 +05:30
});
2020-03-13 15:44:24 +05:30
2020-06-23 00:09:42 +05:30
describe('deleteEvent', () => {
describe('single item', () => {
2020-07-28 23:09:34 +05:30
let tagToBeDeleted;
2021-02-22 17:27:13 +05:30
beforeEach(async () => {
mountComponent();
await waitForApolloRequestRender();
[tagToBeDeleted] = cleanTags;
2020-07-28 23:09:34 +05:30
findTagsList().vm.$emit('delete', { [tagToBeDeleted.name]: true });
2020-03-13 15:44:24 +05:30
});
2021-02-22 17:27:13 +05:30
it('open the modal', async () => {
2020-06-23 00:09:42 +05:30
expect(DeleteModal.methods.show).toHaveBeenCalled();
2020-03-13 15:44:24 +05:30
});
2020-06-23 00:09:42 +05:30
it('tracks a single delete event', () => {
2020-03-13 15:44:24 +05:30
expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
label: 'registry_tag_delete',
});
});
});
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
describe('multiple items', () => {
2021-02-22 17:27:13 +05:30
beforeEach(async () => {
mountComponent();
await waitForApolloRequestRender();
findTagsList().vm.$emit('delete', tagsArrayToSelectedTags(cleanTags));
2020-04-22 19:07:51 +05:30
});
2020-06-23 00:09:42 +05:30
it('open the modal', () => {
expect(DeleteModal.methods.show).toHaveBeenCalled();
2020-04-22 19:07:51 +05:30
});
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
it('tracks a single delete event', () => {
expect(Tracking.event).toHaveBeenCalledWith(undefined, 'click_button', {
label: 'bulk_registry_tag_delete',
2020-04-22 19:07:51 +05:30
});
});
});
});
2020-03-13 15:44:24 +05:30
});
describe('pagination', () => {
2021-02-22 17:27:13 +05:30
it('exists', async () => {
2020-04-22 19:07:51 +05:30
mountComponent();
2021-02-22 17:27:13 +05:30
await waitForApolloRequestRender();
2020-03-13 15:44:24 +05:30
expect(findPagination().exists()).toBe(true);
});
2021-02-22 17:27:13 +05:30
it('is hidden when there are no more pages', async () => {
mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLImageDetailsEmptyTagsMock) });
await waitForApolloRequestRender();
expect(findPagination().exists()).toBe(false);
2020-03-13 15:44:24 +05:30
});
2021-02-22 17:27:13 +05:30
it('is wired to the correct pagination props', async () => {
mountComponent();
await waitForApolloRequestRender();
expect(findPagination().props()).toMatchObject({
hasNextPage: tagsPageInfo.hasNextPage,
hasPreviousPage: tagsPageInfo.hasPreviousPage,
2020-03-13 15:44:24 +05:30
});
});
2021-02-22 17:27:13 +05:30
it('fetch next page when user clicks next', async () => {
const resolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock());
mountComponent({ resolver });
await waitForApolloRequestRender();
findPagination().vm.$emit('next');
expect(resolver).toHaveBeenCalledWith(
expect.objectContaining({ after: tagsPageInfo.endCursor }),
);
});
it('fetch previous page when user clicks prev', async () => {
const resolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock());
mountComponent({ resolver });
await waitForApolloRequestRender();
findPagination().vm.$emit('prev');
expect(resolver).toHaveBeenCalledWith(
expect.objectContaining({ first: null, before: tagsPageInfo.startCursor }),
);
});
2020-03-13 15:44:24 +05:30
});
describe('modal', () => {
2021-02-22 17:27:13 +05:30
it('exists', async () => {
2020-06-23 00:09:42 +05:30
mountComponent();
2021-02-22 17:27:13 +05:30
await waitForApolloRequestRender();
2020-03-13 15:44:24 +05:30
expect(findDeleteModal().exists()).toBe(true);
});
2020-06-23 00:09:42 +05:30
describe('cancel event', () => {
2021-02-22 17:27:13 +05:30
it('tracks cancel_delete', async () => {
2020-06-23 00:09:42 +05:30
mountComponent();
2021-02-22 17:27:13 +05:30
await waitForApolloRequestRender();
2020-06-23 00:09:42 +05:30
findDeleteModal().vm.$emit('cancel');
2021-02-22 17:27:13 +05:30
2020-06-23 00:09:42 +05:30
expect(Tracking.event).toHaveBeenCalledWith(undefined, 'cancel_delete', {
label: 'registry_tag_delete',
2020-03-13 15:44:24 +05:30
});
});
2020-06-23 00:09:42 +05:30
});
2020-03-13 15:44:24 +05:30
2020-06-23 00:09:42 +05:30
describe('confirmDelete event', () => {
2021-02-22 17:27:13 +05:30
let mutationResolver;
beforeEach(() => {
mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
mountComponent({ mutationResolver });
return waitForApolloRequestRender();
});
2020-06-23 00:09:42 +05:30
describe('when one item is selected to be deleted', () => {
2021-02-22 17:27:13 +05:30
it('calls apollo mutation with the right parameters', async () => {
findTagsList().vm.$emit('delete', { [cleanTags[0].name]: true });
await wrapper.vm.$nextTick();
2020-03-13 15:44:24 +05:30
2020-06-23 00:09:42 +05:30
findDeleteModal().vm.$emit('confirmDelete');
2021-02-22 17:27:13 +05:30
expect(mutationResolver).toHaveBeenCalledWith(
expect.objectContaining({ tagNames: [cleanTags[0].name] }),
);
2020-03-13 15:44:24 +05:30
});
});
2020-06-23 00:09:42 +05:30
describe('when more than one item is selected to be deleted', () => {
2021-02-22 17:27:13 +05:30
it('calls apollo mutation with the right parameters', async () => {
findTagsList().vm.$emit('delete', { ...tagsArrayToSelectedTags(tagsMock) });
await wrapper.vm.$nextTick();
2020-03-13 15:44:24 +05:30
2020-06-23 00:09:42 +05:30
findDeleteModal().vm.$emit('confirmDelete');
2021-02-22 17:27:13 +05:30
expect(mutationResolver).toHaveBeenCalledWith(
expect.objectContaining({ tagNames: tagsMock.map(t => t.name) }),
);
2020-03-13 15:44:24 +05:30
});
});
});
2020-06-23 00:09:42 +05:30
});
2020-03-13 15:44:24 +05:30
2020-06-23 00:09:42 +05:30
describe('Header', () => {
2021-02-22 17:27:13 +05:30
it('exists', async () => {
2020-06-23 00:09:42 +05:30
mountComponent();
2021-02-22 17:27:13 +05:30
await waitForApolloRequestRender();
2020-06-23 00:09:42 +05:30
expect(findDetailsHeader().exists()).toBe(true);
});
2021-02-22 17:27:13 +05:30
it('has the correct props', async () => {
2020-06-23 00:09:42 +05:30
mountComponent();
2021-02-22 17:27:13 +05:30
await waitForApolloRequestRender();
expect(findDetailsHeader().props('image')).toMatchObject({
name: containerRepositoryMock.name,
project: {
visibility: containerRepositoryMock.project.visibility,
},
});
2020-03-13 15:44:24 +05:30
});
});
2020-05-24 23:13:21 +05:30
2020-06-23 00:09:42 +05:30
describe('Delete Alert', () => {
2020-05-24 23:13:21 +05:30
const config = {
2020-06-23 00:09:42 +05:30
isAdmin: true,
garbageCollectionHelpPagePath: 'baz',
2020-05-24 23:13:21 +05:30
};
2020-06-23 00:09:42 +05:30
const deleteAlertType = 'success_tag';
2020-05-24 23:13:21 +05:30
2021-02-22 17:27:13 +05:30
it('exists', async () => {
2020-06-23 00:09:42 +05:30
mountComponent();
2021-02-22 17:27:13 +05:30
await waitForApolloRequestRender();
2020-06-23 00:09:42 +05:30
expect(findDeleteAlert().exists()).toBe(true);
});
2020-05-24 23:13:21 +05:30
2021-02-22 17:27:13 +05:30
it('has the correct props', async () => {
2020-06-23 00:09:42 +05:30
mountComponent({
2021-01-03 14:25:43 +05:30
options: {
data: () => ({
deleteAlertType,
}),
},
2021-02-22 17:27:13 +05:30
config,
2020-05-24 23:13:21 +05:30
});
2021-02-22 17:27:13 +05:30
await waitForApolloRequestRender();
2020-06-23 00:09:42 +05:30
expect(findDeleteAlert().props()).toEqual({ ...config, deleteAlertType });
2020-05-24 23:13:21 +05:30
});
});
2021-01-03 14:25:43 +05:30
describe('Partial Cleanup Alert', () => {
const config = {
runCleanupPoliciesHelpPagePath: 'foo',
cleanupPoliciesHelpPagePath: 'bar',
};
describe('when expiration_policy_started is not null', () => {
2021-02-22 17:27:13 +05:30
let resolver;
2021-01-29 00:20:46 +05:30
beforeEach(() => {
2021-02-22 17:27:13 +05:30
resolver = jest.fn().mockResolvedValue(
graphQLImageDetailsMock({
expirationPolicyStartedAt: Date.now().toString(),
}),
);
2021-01-29 00:20:46 +05:30
});
2021-02-22 17:27:13 +05:30
it('exists', async () => {
mountComponent({ resolver });
await waitForApolloRequestRender();
2021-01-03 14:25:43 +05:30
expect(findPartialCleanupAlert().exists()).toBe(true);
});
2021-02-22 17:27:13 +05:30
it('has the correct props', async () => {
mountComponent({ resolver, config });
2021-01-03 14:25:43 +05:30
2021-02-22 17:27:13 +05:30
await waitForApolloRequestRender();
2021-01-03 14:25:43 +05:30
expect(findPartialCleanupAlert().props()).toEqual({ ...config });
});
it('dismiss hides the component', async () => {
2021-02-22 17:27:13 +05:30
mountComponent({ resolver });
await waitForApolloRequestRender();
2021-01-03 14:25:43 +05:30
expect(findPartialCleanupAlert().exists()).toBe(true);
2021-02-22 17:27:13 +05:30
2021-01-03 14:25:43 +05:30
findPartialCleanupAlert().vm.$emit('dismiss');
await wrapper.vm.$nextTick();
expect(findPartialCleanupAlert().exists()).toBe(false);
});
});
describe('when expiration_policy_started is null', () => {
2021-02-22 17:27:13 +05:30
it('the component is hidden', async () => {
2021-01-03 14:25:43 +05:30
mountComponent();
2021-02-22 17:27:13 +05:30
await waitForApolloRequestRender();
2021-01-03 14:25:43 +05:30
expect(findPartialCleanupAlert().exists()).toBe(false);
});
});
});
2021-02-22 17:27:13 +05:30
describe('Breadcrumb connection', () => {
it('when the details are fetched updates the name', async () => {
mountComponent();
await waitForApolloRequestRender();
expect(breadCrumbState.updateName).toHaveBeenCalledWith(containerRepositoryMock.name);
});
});
2020-03-13 15:44:24 +05:30
});