diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-19 01:45:44 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-19 01:45:44 +0000 |
commit | 85dc423f7090da0a52c73eb66faf22ddb20efff9 (patch) | |
tree | 9160f299afd8c80c038f08e1545be119f5e3f1e1 /spec/frontend/packages/details | |
parent | 15c2c8c66dbe422588e5411eee7e68f1fa440bb8 (diff) | |
download | gitlab-ce-85dc423f7090da0a52c73eb66faf22ddb20efff9.tar.gz |
Add latest changes from gitlab-org/gitlab@13-4-stable-ee
Diffstat (limited to 'spec/frontend/packages/details')
22 files changed, 327 insertions, 554 deletions
diff --git a/spec/frontend/packages/details/components/__snapshots__/code_instruction_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/code_instruction_spec.js.snap deleted file mode 100644 index 172b8919673..00000000000 --- a/spec/frontend/packages/details/components/__snapshots__/code_instruction_spec.js.snap +++ /dev/null @@ -1,46 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Package code instruction multiline to match the snapshot 1`] = ` -<div> - <pre - class="js-instruction-pre" - > - this is some -multiline text - </pre> -</div> -`; - -exports[`Package code instruction single line to match the default snapshot 1`] = ` -<div - class="input-group gl-mb-3" -> - <input - class="form-control monospace js-instruction-input" - readonly="readonly" - type="text" - /> - - <span - class="input-group-append js-instruction-button" - > - <button - class="btn input-group-text btn-secondary btn-md btn-default" - data-clipboard-text="npm i @my-package" - title="Copy npm install command" - type="button" - > - <!----> - - <svg - class="gl-icon s16" - data-testid="copy-to-clipboard-icon" - > - <use - href="#copy-to-clipboard" - /> - </svg> - </button> - </span> -</div> -`; diff --git a/spec/frontend/packages/details/components/__snapshots__/conan_installation_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/conan_installation_spec.js.snap index 852292e084b..a1d08f032bc 100644 --- a/spec/frontend/packages/details/components/__snapshots__/conan_installation_spec.js.snap +++ b/spec/frontend/packages/details/components/__snapshots__/conan_installation_spec.js.snap @@ -8,18 +8,12 @@ exports[`ConanInstallation renders all the messages 1`] = ` Installation </h3> - <h4 - class="gl-font-base" - > - - Conan Command - - </h4> - <code-instruction-stub copytext="Copy Conan Command" instruction="foo/command" + label="Conan Command" trackingaction="copy_conan_command" + trackinglabel="code_instruction" /> <h3 @@ -28,18 +22,12 @@ exports[`ConanInstallation renders all the messages 1`] = ` Registry setup </h3> - <h4 - class="gl-font-base" - > - - Add Conan Remote - - </h4> - <code-instruction-stub copytext="Copy Conan Setup Command" instruction="foo/setup" + label="Add Conan Remote" trackingaction="copy_conan_setup_command" + trackinglabel="code_instruction" /> <gl-sprintf-stub diff --git a/spec/frontend/packages/details/components/__snapshots__/dependency_row_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/dependency_row_spec.js.snap index 28b7ca442eb..39469bf4fd0 100644 --- a/spec/frontend/packages/details/components/__snapshots__/dependency_row_spec.js.snap +++ b/spec/frontend/packages/details/components/__snapshots__/dependency_row_spec.js.snap @@ -21,7 +21,7 @@ exports[`DependencyRow renders full dependency 1`] = ` </div> <div - class="table-section section-50 gl-display-flex justify-content-md-end" + class="table-section section-50 gl-display-flex gl-md-justify-content-end" data-testid="version-pattern" > <span diff --git a/spec/frontend/packages/details/components/__snapshots__/history_element_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/history_element_spec.js.snap deleted file mode 100644 index a1751d69c70..00000000000 --- a/spec/frontend/packages/details/components/__snapshots__/history_element_spec.js.snap +++ /dev/null @@ -1,38 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`History Element renders the correct markup 1`] = ` -<li - class="timeline-entry system-note note-wrapper gl-mb-6!" -> - <div - class="timeline-entry-inner" - > - <div - class="timeline-icon" - > - <gl-icon-stub - name="pencil" - size="16" - /> - </div> - - <div - class="timeline-content" - > - <div - class="note-header" - > - <span> - <div - data-testid="default-slot" - /> - </span> - </div> - - <div - class="note-body" - /> - </div> - </div> -</li> -`; diff --git a/spec/frontend/packages/details/components/__snapshots__/maven_installation_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/maven_installation_spec.js.snap index 10e54500797..6d22b372d41 100644 --- a/spec/frontend/packages/details/components/__snapshots__/maven_installation_spec.js.snap +++ b/spec/frontend/packages/details/components/__snapshots__/maven_installation_spec.js.snap @@ -8,14 +8,6 @@ exports[`MavenInstallation renders all the messages 1`] = ` Installation </h3> - <h4 - class="gl-font-base" - > - - Maven XML - - </h4> - <p> <gl-sprintf-stub message="Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block." @@ -25,22 +17,18 @@ exports[`MavenInstallation renders all the messages 1`] = ` <code-instruction-stub copytext="Copy Maven XML" instruction="foo/xml" + label="Maven XML" multiline="true" trackingaction="copy_maven_xml" + trackinglabel="code_instruction" /> - <h4 - class="gl-font-base" - > - - Maven Command - - </h4> - <code-instruction-stub copytext="Copy Maven command" instruction="foo/command" + label="Maven Command" trackingaction="copy_maven_command" + trackinglabel="code_instruction" /> <h3 @@ -58,8 +46,10 @@ exports[`MavenInstallation renders all the messages 1`] = ` <code-instruction-stub copytext="Copy Maven registry XML" instruction="foo/setup" + label="" multiline="true" trackingaction="copy_maven_setup_xml" + trackinglabel="code_instruction" /> <gl-sprintf-stub diff --git a/spec/frontend/packages/details/components/__snapshots__/npm_installation_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/npm_installation_spec.js.snap index 58a509e6847..b616751f75f 100644 --- a/spec/frontend/packages/details/components/__snapshots__/npm_installation_spec.js.snap +++ b/spec/frontend/packages/details/components/__snapshots__/npm_installation_spec.js.snap @@ -8,28 +8,20 @@ exports[`NpmInstallation renders all the messages 1`] = ` Installation </h3> - <h4 - class="gl-font-base" - > - npm command - </h4> - <code-instruction-stub copytext="Copy npm command" instruction="npm i @Test/package" + label="npm command" trackingaction="copy_npm_install_command" + trackinglabel="code_instruction" /> - <h4 - class="gl-font-base" - > - yarn command - </h4> - <code-instruction-stub copytext="Copy yarn command" instruction="yarn add @Test/package" + label="yarn command" trackingaction="copy_yarn_install_command" + trackinglabel="code_instruction" /> <h3 @@ -38,28 +30,20 @@ exports[`NpmInstallation renders all the messages 1`] = ` Registry setup </h3> - <h4 - class="gl-font-base" - > - npm command - </h4> - <code-instruction-stub copytext="Copy npm setup command" - instruction="echo @Test:registry=undefined >> .npmrc" + instruction="echo @Test:registry=undefined/ >> .npmrc" + label="npm command" trackingaction="copy_npm_setup_command" + trackinglabel="code_instruction" /> - <h4 - class="gl-font-base" - > - yarn command - </h4> - <code-instruction-stub copytext="Copy yarn setup command" - instruction="echo \\\\\\"@Test:registry\\\\\\" \\\\\\"undefined\\\\\\" >> .yarnrc" + instruction="echo \\\\\\"@Test:registry\\\\\\" \\\\\\"undefined/\\\\\\" >> .yarnrc" + label="yarn command" trackingaction="copy_yarn_setup_command" + trackinglabel="code_instruction" /> <gl-sprintf-stub diff --git a/spec/frontend/packages/details/components/__snapshots__/nuget_installation_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/nuget_installation_spec.js.snap index 67810290c62..84cf5e4db49 100644 --- a/spec/frontend/packages/details/components/__snapshots__/nuget_installation_spec.js.snap +++ b/spec/frontend/packages/details/components/__snapshots__/nuget_installation_spec.js.snap @@ -8,18 +8,12 @@ exports[`NugetInstallation renders all the messages 1`] = ` Installation </h3> - <h4 - class="gl-font-base" - > - - NuGet Command - - </h4> - <code-instruction-stub copytext="Copy NuGet Command" instruction="foo/command" + label="NuGet Command" trackingaction="copy_nuget_install_command" + trackinglabel="code_instruction" /> <h3 @@ -28,18 +22,12 @@ exports[`NugetInstallation renders all the messages 1`] = ` Registry setup </h3> - <h4 - class="gl-font-base" - > - - Add NuGet Source - - </h4> - <code-instruction-stub copytext="Copy NuGet Setup Command" instruction="foo/setup" + label="Add NuGet Source" trackingaction="copy_nuget_setup_command" + trackinglabel="code_instruction" /> <gl-sprintf-stub diff --git a/spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap index bdcd4a9e077..4d9e0af1545 100644 --- a/spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap +++ b/spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap @@ -2,171 +2,151 @@ exports[`PackageTitle renders with tags 1`] = ` <div - class="gl-flex-direction-column" + class="gl-display-flex gl-justify-content-space-between gl-py-3" + data-qa-selector="package_title" > <div - class="gl-display-flex" + class="gl-flex-direction-column" > - <!----> - <div - class="gl-display-flex gl-flex-direction-column" + class="gl-display-flex" > - <h1 - class="gl-font-size-h1 gl-mt-3 gl-mb-2" - > - - Test package - - </h1> + <!----> <div - class="gl-display-flex gl-align-items-center gl-text-gray-500" + class="gl-display-flex gl-flex-direction-column" > - <gl-icon-stub - class="gl-mr-3" - name="eye" - size="16" - /> + <h1 + class="gl-font-size-h1 gl-mt-3 gl-mb-2" + data-testid="title" + > + Test package + </h1> - <gl-sprintf-stub - message="v%{version} published %{timeAgo}" - /> + <div + class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1" + > + <gl-icon-stub + class="gl-mr-3" + name="eye" + size="16" + /> + + <gl-sprintf-stub + message="v%{version} published %{timeAgo}" + /> + </div> </div> </div> - </div> - - <div - class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mb-3" - > - <div - class="gl-display-flex gl-align-items-center gl-mr-5" - > - <gl-icon-stub - class="gl-text-gray-500 gl-mr-3" - name="package" - size="16" - /> - - <span - class="gl-font-weight-bold" - data-testid="package-type" - > - maven - </span> - </div> <div - class="gl-display-flex gl-align-items-center gl-mr-5" + class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mt-3" > - <package-tags-stub - tagdisplaylimit="1" - tags="[object Object],[object Object],[object Object],[object Object]" - /> - </div> - - <!----> - - <!----> - - <div - class="gl-display-flex gl-align-items-center gl-mr-5" - > - <gl-icon-stub - class="gl-text-gray-500 gl-mr-3" - name="disk" - size="16" - /> - - <span - class="gl-font-weight-bold" - data-testid="package-size" + <div + class="gl-display-flex gl-align-items-center gl-mr-5" + > + <metadata-item-stub + data-testid="package-type" + icon="package" + link="" + size="s" + text="maven" + /> + </div> + <div + class="gl-display-flex gl-align-items-center gl-mr-5" + > + <metadata-item-stub + data-testid="package-size" + icon="disk" + link="" + size="s" + text="300 bytes" + /> + </div> + <div + class="gl-display-flex gl-align-items-center gl-mr-5" > - 300 bytes - </span> + <package-tags-stub + hidelabel="true" + tagdisplaylimit="2" + tags="[object Object],[object Object],[object Object],[object Object]" + /> + </div> </div> </div> + + <!----> </div> `; exports[`PackageTitle renders without tags 1`] = ` <div - class="gl-flex-direction-column" + class="gl-display-flex gl-justify-content-space-between gl-py-3" + data-qa-selector="package_title" > <div - class="gl-display-flex" + class="gl-flex-direction-column" > - <!----> - <div - class="gl-display-flex gl-flex-direction-column" + class="gl-display-flex" > - <h1 - class="gl-font-size-h1 gl-mt-3 gl-mb-2" - > - - Test package - - </h1> + <!----> <div - class="gl-display-flex gl-align-items-center gl-text-gray-500" + class="gl-display-flex gl-flex-direction-column" > - <gl-icon-stub - class="gl-mr-3" - name="eye" - size="16" - /> + <h1 + class="gl-font-size-h1 gl-mt-3 gl-mb-2" + data-testid="title" + > + Test package + </h1> - <gl-sprintf-stub - message="v%{version} published %{timeAgo}" - /> + <div + class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1" + > + <gl-icon-stub + class="gl-mr-3" + name="eye" + size="16" + /> + + <gl-sprintf-stub + message="v%{version} published %{timeAgo}" + /> + </div> </div> </div> - </div> - - <div - class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mb-3" - > - <div - class="gl-display-flex gl-align-items-center gl-mr-5" - > - <gl-icon-stub - class="gl-text-gray-500 gl-mr-3" - name="package" - size="16" - /> - - <span - class="gl-font-weight-bold" - data-testid="package-type" - > - maven - </span> - </div> - - <!----> - - <!----> - - <!----> <div - class="gl-display-flex gl-align-items-center gl-mr-5" + class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mt-3" > - <gl-icon-stub - class="gl-text-gray-500 gl-mr-3" - name="disk" - size="16" - /> - - <span - class="gl-font-weight-bold" - data-testid="package-size" + <div + class="gl-display-flex gl-align-items-center gl-mr-5" > - 300 bytes - </span> + <metadata-item-stub + data-testid="package-type" + icon="package" + link="" + size="s" + text="maven" + /> + </div> + <div + class="gl-display-flex gl-align-items-center gl-mr-5" + > + <metadata-item-stub + data-testid="package-size" + icon="disk" + link="" + size="s" + text="300 bytes" + /> + </div> </div> </div> + + <!----> </div> `; diff --git a/spec/frontend/packages/details/components/__snapshots__/pypi_installation_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/pypi_installation_spec.js.snap index 5c1e74d73af..2a588f99c1d 100644 --- a/spec/frontend/packages/details/components/__snapshots__/pypi_installation_spec.js.snap +++ b/spec/frontend/packages/details/components/__snapshots__/pypi_installation_spec.js.snap @@ -8,19 +8,13 @@ exports[`PypiInstallation renders all the messages 1`] = ` Installation </h3> - <h4 - class="gl-font-base" - > - - Pip Command - - </h4> - <code-instruction-stub copytext="Copy Pip command" data-testid="pip-command" instruction="pip install" + label="Pip Command" trackingaction="copy_pip_install_command" + trackinglabel="code_instruction" /> <h3 @@ -39,8 +33,10 @@ exports[`PypiInstallation renders all the messages 1`] = ` copytext="Copy .pypirc content" data-testid="pypi-setup-content" instruction="python setup" + label="" multiline="true" trackingaction="copy_pypi_setup_command" + trackinglabel="code_instruction" /> <gl-sprintf-stub diff --git a/spec/frontend/packages/details/components/additional_metadata_spec.js b/spec/frontend/packages/details/components/additional_metadata_spec.js index b2337b86740..111e4205abb 100644 --- a/spec/frontend/packages/details/components/additional_metadata_spec.js +++ b/spec/frontend/packages/details/components/additional_metadata_spec.js @@ -1,6 +1,6 @@ import { shallowMount } from '@vue/test-utils'; import { GlLink, GlSprintf } from '@gitlab/ui'; -import DetailsRow from '~/registry/shared/components/details_row.vue'; +import DetailsRow from '~/vue_shared/components/registry/details_row.vue'; import component from '~/packages/details/components/additional_metadata.vue'; import { mavenPackage, conanPackage, nugetPackage, npmPackage } from '../../mock_data'; diff --git a/spec/frontend/packages/details/components/app_spec.js b/spec/frontend/packages/details/components/app_spec.js index f535f3f5744..e82c74e56e5 100644 --- a/spec/frontend/packages/details/components/app_spec.js +++ b/spec/frontend/packages/details/components/app_spec.js @@ -34,12 +34,15 @@ describe('PackagesApp', () => { let wrapper; let store; const fetchPackageVersions = jest.fn(); + const deletePackage = jest.fn(); + const defaultProjectName = 'bar'; + const { location } = window; function createComponent({ packageEntity = mavenPackage, packageFiles = mavenFiles, isLoading = false, - oneColumnView = false, + projectName = defaultProjectName, } = {}) { store = new Vuex.Store({ state: { @@ -47,14 +50,15 @@ describe('PackagesApp', () => { packageEntity, packageFiles, canDelete: true, - destroyPath: 'destroy-package-path', emptySvgPath: 'empty-illustration', npmPath: 'foo', npmHelpPath: 'foo', - projectName: 'bar', - oneColumnView, + projectName, + projectListUrl: 'project_url', + groupListUrl: 'group_url', }, actions: { + deletePackage, fetchPackageVersions, }, getters, @@ -65,6 +69,8 @@ describe('PackagesApp', () => { store, stubs: { ...stubChildren(PackagesApp), + PackageTitle: false, + TitleArea: false, GlButton: false, GlModal: false, GlTab: false, @@ -93,8 +99,14 @@ describe('PackagesApp', () => { const findAdditionalMetadata = () => wrapper.find(AdditionalMetadata); const findInstallationCommands = () => wrapper.find(InstallationCommands); + beforeEach(() => { + delete window.location; + window.location = { replace: jest.fn() }; + }); + afterEach(() => { wrapper.destroy(); + window.location = location; }); it('renders the app and displays the package title', () => { @@ -238,44 +250,94 @@ describe('PackagesApp', () => { }); }); - describe('tracking', () => { - let eventSpy; - let utilSpy; - const category = 'foo'; + describe('tracking and delete', () => { + const doDelete = async () => { + deleteButton().trigger('click'); + await wrapper.vm.$nextTick(); + modalDeleteButton().trigger('click'); + }; + + describe('delete', () => { + const originalReferrer = document.referrer; + const setReferrer = (value = defaultProjectName) => { + Object.defineProperty(document, 'referrer', { + value, + configurable: true, + }); + }; + + afterEach(() => { + Object.defineProperty(document, 'referrer', { + value: originalReferrer, + configurable: true, + }); + }); - beforeEach(() => { - eventSpy = jest.spyOn(Tracking, 'event'); - utilSpy = jest.spyOn(SharedUtils, 'packageTypeToTrackCategory').mockReturnValue(category); - }); + it('calls the proper vuex action', async () => { + createComponent({ packageEntity: npmPackage }); + await doDelete(); + expect(deletePackage).toHaveBeenCalled(); + }); - it('tracking category calls packageTypeToTrackCategory', () => { - createComponent({ packageEntity: conanPackage }); - expect(wrapper.vm.tracking.category).toBe(category); - expect(utilSpy).toHaveBeenCalledWith('conan'); + it('when referrer contains project name calls window.replace with project url', async () => { + setReferrer(); + deletePackage.mockResolvedValue(); + createComponent({ packageEntity: npmPackage }); + await doDelete(); + await deletePackage(); + expect(window.location.replace).toHaveBeenCalledWith( + 'project_url?showSuccessDeleteAlert=true', + ); + }); + + it('when referrer does not contain project name calls window.replace with group url', async () => { + setReferrer('baz'); + deletePackage.mockResolvedValue(); + createComponent({ packageEntity: npmPackage }); + await doDelete(); + await deletePackage(); + expect(window.location.replace).toHaveBeenCalledWith( + 'group_url?showSuccessDeleteAlert=true', + ); + }); }); - it(`delete button on delete modal call event with ${TrackingActions.DELETE_PACKAGE}`, () => { - createComponent({ packageEntity: conanPackage }); - deleteButton().trigger('click'); - return wrapper.vm.$nextTick().then(() => { - modalDeleteButton().trigger('click'); + describe('tracking', () => { + let eventSpy; + let utilSpy; + const category = 'foo'; + + beforeEach(() => { + eventSpy = jest.spyOn(Tracking, 'event'); + utilSpy = jest.spyOn(SharedUtils, 'packageTypeToTrackCategory').mockReturnValue(category); + }); + + it('tracking category calls packageTypeToTrackCategory', () => { + createComponent({ packageEntity: conanPackage }); + expect(wrapper.vm.tracking.category).toBe(category); + expect(utilSpy).toHaveBeenCalledWith('conan'); + }); + + it(`delete button on delete modal call event with ${TrackingActions.DELETE_PACKAGE}`, async () => { + createComponent({ packageEntity: npmPackage }); + await doDelete(); expect(eventSpy).toHaveBeenCalledWith( category, TrackingActions.DELETE_PACKAGE, expect.any(Object), ); }); - }); - it(`file download link call event with ${TrackingActions.PULL_PACKAGE}`, () => { - createComponent({ packageEntity: conanPackage }); + it(`file download link call event with ${TrackingActions.PULL_PACKAGE}`, () => { + createComponent({ packageEntity: conanPackage }); - firstFileDownloadLink().vm.$emit('click'); - expect(eventSpy).toHaveBeenCalledWith( - category, - TrackingActions.PULL_PACKAGE, - expect.any(Object), - ); + firstFileDownloadLink().vm.$emit('click'); + expect(eventSpy).toHaveBeenCalledWith( + category, + TrackingActions.PULL_PACKAGE, + expect.any(Object), + ); + }); }); }); }); diff --git a/spec/frontend/packages/details/components/code_instruction_spec.js b/spec/frontend/packages/details/components/code_instruction_spec.js deleted file mode 100644 index 724eddb9070..00000000000 --- a/spec/frontend/packages/details/components/code_instruction_spec.js +++ /dev/null @@ -1,110 +0,0 @@ -import { mount } from '@vue/test-utils'; -import CodeInstruction from '~/packages/details/components/code_instruction.vue'; -import { TrackingLabels } from '~/packages/details/constants'; -import Tracking from '~/tracking'; - -describe('Package code instruction', () => { - let wrapper; - - const defaultProps = { - instruction: 'npm i @my-package', - copyText: 'Copy npm install command', - }; - - function createComponent(props = {}) { - wrapper = mount(CodeInstruction, { - propsData: { - ...defaultProps, - ...props, - }, - }); - } - - const findInstructionInput = () => wrapper.find('.js-instruction-input'); - const findInstructionPre = () => wrapper.find('.js-instruction-pre'); - const findInstructionButton = () => wrapper.find('.js-instruction-button'); - - afterEach(() => { - wrapper.destroy(); - }); - - describe('single line', () => { - beforeEach(() => createComponent()); - - it('to match the default snapshot', () => { - expect(wrapper.element).toMatchSnapshot(); - }); - }); - - describe('multiline', () => { - beforeEach(() => - createComponent({ - instruction: 'this is some\nmultiline text', - copyText: 'Copy the command', - multiline: true, - }), - ); - - it('to match the snapshot', () => { - expect(wrapper.element).toMatchSnapshot(); - }); - }); - - describe('tracking', () => { - let eventSpy; - const trackingAction = 'test_action'; - const label = TrackingLabels.CODE_INSTRUCTION; - - beforeEach(() => { - eventSpy = jest.spyOn(Tracking, 'event'); - }); - - it('should not track when no trackingAction is provided', () => { - createComponent(); - findInstructionButton().trigger('click'); - - expect(eventSpy).toHaveBeenCalledTimes(0); - }); - - describe('when trackingAction is provided for single line', () => { - beforeEach(() => - createComponent({ - trackingAction, - }), - ); - - it('should track when copying from the input', () => { - findInstructionInput().trigger('copy'); - - expect(eventSpy).toHaveBeenCalledWith(undefined, trackingAction, { - label, - }); - }); - - it('should track when the copy button is pressed', () => { - findInstructionButton().trigger('click'); - - expect(eventSpy).toHaveBeenCalledWith(undefined, trackingAction, { - label, - }); - }); - }); - - describe('when trackingAction is provided for multiline', () => { - beforeEach(() => - createComponent({ - trackingAction, - multiline: true, - }), - ); - - it('should track when copying from the multiline pre element', () => { - findInstructionPre().trigger('copy'); - - expect(eventSpy).toHaveBeenCalledWith(undefined, trackingAction, { - label, - }); - }); - }); - }); -}); diff --git a/spec/frontend/packages/details/components/composer_installation_spec.js b/spec/frontend/packages/details/components/composer_installation_spec.js index 7679d721391..c13981fbb87 100644 --- a/spec/frontend/packages/details/components/composer_installation_spec.js +++ b/spec/frontend/packages/details/components/composer_installation_spec.js @@ -4,7 +4,7 @@ import { GlSprintf, GlLink } from '@gitlab/ui'; import { registryUrl as composerHelpPath } from 'jest/packages/details/mock_data'; import { composerPackage as packageEntity } from 'jest/packages/mock_data'; import ComposerInstallation from '~/packages/details/components/composer_installation.vue'; -import CodeInstructions from '~/packages/details/components/code_instruction.vue'; + import { TrackingActions } from '~/packages/details/constants'; const localVue = createLocalVue(); @@ -27,9 +27,8 @@ describe('ComposerInstallation', () => { }, }); - const findCodeInstructions = () => wrapper.findAll(CodeInstructions); - const findRegistryIncludeTitle = () => wrapper.find('[data-testid="registry-include-title"]'); - const findPackageIncludeTitle = () => wrapper.find('[data-testid="package-include-title"]'); + const findRegistryInclude = () => wrapper.find('[data-testid="registry-include"]'); + const findPackageInclude = () => wrapper.find('[data-testid="package-include"]'); const findHelpText = () => wrapper.find('[data-testid="help-text"]'); const findHelpLink = () => wrapper.find(GlLink); @@ -53,7 +52,7 @@ describe('ComposerInstallation', () => { describe('registry include command', () => { it('uses code_instructions', () => { - const registryIncludeCommand = findCodeInstructions().at(0); + const registryIncludeCommand = findRegistryInclude(); expect(registryIncludeCommand.exists()).toBe(true); expect(registryIncludeCommand.props()).toMatchObject({ instruction: composerRegistryIncludeStr, @@ -63,13 +62,13 @@ describe('ComposerInstallation', () => { }); it('has the correct title', () => { - expect(findRegistryIncludeTitle().text()).toBe('composer.json registry include'); + expect(findRegistryInclude().props('label')).toBe('composer.json registry include'); }); }); describe('package include command', () => { it('uses code_instructions', () => { - const registryIncludeCommand = findCodeInstructions().at(1); + const registryIncludeCommand = findPackageInclude(); expect(registryIncludeCommand.exists()).toBe(true); expect(registryIncludeCommand.props()).toMatchObject({ instruction: composerPackageIncludeStr, @@ -79,7 +78,7 @@ describe('ComposerInstallation', () => { }); it('has the correct title', () => { - expect(findPackageIncludeTitle().text()).toBe('composer.json require package include'); + expect(findPackageInclude().props('label')).toBe('composer.json require package include'); }); it('has the correct help text', () => { diff --git a/spec/frontend/packages/details/components/conan_installation_spec.js b/spec/frontend/packages/details/components/conan_installation_spec.js index 5b31e38dad5..c79d1bb50dd 100644 --- a/spec/frontend/packages/details/components/conan_installation_spec.js +++ b/spec/frontend/packages/details/components/conan_installation_spec.js @@ -1,7 +1,7 @@ import Vuex from 'vuex'; import { shallowMount, createLocalVue } from '@vue/test-utils'; import ConanInstallation from '~/packages/details/components/conan_installation.vue'; -import CodeInstructions from '~/packages/details/components/code_instruction.vue'; +import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue'; import { conanPackage as packageEntity } from '../../mock_data'; import { registryUrl as conanPath } from '../mock_data'; diff --git a/spec/frontend/packages/details/components/history_element_spec.js b/spec/frontend/packages/details/components/history_element_spec.js deleted file mode 100644 index e8746fc93f5..00000000000 --- a/spec/frontend/packages/details/components/history_element_spec.js +++ /dev/null @@ -1,57 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import { GlIcon } from '@gitlab/ui'; -import component from '~/packages/details/components/history_element.vue'; -import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; - -describe('History Element', () => { - let wrapper; - const defaultProps = { - icon: 'pencil', - }; - - const mountComponent = () => { - wrapper = shallowMount(component, { - propsData: { ...defaultProps }, - stubs: { - TimelineEntryItem, - }, - slots: { - default: '<div data-testid="default-slot"></div>', - }, - }); - }; - - afterEach(() => { - wrapper.destroy(); - wrapper = null; - }); - - const findTimelineEntry = () => wrapper.find(TimelineEntryItem); - const findGlIcon = () => wrapper.find(GlIcon); - const findDefaultSlot = () => wrapper.find('[data-testid="default-slot"]'); - - it('renders the correct markup', () => { - mountComponent(); - - expect(wrapper.element).toMatchSnapshot(); - }); - - it('has a default slot', () => { - mountComponent(); - - expect(findDefaultSlot().exists()).toBe(true); - }); - it('has a timeline entry', () => { - mountComponent(); - - expect(findTimelineEntry().exists()).toBe(true); - }); - it('has an icon', () => { - mountComponent(); - - const icon = findGlIcon(); - - expect(icon.exists()).toBe(true); - expect(icon.attributes('name')).toBe(defaultProps.icon); - }); -}); diff --git a/spec/frontend/packages/details/components/maven_installation_spec.js b/spec/frontend/packages/details/components/maven_installation_spec.js index 5d0007294b6..f301a03a7f3 100644 --- a/spec/frontend/packages/details/components/maven_installation_spec.js +++ b/spec/frontend/packages/details/components/maven_installation_spec.js @@ -3,7 +3,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils'; import { registryUrl as mavenPath } from 'jest/packages/details/mock_data'; import { mavenPackage as packageEntity } from 'jest/packages/mock_data'; import MavenInstallation from '~/packages/details/components/maven_installation.vue'; -import CodeInstructions from '~/packages/details/components/code_instruction.vue'; +import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue'; import { TrackingActions } from '~/packages/details/constants'; const localVue = createLocalVue(); diff --git a/spec/frontend/packages/details/components/npm_installation_spec.js b/spec/frontend/packages/details/components/npm_installation_spec.js index f47bac57a66..4223a05453c 100644 --- a/spec/frontend/packages/details/components/npm_installation_spec.js +++ b/spec/frontend/packages/details/components/npm_installation_spec.js @@ -3,7 +3,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils'; import { npmPackage as packageEntity } from 'jest/packages/mock_data'; import { registryUrl as nugetPath } from 'jest/packages/details/mock_data'; import NpmInstallation from '~/packages/details/components/npm_installation.vue'; -import CodeInstructions from '~/packages/details/components/code_instruction.vue'; +import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue'; import { TrackingActions } from '~/packages/details/constants'; import { npmInstallationCommand, npmSetupCommand } from '~/packages/details/store/getters'; @@ -78,7 +78,7 @@ describe('NpmInstallation', () => { .at(2) .props(), ).toMatchObject({ - instruction: 'echo @Test:registry=undefined >> .npmrc', + instruction: 'echo @Test:registry=undefined/ >> .npmrc', multiline: false, trackingAction: TrackingActions.COPY_NPM_SETUP_COMMAND, }); @@ -90,7 +90,7 @@ describe('NpmInstallation', () => { .at(3) .props(), ).toMatchObject({ - instruction: 'echo \\"@Test:registry\\" \\"undefined\\" >> .yarnrc', + instruction: 'echo \\"@Test:registry\\" \\"undefined/\\" >> .yarnrc', multiline: false, trackingAction: TrackingActions.COPY_YARN_SETUP_COMMAND, }); diff --git a/spec/frontend/packages/details/components/nuget_installation_spec.js b/spec/frontend/packages/details/components/nuget_installation_spec.js index a23bf9a18a1..b381d131e94 100644 --- a/spec/frontend/packages/details/components/nuget_installation_spec.js +++ b/spec/frontend/packages/details/components/nuget_installation_spec.js @@ -3,7 +3,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils'; import { nugetPackage as packageEntity } from 'jest/packages/mock_data'; import { registryUrl as nugetPath } from 'jest/packages/details/mock_data'; import NugetInstallation from '~/packages/details/components/nuget_installation.vue'; -import CodeInstructions from '~/packages/details/components/code_instruction.vue'; +import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue'; import { TrackingActions } from '~/packages/details/constants'; const localVue = createLocalVue(); diff --git a/spec/frontend/packages/details/components/package_history_spec.js b/spec/frontend/packages/details/components/package_history_spec.js index e293e119585..f745a457b0a 100644 --- a/spec/frontend/packages/details/components/package_history_spec.js +++ b/spec/frontend/packages/details/components/package_history_spec.js @@ -1,6 +1,7 @@ import { shallowMount } from '@vue/test-utils'; import { GlLink, GlSprintf } from '@gitlab/ui'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; +import HistoryItem from '~/vue_shared/components/registry/history_item.vue'; import component from '~/packages/details/components/package_history.vue'; import { mavenPackage, mockPipelineInfo } from '../../mock_data'; @@ -16,7 +17,10 @@ describe('Package History', () => { wrapper = shallowMount(component, { propsData: { ...defaultProps, ...props }, stubs: { - HistoryElement: '<div data-testid="history-element"><slot></slot></div>', + HistoryItem: { + props: HistoryItem.props, + template: '<div data-testid="history-element"><slot></slot></div>', + }, GlSprintf, }, }); diff --git a/spec/frontend/packages/details/components/package_title_spec.js b/spec/frontend/packages/details/components/package_title_spec.js index a30dc4b8aba..d0ed78418af 100644 --- a/spec/frontend/packages/details/components/package_title_spec.js +++ b/spec/frontend/packages/details/components/package_title_spec.js @@ -2,6 +2,7 @@ import Vuex from 'vuex'; import { shallowMount, createLocalVue } from '@vue/test-utils'; import PackageTitle from '~/packages/details/components/package_title.vue'; import PackageTags from '~/packages/shared/components/package_tags.vue'; +import TitleArea from '~/vue_shared/components/registry/title_area.vue'; import { conanPackage, mavenFiles, @@ -39,10 +40,14 @@ describe('PackageTitle', () => { wrapper = shallowMount(PackageTitle, { localVue, store, + stubs: { + TitleArea, + }, }); + return wrapper.vm.$nextTick(); } - const packageIcon = () => wrapper.find('[data-testid="package-icon"]'); + const findTitleArea = () => wrapper.find(TitleArea); const packageType = () => wrapper.find('[data-testid="package-type"]'); const packageSize = () => wrapper.find('[data-testid="package-size"]'); const pipelineProject = () => wrapper.find('[data-testid="pipeline-project"]'); @@ -54,72 +59,74 @@ describe('PackageTitle', () => { }); describe('renders', () => { - it('without tags', () => { - createComponent(); + it('without tags', async () => { + await createComponent(); expect(wrapper.element).toMatchSnapshot(); }); - it('with tags', () => { - createComponent({ packageEntity: { ...mavenPackage, tags: mockTags } }); + it('with tags', async () => { + await createComponent({ packageEntity: { ...mavenPackage, tags: mockTags } }); expect(wrapper.element).toMatchSnapshot(); }); }); - describe('package icon', () => { - const fakeSrc = 'a-fake-src'; - - it('shows an icon when provided one from vuex', () => { - createComponent({ icon: fakeSrc }); + describe('package title', () => { + it('is correctly bound', async () => { + await createComponent(); - expect(packageIcon().exists()).toBe(true); + expect(findTitleArea().props('title')).toBe('Test package'); }); + }); - it('has the correct src attribute', () => { - createComponent({ icon: fakeSrc }); + describe('package icon', () => { + const fakeSrc = 'a-fake-src'; + + it('binds an icon when provided one from vuex', async () => { + await createComponent({ icon: fakeSrc }); - expect(packageIcon().props('src')).toBe(fakeSrc); + expect(findTitleArea().props('avatar')).toBe(fakeSrc); }); - it('does not show an icon when not provided one', () => { - createComponent(); + it('do not binds an icon when not provided one', async () => { + await createComponent(); - expect(packageIcon().exists()).toBe(false); + expect(findTitleArea().props('avatar')).toBe(null); }); }); describe.each` - packageEntity | expectedResult + packageEntity | text ${conanPackage} | ${'conan'} ${mavenPackage} | ${'maven'} ${npmPackage} | ${'npm'} ${nugetPackage} | ${'nuget'} - `(`package type`, ({ packageEntity, expectedResult }) => { + `(`package type`, ({ packageEntity, text }) => { beforeEach(() => createComponent({ packageEntity })); - it(`${packageEntity.package_type} should render from Vuex getters ${expectedResult}`, () => { - expect(packageType().text()).toBe(expectedResult); + it(`${packageEntity.package_type} should render from Vuex getters ${text}`, () => { + expect(packageType().props()).toEqual(expect.objectContaining({ text, icon: 'package' })); }); }); describe('calculates the package size', () => { - it('correctly calulates when there is only 1 file', () => { - createComponent({ packageEntity: npmPackage, packageFiles: npmFiles }); + it('correctly calculates when there is only 1 file', async () => { + await createComponent({ packageEntity: npmPackage, packageFiles: npmFiles }); - expect(packageSize().text()).toBe('200 bytes'); + expect(packageSize().props()).toMatchObject({ text: '200 bytes', icon: 'disk' }); }); - it('correctly calulates when there are multiple files', () => { - createComponent(); + it('correctly calulates when there are multiple files', async () => { + await createComponent(); - expect(packageSize().text()).toBe('300 bytes'); + expect(packageSize().props('text')).toBe('300 bytes'); }); }); describe('package tags', () => { - it('displays the package-tags component when the package has tags', () => { - createComponent({ + it('displays the package-tags component when the package has tags', async () => { + await createComponent({ packageEntity: { ...npmPackage, tags: mockTags, @@ -129,40 +136,44 @@ describe('PackageTitle', () => { expect(packageTags().exists()).toBe(true); }); - it('does not display the package-tags component when there are no tags', () => { - createComponent(); + it('does not display the package-tags component when there are no tags', async () => { + await createComponent(); expect(packageTags().exists()).toBe(false); }); }); describe('package ref', () => { - it('does not display the ref if missing', () => { - createComponent(); + it('does not display the ref if missing', async () => { + await createComponent(); expect(packageRef().exists()).toBe(false); }); - it('correctly shows the package ref if there is one', () => { - createComponent({ packageEntity: npmPackage }); - - expect(packageRef().contains('gl-icon-stub')).toBe(true); - expect(packageRef().text()).toBe(npmPackage.pipeline.ref); + it('correctly shows the package ref if there is one', async () => { + await createComponent({ packageEntity: npmPackage }); + expect(packageRef().props()).toMatchObject({ + text: npmPackage.pipeline.ref, + icon: 'branch', + }); }); }); describe('pipeline project', () => { - it('does not display the project if missing', () => { - createComponent(); + it('does not display the project if missing', async () => { + await createComponent(); expect(pipelineProject().exists()).toBe(false); }); - it('correctly shows the pipeline project if there is one', () => { - createComponent({ packageEntity: npmPackage }); + it('correctly shows the pipeline project if there is one', async () => { + await createComponent({ packageEntity: npmPackage }); - expect(pipelineProject().text()).toBe(npmPackage.pipeline.project.name); - expect(pipelineProject().attributes('href')).toBe(npmPackage.pipeline.project.web_url); + expect(pipelineProject().props()).toMatchObject({ + text: npmPackage.pipeline.project.name, + icon: 'review-list', + link: npmPackage.pipeline.project.web_url, + }); }); }); }); diff --git a/spec/frontend/packages/details/store/actions_spec.js b/spec/frontend/packages/details/store/actions_spec.js index 6dfb2b63f85..70f87d18bcb 100644 --- a/spec/frontend/packages/details/store/actions_spec.js +++ b/spec/frontend/packages/details/store/actions_spec.js @@ -1,9 +1,10 @@ import testAction from 'helpers/vuex_action_helper'; import Api from '~/api'; import { deprecatedCreateFlash as createFlash } from '~/flash'; -import fetchPackageVersions from '~/packages/details/store/actions'; +import { fetchPackageVersions, deletePackage } from '~/packages/details/store/actions'; import * as types from '~/packages/details/store/mutation_types'; import { FETCH_PACKAGE_VERSIONS_ERROR } from '~/packages/details/constants'; +import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants'; import { npmPackage as packageEntity } from '../../mock_data'; jest.mock('~/flash.js'); @@ -73,4 +74,25 @@ describe('Actions Package details store', () => { ); }); }); + + describe('deletePackage', () => { + it('should call Api.deleteProjectPackage', done => { + Api.deleteProjectPackage = jest.fn().mockResolvedValue(); + testAction(deletePackage, undefined, { packageEntity }, [], [], () => { + expect(Api.deleteProjectPackage).toHaveBeenCalledWith( + packageEntity.project_id, + packageEntity.id, + ); + done(); + }); + }); + it('should create flash on API error', done => { + Api.deleteProjectPackage = jest.fn().mockRejectedValue(); + + testAction(deletePackage, undefined, { packageEntity }, [], [], () => { + expect(createFlash).toHaveBeenCalledWith(DELETE_PACKAGE_ERROR_MESSAGE); + done(); + }); + }); + }); }); diff --git a/spec/frontend/packages/details/store/getters_spec.js b/spec/frontend/packages/details/store/getters_spec.js index 307976d4124..0e95ee4cfd3 100644 --- a/spec/frontend/packages/details/store/getters_spec.js +++ b/spec/frontend/packages/details/store/getters_spec.js @@ -62,9 +62,9 @@ describe('Getters PackageDetails Store', () => { const mavenSetupXmlBlock = generateMavenSetupXml(); const npmInstallStr = `npm i ${npmPackage.name}`; - const npmSetupStr = `echo @Test:registry=${registryUrl} >> .npmrc`; + const npmSetupStr = `echo @Test:registry=${registryUrl}/ >> .npmrc`; const yarnInstallStr = `yarn add ${npmPackage.name}`; - const yarnSetupStr = `echo \\"@Test:registry\\" \\"${registryUrl}\\" >> .yarnrc`; + const yarnSetupStr = `echo \\"@Test:registry\\" \\"${registryUrl}/\\" >> .yarnrc`; const nugetInstallationCommandStr = `nuget install ${nugetPackage.name} -Source "GitLab"`; const nugetSetupCommandStr = `nuget source Add -Name "GitLab" -Source "${registryUrl}" -UserName <your_username> -Password <your_token>`; |