diff options
Diffstat (limited to 'spec/frontend/registry/explorer/pages/details_spec.js')
-rw-r--r-- | spec/frontend/registry/explorer/pages/details_spec.js | 160 |
1 files changed, 146 insertions, 14 deletions
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/registry/explorer/pages/details_spec.js index 1746a6a63b6..65c58bf9874 100644 --- a/spec/frontend/registry/explorer/pages/details_spec.js +++ b/spec/frontend/registry/explorer/pages/details_spec.js @@ -1,27 +1,35 @@ -import { shallowMount, createLocalVue } from '@vue/test-utils'; 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 Tracking from '~/tracking'; -import component from '~/registry/explorer/pages/details.vue'; +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 PartialCleanupAlert from '~/registry/explorer/components/details_page/partial_cleanup_alert.vue'; import DetailsHeader from '~/registry/explorer/components/details_page/details_header.vue'; -import TagsLoader from '~/registry/explorer/components/details_page/tags_loader.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 EmptyTagsState from '~/registry/explorer/components/details_page/empty_tags_state.vue'; +import TagsLoader from '~/registry/explorer/components/details_page/tags_loader.vue'; -import getContainerRepositoryDetailsQuery from '~/registry/explorer/graphql/queries/get_container_repository_details.query.graphql'; +import { + UNFINISHED_STATUS, + DELETE_SCHEDULED, + ALERT_DANGER_IMAGE, +} 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 { UNFINISHED_STATUS } from '~/registry/explorer/constants/index'; +import component from '~/registry/explorer/pages/details.vue'; +import Tracking from '~/tracking'; import { graphQLImageDetailsMock, graphQLImageDetailsEmptyTagsMock, graphQLDeleteImageRepositoryTagsMock, containerRepositoryMock, + graphQLEmptyImageDetailsMock, tagsMock, tagsPageInfo, } from '../mock_data'; @@ -39,8 +47,10 @@ describe('Details Page', () => { const findTagsList = () => wrapper.find(TagsList); const findDeleteAlert = () => wrapper.find(DeleteAlert); const findDetailsHeader = () => wrapper.find(DetailsHeader); - const findEmptyTagsState = () => wrapper.find(EmptyTagsState); + const findEmptyState = () => wrapper.find(EmptyTagsState); const findPartialCleanupAlert = () => wrapper.find(PartialCleanupAlert); + const findStatusAlert = () => wrapper.find(StatusAlert); + const findDeleteImage = () => wrapper.find(DeleteImage); const routeId = 1; @@ -86,6 +96,7 @@ describe('Details Page', () => { apolloProvider, stubs: { DeleteModal, + DeleteImage, }, mocks: { $route: { @@ -133,6 +144,27 @@ describe('Details Page', () => { }); }); + 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('when the list of tags is empty', () => { const resolver = jest.fn().mockResolvedValue(graphQLImageDetailsEmptyTagsMock); @@ -141,7 +173,7 @@ describe('Details Page', () => { await waitForApolloRequestRender(); - expect(findEmptyTagsState().exists()).toBe(true); + expect(findEmptyState().exists()).toBe(true); }); it('does not show the loader', async () => { @@ -401,6 +433,9 @@ describe('Details Page', () => { const config = { runCleanupPoliciesHelpPagePath: 'foo', cleanupPoliciesHelpPagePath: 'bar', + userCalloutsPath: 'call_out_path', + userCalloutId: 'call_out_id', + showUnfinishedTagCleanupCallout: true, }; describe(`when expirationPolicyCleanupStatus is ${UNFINISHED_STATUS}`, () => { @@ -413,8 +448,9 @@ describe('Details Page', () => { }), ); }); + it('exists', async () => { - mountComponent({ resolver }); + mountComponent({ resolver, config }); await waitForApolloRequestRender(); @@ -426,11 +462,16 @@ describe('Details Page', () => { await waitForApolloRequestRender(); - expect(findPartialCleanupAlert().props()).toEqual({ ...config }); + expect(findPartialCleanupAlert().props()).toEqual({ + runCleanupPoliciesHelpPagePath: config.runCleanupPoliciesHelpPagePath, + cleanupPoliciesHelpPagePath: config.cleanupPoliciesHelpPagePath, + }); }); it('dismiss hides the component', async () => { - mountComponent({ resolver }); + jest.spyOn(axios, 'post').mockReturnValue(); + + mountComponent({ resolver, config }); await waitForApolloRequestRender(); @@ -440,13 +481,25 @@ describe('Details Page', () => { 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(); + mountComponent({ config }); + await waitForApolloRequestRender(); expect(findPartialCleanupAlert().exists()).toBe(false); @@ -463,4 +516,83 @@ describe('Details Page', () => { expect(breadCrumbState.updateName).toHaveBeenCalledWith(containerRepositoryMock.name); }); }); + + 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); + }); + }); }); |