diff options
Diffstat (limited to 'spec/frontend/packages_and_registries/package_registry/pages/details_spec.js')
-rw-r--r-- | spec/frontend/packages_and_registries/package_registry/pages/details_spec.js | 187 |
1 files changed, 174 insertions, 13 deletions
diff --git a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js index 3cadb001c58..de78e6bb87b 100644 --- a/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/pages/details_spec.js @@ -22,6 +22,8 @@ import { PACKAGE_TYPE_COMPOSER, DELETE_PACKAGE_FILE_SUCCESS_MESSAGE, DELETE_PACKAGE_FILE_ERROR_MESSAGE, + DELETE_PACKAGE_FILES_SUCCESS_MESSAGE, + DELETE_PACKAGE_FILES_ERROR_MESSAGE, PACKAGE_TYPE_NUGET, PACKAGE_TYPE_MAVEN, PACKAGE_TYPE_CONAN, @@ -29,7 +31,7 @@ import { PACKAGE_TYPE_NPM, } from '~/packages_and_registries/package_registry/constants'; -import destroyPackageFileMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_file.mutation.graphql'; +import destroyPackageFilesMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_package_files.mutation.graphql'; import getPackageDetails from '~/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql'; import { packageDetailsQuery, @@ -38,8 +40,8 @@ import { dependencyLinks, emptyPackageDetailsQuery, packageFiles, - packageDestroyFileMutation, - packageDestroyFileMutationError, + packageDestroyFilesMutation, + packageDestroyFilesMutationError, } from '../mock_data'; jest.mock('~/flash'); @@ -58,6 +60,7 @@ describe('PackagesApp', () => { emptyListIllustration: 'svgPath', projectListUrl: 'projectListUrl', groupListUrl: 'groupListUrl', + isGroupPage: false, breadCrumbState, }; @@ -65,14 +68,14 @@ describe('PackagesApp', () => { function createComponent({ resolver = jest.fn().mockResolvedValue(packageDetailsQuery()), - fileDeleteMutationResolver = jest.fn().mockResolvedValue(packageDestroyFileMutation()), + filesDeleteMutationResolver = jest.fn().mockResolvedValue(packageDestroyFilesMutation()), routeId = '1', } = {}) { Vue.use(VueApollo); const requestHandlers = [ [getPackageDetails, resolver], - [destroyPackageFileMutation, fileDeleteMutationResolver], + [destroyPackageFilesMutation, filesDeleteMutationResolver], ]; apolloProvider = createMockApollo(requestHandlers); @@ -110,6 +113,7 @@ describe('PackagesApp', () => { const findDeleteButton = () => wrapper.findByTestId('delete-package'); const findPackageFiles = () => wrapper.findComponent(PackageFiles); const findDeleteFileModal = () => wrapper.findByTestId('delete-file-modal'); + const findDeleteFilesModal = () => wrapper.findByTestId('delete-files-modal'); const findVersionRows = () => wrapper.findAllComponents(VersionRow); const noVersionsMessage = () => wrapper.findByTestId('no-versions-message'); const findDependenciesCountBadge = () => wrapper.findComponent(GlBadge); @@ -288,6 +292,7 @@ describe('PackagesApp', () => { expect(findPackageFiles().props('packageFiles')[0]).toMatchObject(expectedFile); expect(findPackageFiles().props('canDelete')).toBe(packageData().canDestroy); + expect(findPackageFiles().props('isLoading')).toEqual(false); }); it('does not render the package files table when the package is composer', async () => { @@ -305,24 +310,69 @@ describe('PackagesApp', () => { describe('deleting a file', () => { const [fileToDelete] = packageFiles(); - const doDeleteFile = () => { - findPackageFiles().vm.$emit('delete-file', fileToDelete); + const doDeleteFile = async () => { + findPackageFiles().vm.$emit('delete-files', [fileToDelete]); findDeleteFileModal().vm.$emit('primary'); return waitForPromises(); }; - it('opens a confirmation modal', async () => { + it('opens delete file confirmation modal', async () => { createComponent(); await waitForPromises(); - findPackageFiles().vm.$emit('delete-file', fileToDelete); + const showDeleteFileSpy = jest.spyOn(wrapper.vm.$refs.deleteFileModal, 'show'); + const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show'); + + findPackageFiles().vm.$emit('delete-files', [fileToDelete]); + + expect(showDeletePackageSpy).not.toBeCalled(); + expect(showDeleteFileSpy).toBeCalled(); + }); + + it('when its the only file opens delete package confirmation modal', async () => { + const [packageFile] = packageFiles(); + const resolver = jest.fn().mockResolvedValue( + packageDetailsQuery({ + packageFiles: { + pageInfo: { + hasNextPage: false, + }, + nodes: [packageFile], + __typename: 'PackageFileConnection', + }, + }), + ); + + createComponent({ + resolver, + }); + + await waitForPromises(); + + const showDeleteFileSpy = jest.spyOn(wrapper.vm.$refs.deleteFileModal, 'show'); + const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show'); + + findPackageFiles().vm.$emit('delete-files', [fileToDelete]); + + expect(showDeletePackageSpy).toBeCalled(); + expect(showDeleteFileSpy).not.toBeCalled(); + }); + + it('confirming on the modal sets the loading state', async () => { + createComponent(); + + await waitForPromises(); + + findPackageFiles().vm.$emit('delete-files', [fileToDelete]); + + findDeleteFileModal().vm.$emit('primary'); await nextTick(); - expect(findDeleteFileModal().exists()).toBe(true); + expect(findPackageFiles().props('isLoading')).toEqual(true); }); it('confirming on the modal deletes the file and shows a success message', async () => { @@ -344,7 +394,7 @@ describe('PackagesApp', () => { describe('errors', () => { it('shows an error when the mutation request fails', async () => { - createComponent({ fileDeleteMutationResolver: jest.fn().mockRejectedValue() }); + createComponent({ filesDeleteMutationResolver: jest.fn().mockRejectedValue() }); await waitForPromises(); await doDeleteFile(); @@ -358,9 +408,9 @@ describe('PackagesApp', () => { it('shows an error when the mutation request returns an error payload', async () => { createComponent({ - fileDeleteMutationResolver: jest + filesDeleteMutationResolver: jest .fn() - .mockResolvedValue(packageDestroyFileMutationError()), + .mockResolvedValue(packageDestroyFilesMutationError()), }); await waitForPromises(); @@ -374,6 +424,117 @@ describe('PackagesApp', () => { }); }); }); + + describe('deleting multiple files', () => { + const doDeleteFiles = async () => { + findPackageFiles().vm.$emit('delete-files', packageFiles()); + + findDeleteFilesModal().vm.$emit('primary'); + + return waitForPromises(); + }; + + it('opens delete files confirmation modal', async () => { + createComponent(); + + await waitForPromises(); + + const showDeleteFilesSpy = jest.spyOn(wrapper.vm.$refs.deleteFilesModal, 'show'); + + findPackageFiles().vm.$emit('delete-files', packageFiles()); + + expect(showDeleteFilesSpy).toBeCalled(); + }); + + it('confirming on the modal sets the loading state', async () => { + createComponent(); + + await waitForPromises(); + + findPackageFiles().vm.$emit('delete-files', packageFiles()); + + findDeleteFilesModal().vm.$emit('primary'); + + await nextTick(); + + expect(findPackageFiles().props('isLoading')).toEqual(true); + }); + + it('confirming on the modal deletes the file and shows a success message', async () => { + const resolver = jest.fn().mockResolvedValue(packageDetailsQuery()); + createComponent({ resolver }); + + await waitForPromises(); + + await doDeleteFiles(); + + expect(createFlash).toHaveBeenCalledWith( + expect.objectContaining({ + message: DELETE_PACKAGE_FILES_SUCCESS_MESSAGE, + }), + ); + // we are re-fetching the package details, so we expect the resolver to have been called twice + expect(resolver).toHaveBeenCalledTimes(2); + }); + + describe('errors', () => { + it('shows an error when the mutation request fails', async () => { + createComponent({ filesDeleteMutationResolver: jest.fn().mockRejectedValue() }); + await waitForPromises(); + + await doDeleteFiles(); + + expect(createFlash).toHaveBeenCalledWith( + expect.objectContaining({ + message: DELETE_PACKAGE_FILES_ERROR_MESSAGE, + }), + ); + }); + + it('shows an error when the mutation request returns an error payload', async () => { + createComponent({ + filesDeleteMutationResolver: jest + .fn() + .mockResolvedValue(packageDestroyFilesMutationError()), + }); + await waitForPromises(); + + await doDeleteFiles(); + + expect(createFlash).toHaveBeenCalledWith( + expect.objectContaining({ + message: DELETE_PACKAGE_FILES_ERROR_MESSAGE, + }), + ); + }); + }); + }); + + describe('deleting all files', () => { + it('opens the delete package confirmation modal', async () => { + const resolver = jest.fn().mockResolvedValue( + packageDetailsQuery({ + packageFiles: { + pageInfo: { + hasNextPage: false, + }, + nodes: packageFiles(), + }, + }), + ); + createComponent({ + resolver, + }); + + await waitForPromises(); + + const showDeletePackageSpy = jest.spyOn(wrapper.vm.$refs.deleteModal, 'show'); + + findPackageFiles().vm.$emit('delete-files', packageFiles()); + + expect(showDeletePackageSpy).toBeCalled(); + }); + }); }); describe('versions', () => { |