diff options
Diffstat (limited to 'spec/frontend/registry/explorer/pages/details_spec.js')
-rw-r--r-- | spec/frontend/registry/explorer/pages/details_spec.js | 521 |
1 files changed, 0 insertions, 521 deletions
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/registry/explorer/pages/details_spec.js deleted file mode 100644 index 21af9dcc60f..00000000000 --- a/spec/frontend/registry/explorer/pages/details_spec.js +++ /dev/null @@ -1,521 +0,0 @@ -import { GlKeysetPagination } from '@gitlab/ui'; -import { shallowMount, createLocalVue } from '@vue/test-utils'; -import VueApollo from 'vue-apollo'; -import createMockApollo from 'helpers/mock_apollo_helper'; -import waitForPromises from 'helpers/wait_for_promises'; -import axios from '~/lib/utils/axios_utils'; -import DeleteImage from '~/registry/explorer/components/delete_image.vue'; -import DeleteAlert from '~/registry/explorer/components/details_page/delete_alert.vue'; -import DetailsHeader from '~/registry/explorer/components/details_page/details_header.vue'; -import EmptyTagsState from '~/registry/explorer/components/details_page/empty_state.vue'; -import PartialCleanupAlert from '~/registry/explorer/components/details_page/partial_cleanup_alert.vue'; -import StatusAlert from '~/registry/explorer/components/details_page/status_alert.vue'; -import TagsList from '~/registry/explorer/components/details_page/tags_list.vue'; -import TagsLoader from '~/registry/explorer/components/details_page/tags_loader.vue'; - -import { - UNFINISHED_STATUS, - DELETE_SCHEDULED, - ALERT_DANGER_IMAGE, - MISSING_OR_DELETED_IMAGE_BREADCRUMB, - ROOT_IMAGE_TEXT, -} from '~/registry/explorer/constants'; -import deleteContainerRepositoryTagsMutation from '~/registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql'; -import getContainerRepositoryDetailsQuery from '~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql'; - -import component from '~/registry/explorer/pages/details.vue'; -import Tracking from '~/tracking'; - -import { - graphQLImageDetailsMock, - graphQLDeleteImageRepositoryTagsMock, - containerRepositoryMock, - graphQLEmptyImageDetailsMock, - tagsMock, -} from '../mock_data'; -import { DeleteModal } from '../stubs'; - -const localVue = createLocalVue(); - -describe('Details Page', () => { - let wrapper; - let apolloProvider; - - const findDeleteModal = () => wrapper.find(DeleteModal); - const findPagination = () => wrapper.find(GlKeysetPagination); - const findTagsLoader = () => wrapper.find(TagsLoader); - const findTagsList = () => wrapper.find(TagsList); - const findDeleteAlert = () => wrapper.find(DeleteAlert); - const findDetailsHeader = () => wrapper.find(DetailsHeader); - const findEmptyState = () => wrapper.find(EmptyTagsState); - const findPartialCleanupAlert = () => wrapper.find(PartialCleanupAlert); - const findStatusAlert = () => wrapper.find(StatusAlert); - const findDeleteImage = () => wrapper.find(DeleteImage); - - const routeId = 1; - - 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(); - }; - - 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); - - wrapper = shallowMount(component, { - localVue, - apolloProvider, - stubs: { - DeleteModal, - DeleteImage, - }, - mocks: { - $route: { - params: { - id: routeId, - }, - }, - }, - provide() { - return { - breadCrumbState, - config, - }; - }, - ...options, - }); - }; - - beforeEach(() => { - jest.spyOn(Tracking, 'event'); - }); - - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - - describe('when isLoading is true', () => { - it('shows the loader', () => { - mountComponent(); - - expect(findTagsLoader().exists()).toBe(true); - }); - - it('does not show the list', () => { - mountComponent(); - - expect(findTagsList().exists()).toBe(false); - }); - }); - - describe('when the image does not exist', () => { - it('does not show the default ui', async () => { - mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLEmptyImageDetailsMock) }); - - await waitForApolloRequestRender(); - - expect(findTagsLoader().exists()).toBe(false); - expect(findDetailsHeader().exists()).toBe(false); - expect(findTagsList().exists()).toBe(false); - expect(findPagination().exists()).toBe(false); - }); - - it('shows an empty state message', async () => { - mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLEmptyImageDetailsMock) }); - - await waitForApolloRequestRender(); - - expect(findEmptyState().exists()).toBe(true); - }); - }); - - describe('list', () => { - it('exists', async () => { - mountComponent(); - - await waitForApolloRequestRender(); - - expect(findTagsList().exists()).toBe(true); - }); - - it('has the correct props bound', async () => { - mountComponent(); - - await waitForApolloRequestRender(); - - expect(findTagsList().props()).toMatchObject({ - 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', () => { - 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; - - beforeEach(() => { - mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock); - mountComponent({ mutationResolver }); - - return waitForApolloRequestRender(); - }); - describe('when one item is selected to be deleted', () => { - it('calls apollo mutation with the right parameters', async () => { - findTagsList().vm.$emit('delete', [cleanTags[0]]); - - await wrapper.vm.$nextTick(); - - findDeleteModal().vm.$emit('confirmDelete'); - - expect(mutationResolver).toHaveBeenCalledWith( - expect.objectContaining({ tagNames: [cleanTags[0].name] }), - ); - }); - }); - - describe('when more than one item is selected to be deleted', () => { - it('calls apollo mutation with the right parameters', async () => { - findTagsList().vm.$emit('delete', tagsMock); - - await wrapper.vm.$nextTick(); - - findDeleteModal().vm.$emit('confirmDelete'); - - expect(mutationResolver).toHaveBeenCalledWith( - expect.objectContaining({ tagNames: tagsMock.map((t) => t.name) }), - ); - }); - }); - }); - }); - - describe('Header', () => { - it('exists', async () => { - mountComponent(); - - await waitForApolloRequestRender(); - expect(findDetailsHeader().exists()).toBe(true); - }); - - it('has the correct props', async () => { - mountComponent(); - - await waitForApolloRequestRender(); - expect(findDetailsHeader().props()).toMatchObject({ - image: { - name: containerRepositoryMock.name, - project: { - visibility: containerRepositoryMock.project.visibility, - }, - }, - }); - }); - }); - - describe('Delete Alert', () => { - const config = { - isAdmin: true, - garbageCollectionHelpPagePath: 'baz', - }; - const deleteAlertType = 'success_tag'; - - it('exists', async () => { - mountComponent(); - - await waitForApolloRequestRender(); - expect(findDeleteAlert().exists()).toBe(true); - }); - - it('has the correct props', async () => { - mountComponent({ - options: { - data: () => ({ - deleteAlertType, - }), - }, - config, - }); - - await waitForApolloRequestRender(); - - expect(findDeleteAlert().props()).toEqual({ ...config, deleteAlertType }); - }); - }); - - describe('Partial Cleanup Alert', () => { - const config = { - runCleanupPoliciesHelpPagePath: 'foo', - expirationPolicyHelpPagePath: 'bar', - userCalloutsPath: 'call_out_path', - userCalloutId: 'call_out_id', - showUnfinishedTagCleanupCallout: true, - }; - - describe(`when expirationPolicyCleanupStatus is ${UNFINISHED_STATUS}`, () => { - let resolver; - - beforeEach(() => { - resolver = jest.fn().mockResolvedValue( - graphQLImageDetailsMock({ - expirationPolicyCleanupStatus: UNFINISHED_STATUS, - }), - ); - }); - - it('exists', async () => { - mountComponent({ resolver, config }); - - await waitForApolloRequestRender(); - - expect(findPartialCleanupAlert().exists()).toBe(true); - }); - - it('has the correct props', async () => { - mountComponent({ resolver, config }); - - await waitForApolloRequestRender(); - - expect(findPartialCleanupAlert().props()).toEqual({ - runCleanupPoliciesHelpPagePath: config.runCleanupPoliciesHelpPagePath, - cleanupPoliciesHelpPagePath: config.expirationPolicyHelpPagePath, - }); - }); - - it('dismiss hides the component', async () => { - jest.spyOn(axios, 'post').mockReturnValue(); - - mountComponent({ resolver, config }); - - await waitForApolloRequestRender(); - - expect(findPartialCleanupAlert().exists()).toBe(true); - - findPartialCleanupAlert().vm.$emit('dismiss'); - - await wrapper.vm.$nextTick(); - - expect(axios.post).toHaveBeenCalledWith(config.userCalloutsPath, { - feature_name: config.userCalloutId, - }); - expect(findPartialCleanupAlert().exists()).toBe(false); - }); - - it('is hidden if the callout is dismissed', async () => { - mountComponent({ resolver }); - - await waitForApolloRequestRender(); - - expect(findPartialCleanupAlert().exists()).toBe(false); - }); - }); - - describe(`when expirationPolicyCleanupStatus is not ${UNFINISHED_STATUS}`, () => { - it('the component is hidden', async () => { - mountComponent({ config }); - - await waitForApolloRequestRender(); - - expect(findPartialCleanupAlert().exists()).toBe(false); - }); - }); - }); - - describe('Breadcrumb connection', () => { - it('when the details are fetched updates the name', async () => { - mountComponent(); - - await waitForApolloRequestRender(); - - expect(breadCrumbState.updateName).toHaveBeenCalledWith(containerRepositoryMock.name); - }); - - it(`when the image is missing set the breadcrumb to ${MISSING_OR_DELETED_IMAGE_BREADCRUMB}`, async () => { - mountComponent({ resolver: jest.fn().mockResolvedValue(graphQLEmptyImageDetailsMock) }); - - await waitForApolloRequestRender(); - - expect(breadCrumbState.updateName).toHaveBeenCalledWith(MISSING_OR_DELETED_IMAGE_BREADCRUMB); - }); - - it(`when the image has no name set the breadcrumb to ${ROOT_IMAGE_TEXT}`, async () => { - mountComponent({ - resolver: jest - .fn() - .mockResolvedValue(graphQLImageDetailsMock({ ...containerRepositoryMock, name: null })), - }); - - await waitForApolloRequestRender(); - - expect(breadCrumbState.updateName).toHaveBeenCalledWith(ROOT_IMAGE_TEXT); - }); - }); - - describe('when the image has a status different from null', () => { - const resolver = jest - .fn() - .mockResolvedValue(graphQLImageDetailsMock({ status: DELETE_SCHEDULED })); - it('disables all the actions', async () => { - mountComponent({ resolver }); - - await waitForApolloRequestRender(); - - expect(findDetailsHeader().props('disabled')).toBe(true); - expect(findTagsList().props('disabled')).toBe(true); - }); - - it('shows a status alert', async () => { - mountComponent({ resolver }); - - await waitForApolloRequestRender(); - - expect(findStatusAlert().exists()).toBe(true); - expect(findStatusAlert().props()).toMatchObject({ - status: DELETE_SCHEDULED, - }); - }); - }); - - describe('delete the image', () => { - const mountComponentAndDeleteImage = async () => { - mountComponent(); - - await waitForApolloRequestRender(); - findDetailsHeader().vm.$emit('delete'); - - await wrapper.vm.$nextTick(); - }; - - it('on delete event it deletes the image', async () => { - await mountComponentAndDeleteImage(); - - findDeleteModal().vm.$emit('confirmDelete'); - - expect(findDeleteImage().emitted('start')).toEqual([[]]); - }); - - it('binds the correct props to the modal', async () => { - await mountComponentAndDeleteImage(); - - expect(findDeleteModal().props()).toMatchObject({ - itemsToBeDeleted: [{ path: 'gitlab-org/gitlab-test/rails-12009' }], - deleteImage: true, - }); - }); - - it('binds correctly to delete-image start and end events', async () => { - mountComponent(); - - findDeleteImage().vm.$emit('start'); - - await wrapper.vm.$nextTick(); - - expect(findTagsLoader().exists()).toBe(true); - - findDeleteImage().vm.$emit('end'); - - await wrapper.vm.$nextTick(); - - expect(findTagsLoader().exists()).toBe(false); - }); - - it('binds correctly to delete-image error event', async () => { - mountComponent(); - - findDeleteImage().vm.$emit('error'); - - await wrapper.vm.$nextTick(); - - expect(findDeleteAlert().props('deleteAlertType')).toBe(ALERT_DANGER_IMAGE); - }); - }); -}); |