diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-02 18:09:59 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-02 18:09:59 +0300 |
commit | 1c2ff01b694fd06be15bc20279eef71ee5adf402 (patch) | |
tree | 98a588172ab8021790538a515933cf83552c5086 /spec/frontend/packages | |
parent | 2e4e6e9bb63212c628e67c6865fa39f62217a83d (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/packages')
4 files changed, 201 insertions, 31 deletions
diff --git a/spec/frontend/packages/details/components/app_spec.js b/spec/frontend/packages/details/components/app_spec.js index 11dad7ba34d..4b890f868f4 100644 --- a/spec/frontend/packages/details/components/app_spec.js +++ b/spec/frontend/packages/details/components/app_spec.js @@ -1,4 +1,4 @@ -import { GlEmptyState, GlModal } from '@gitlab/ui'; +import { GlEmptyState } from '@gitlab/ui'; import { mount, createLocalVue } from '@vue/test-utils'; import Vuex from 'vuex'; import stubChildren from 'helpers/stub_children'; @@ -34,6 +34,7 @@ describe('PackagesApp', () => { let store; const fetchPackageVersions = jest.fn(); const deletePackage = jest.fn(); + const deletePackageFile = jest.fn(); const defaultProjectName = 'bar'; const { location } = window; @@ -59,6 +60,7 @@ describe('PackagesApp', () => { actions: { deletePackage, fetchPackageVersions, + deletePackageFile, }, getters, }); @@ -82,8 +84,8 @@ describe('PackagesApp', () => { const packageTitle = () => wrapper.find(PackageTitle); const emptyState = () => wrapper.find(GlEmptyState); const deleteButton = () => wrapper.find('.js-delete-button'); - const deleteModal = () => wrapper.find(GlModal); - const modalDeleteButton = () => wrapper.find({ ref: 'modal-delete-button' }); + const findDeleteModal = () => wrapper.find({ ref: 'deleteModal' }); + const findDeleteFileModal = () => wrapper.find({ ref: 'deleteFileModal' }); const versionsTab = () => wrapper.find('.js-versions-tab > a'); const packagesLoader = () => wrapper.find(PackagesListLoader); const packagesVersionRows = () => wrapper.findAll(PackageListRow); @@ -110,7 +112,7 @@ describe('PackagesApp', () => { it('renders the app and displays the package title', () => { createComponent(); - expect(packageTitle()).toExist(); + expect(packageTitle().exists()).toBe(true); }); it('renders an empty state component when no an invalid package is passed as a prop', () => { @@ -118,7 +120,7 @@ describe('PackagesApp', () => { packageEntity: {}, }); - expect(emptyState()).toExist(); + expect(emptyState().exists()).toBe(true); }); it('package history has the right props', () => { @@ -152,7 +154,16 @@ describe('PackagesApp', () => { }); it('shows the delete confirmation modal when delete is clicked', () => { - expect(deleteModal()).toExist(); + expect(findDeleteModal().exists()).toBe(true); + }); + }); + + describe('deleting package files', () => { + it('shows the delete confirmation modal when delete is clicked', () => { + createComponent(); + findPackageFiles().vm.$emit('delete-file', mavenFiles[0]); + + expect(findDeleteFileModal().exists()).toBe(true); }); }); @@ -228,13 +239,7 @@ describe('PackagesApp', () => { }); describe('tracking and delete', () => { - const doDelete = async () => { - deleteButton().trigger('click'); - await wrapper.vm.$nextTick(); - modalDeleteButton().trigger('click'); - }; - - describe('delete', () => { + describe('delete package', () => { const originalReferrer = document.referrer; const setReferrer = (value = defaultProjectName) => { Object.defineProperty(document, 'referrer', { @@ -250,9 +255,9 @@ describe('PackagesApp', () => { }); }); - it('calls the proper vuex action', async () => { + it('calls the proper vuex action', () => { createComponent({ packageEntity: npmPackage }); - await doDelete(); + findDeleteModal().vm.$emit('primary'); expect(deletePackage).toHaveBeenCalled(); }); @@ -260,7 +265,7 @@ describe('PackagesApp', () => { setReferrer(); deletePackage.mockResolvedValue(); createComponent({ packageEntity: npmPackage }); - await doDelete(); + findDeleteModal().vm.$emit('primary'); await deletePackage(); expect(window.location.replace).toHaveBeenCalledWith( 'project_url?showSuccessDeleteAlert=true', @@ -271,7 +276,7 @@ describe('PackagesApp', () => { setReferrer('baz'); deletePackage.mockResolvedValue(); createComponent({ packageEntity: npmPackage }); - await doDelete(); + findDeleteModal().vm.$emit('primary'); await deletePackage(); expect(window.location.replace).toHaveBeenCalledWith( 'group_url?showSuccessDeleteAlert=true', @@ -279,6 +284,17 @@ describe('PackagesApp', () => { }); }); + describe('delete file', () => { + it('calls the proper vuex action', () => { + createComponent({ packageEntity: npmPackage }); + + findPackageFiles().vm.$emit('delete-file', mavenFiles[0]); + findDeleteFileModal().vm.$emit('primary'); + + expect(deletePackageFile).toHaveBeenCalled(); + }); + }); + describe('tracking', () => { let eventSpy; let utilSpy; @@ -295,9 +311,9 @@ describe('PackagesApp', () => { expect(utilSpy).toHaveBeenCalledWith('conan'); }); - it(`delete button on delete modal call event with ${TrackingActions.DELETE_PACKAGE}`, async () => { + it(`delete button on delete modal call event with ${TrackingActions.DELETE_PACKAGE}`, () => { createComponent({ packageEntity: npmPackage }); - await doDelete(); + findDeleteModal().vm.$emit('primary'); expect(eventSpy).toHaveBeenCalledWith( category, TrackingActions.DELETE_PACKAGE, @@ -305,6 +321,56 @@ describe('PackagesApp', () => { ); }); + it(`canceling a package deletion tracks ${TrackingActions.CANCEL_DELETE_PACKAGE}`, () => { + createComponent({ packageEntity: npmPackage }); + + findDeleteModal().vm.$emit('canceled'); + + expect(eventSpy).toHaveBeenCalledWith( + category, + TrackingActions.CANCEL_DELETE_PACKAGE, + expect.any(Object), + ); + }); + + it(`request a file deletion tracks ${TrackingActions.REQUEST_DELETE_PACKAGE_FILE}`, () => { + createComponent({ packageEntity: npmPackage }); + + findPackageFiles().vm.$emit('delete-file', mavenFiles[0]); + + expect(eventSpy).toHaveBeenCalledWith( + category, + TrackingActions.REQUEST_DELETE_PACKAGE_FILE, + expect.any(Object), + ); + }); + + it(`confirming a file deletion tracks ${TrackingActions.DELETE_PACKAGE_FILE}`, () => { + createComponent({ packageEntity: npmPackage }); + + findPackageFiles().vm.$emit('delete-file', npmPackage); + findDeleteFileModal().vm.$emit('primary'); + + expect(eventSpy).toHaveBeenCalledWith( + category, + TrackingActions.REQUEST_DELETE_PACKAGE_FILE, + expect.any(Object), + ); + }); + + it(`canceling a file deletion tracks ${TrackingActions.CANCEL_DELETE_PACKAGE_FILE}`, () => { + createComponent({ packageEntity: npmPackage }); + + findPackageFiles().vm.$emit('delete-file', npmPackage); + findDeleteFileModal().vm.$emit('canceled'); + + expect(eventSpy).toHaveBeenCalledWith( + category, + TrackingActions.CANCEL_DELETE_PACKAGE_FILE, + expect.any(Object), + ); + }); + it(`file download link call event with ${TrackingActions.PULL_PACKAGE}`, () => { createComponent({ packageEntity: conanPackage }); diff --git a/spec/frontend/packages/details/components/package_files_spec.js b/spec/frontend/packages/details/components/package_files_spec.js index bcf1b6d56f0..494aa631d9d 100644 --- a/spec/frontend/packages/details/components/package_files_spec.js +++ b/spec/frontend/packages/details/components/package_files_spec.js @@ -1,3 +1,4 @@ +import { GlDropdown } from '@gitlab/ui'; import { mount } from '@vue/test-utils'; import stubChildren from 'helpers/stub_children'; import component from '~/packages/details/components/package_files.vue'; @@ -12,16 +13,19 @@ describe('Package Files', () => { const findAllRows = () => wrapper.findAll('[data-testid="file-row"'); const findFirstRow = () => findAllRows().at(0); const findSecondRow = () => findAllRows().at(1); - const findFirstRowDownloadLink = () => findFirstRow().find('[data-testid="download-link"'); - const findFirstRowCommitLink = () => findFirstRow().find('[data-testid="commit-link"'); - const findSecondRowCommitLink = () => findSecondRow().find('[data-testid="commit-link"'); + const findFirstRowDownloadLink = () => findFirstRow().find('[data-testid="download-link"]'); + const findFirstRowCommitLink = () => findFirstRow().find('[data-testid="commit-link"]'); + const findSecondRowCommitLink = () => findSecondRow().find('[data-testid="commit-link"]'); const findFirstRowFileIcon = () => findFirstRow().find(FileIcon); const findFirstRowCreatedAt = () => findFirstRow().find(TimeAgoTooltip); + const findFirstActionMenu = () => findFirstRow().findComponent(GlDropdown); + const findActionMenuDelete = () => findFirstActionMenu().find('[data-testid="delete-file"]'); - const createComponent = (packageFiles = npmFiles) => { + const createComponent = ({ packageFiles = npmFiles, canDelete = true } = {}) => { wrapper = mount(component, { propsData: { packageFiles, + canDelete, }, stubs: { ...stubChildren(component), @@ -43,7 +47,7 @@ describe('Package Files', () => { }); it('renders multiple files for a package that contains more than one file', () => { - createComponent(mavenFiles); + createComponent({ packageFiles: mavenFiles }); expect(findAllRows()).toHaveLength(2); }); @@ -123,7 +127,7 @@ describe('Package Files', () => { }); describe('when package file has no pipeline associated', () => { it('does not exist', () => { - createComponent(mavenFiles); + createComponent({ packageFiles: mavenFiles }); expect(findFirstRowCommitLink().exists()).toBe(false); }); @@ -131,11 +135,50 @@ describe('Package Files', () => { describe('when only one file lacks an associated pipeline', () => { it('renders the commit when it exists and not otherwise', () => { - createComponent([npmFiles[0], mavenFiles[0]]); + createComponent({ packageFiles: [npmFiles[0], mavenFiles[0]] }); expect(findFirstRowCommitLink().exists()).toBe(true); expect(findSecondRowCommitLink().exists()).toBe(false); }); }); + + describe('action menu', () => { + describe('when the user can delete', () => { + it('exists', () => { + createComponent(); + + expect(findFirstActionMenu().exists()).toBe(true); + }); + + describe('menu items', () => { + describe('delete file', () => { + it('exists', () => { + createComponent(); + + expect(findActionMenuDelete().exists()).toBe(true); + }); + + it('emits a delete event when clicked', () => { + createComponent(); + + findActionMenuDelete().vm.$emit('click'); + + const [[{ id }]] = wrapper.emitted('delete-file'); + expect(id).toBe(npmFiles[0].id); + }); + }); + }); + }); + + describe('when the user can not delete', () => { + const canDelete = false; + + it('does not exist', () => { + createComponent({ canDelete }); + + expect(findFirstActionMenu().exists()).toBe(false); + }); + }); + }); }); }); diff --git a/spec/frontend/packages/details/store/actions_spec.js b/spec/frontend/packages/details/store/actions_spec.js index d11ee548b72..b16e50debc4 100644 --- a/spec/frontend/packages/details/store/actions_spec.js +++ b/spec/frontend/packages/details/store/actions_spec.js @@ -1,10 +1,18 @@ import testAction from 'helpers/vuex_action_helper'; import Api from '~/api'; -import { deprecatedCreateFlash as createFlash } from '~/flash'; +import createFlash from '~/flash'; import { FETCH_PACKAGE_VERSIONS_ERROR } from '~/packages/details/constants'; -import { fetchPackageVersions, deletePackage } from '~/packages/details/store/actions'; +import { + fetchPackageVersions, + deletePackage, + deletePackageFile, +} from '~/packages/details/store/actions'; import * as types from '~/packages/details/store/mutation_types'; -import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants'; +import { + DELETE_PACKAGE_ERROR_MESSAGE, + DELETE_PACKAGE_FILE_ERROR_MESSAGE, + DELETE_PACKAGE_FILE_SUCCESS_MESSAGE, +} from '~/packages/shared/constants'; import { npmPackage as packageEntity } from '../../mock_data'; jest.mock('~/flash.js'); @@ -74,7 +82,10 @@ describe('Actions Package details store', () => { packageEntity.project_id, packageEntity.id, ); - expect(createFlash).toHaveBeenCalledWith(FETCH_PACKAGE_VERSIONS_ERROR); + expect(createFlash).toHaveBeenCalledWith({ + message: FETCH_PACKAGE_VERSIONS_ERROR, + type: 'warning', + }); done(); }, ); @@ -96,7 +107,48 @@ describe('Actions Package details store', () => { Api.deleteProjectPackage = jest.fn().mockRejectedValue(); testAction(deletePackage, undefined, { packageEntity }, [], [], () => { - expect(createFlash).toHaveBeenCalledWith(DELETE_PACKAGE_ERROR_MESSAGE); + expect(createFlash).toHaveBeenCalledWith({ + message: DELETE_PACKAGE_ERROR_MESSAGE, + type: 'warning', + }); + done(); + }); + }); + }); + + describe('deletePackageFile', () => { + const fileId = 'a_file_id'; + + it('should call Api.deleteProjectPackageFile and commit the right data', (done) => { + const packageFiles = [{ id: 'foo' }, { id: fileId }]; + Api.deleteProjectPackageFile = jest.fn().mockResolvedValue(); + testAction( + deletePackageFile, + fileId, + { packageEntity, packageFiles }, + [{ type: types.UPDATE_PACKAGE_FILES, payload: [{ id: 'foo' }] }], + [], + () => { + expect(Api.deleteProjectPackageFile).toHaveBeenCalledWith( + packageEntity.project_id, + packageEntity.id, + fileId, + ); + expect(createFlash).toHaveBeenCalledWith({ + message: DELETE_PACKAGE_FILE_SUCCESS_MESSAGE, + type: 'success', + }); + done(); + }, + ); + }); + it('should create flash on API error', (done) => { + Api.deleteProjectPackageFile = jest.fn().mockRejectedValue(); + testAction(deletePackageFile, fileId, { packageEntity }, [], [], () => { + expect(createFlash).toHaveBeenCalledWith({ + message: DELETE_PACKAGE_FILE_ERROR_MESSAGE, + type: 'warning', + }); done(); }); }); diff --git a/spec/frontend/packages/details/store/mutations_spec.js b/spec/frontend/packages/details/store/mutations_spec.js index 6bc5fb7241f..296ed02d786 100644 --- a/spec/frontend/packages/details/store/mutations_spec.js +++ b/spec/frontend/packages/details/store/mutations_spec.js @@ -28,4 +28,13 @@ describe('Mutations package details Store', () => { expect(mockState.packageEntity.versions).toEqual(fakeVersions); }); }); + describe('UPDATE_PACKAGE_FILES', () => { + it('should update the packageFiles', () => { + const files = [1, 2, 3]; + + mutations[types.UPDATE_PACKAGE_FILES](mockState, files); + + expect(mockState.packageFiles).toEqual(files); + }); + }); }); |