diff options
Diffstat (limited to 'spec/frontend/design_management')
12 files changed, 180 insertions, 202 deletions
diff --git a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js index 9fbd9b2c2a3..77fc70e08d1 100644 --- a/spec/frontend/design_management/components/design_notes/design_discussion_spec.js +++ b/spec/frontend/design_management/components/design_notes/design_discussion_spec.js @@ -108,7 +108,7 @@ describe('Design discussions component', () => { it('renders correct amount of discussion notes', () => { expect(findDesignNotes()).toHaveLength(2); - expect(findDesignNotes().wrappers.every(w => w.isVisible())).toBe(true); + expect(findDesignNotes().wrappers.every((w) => w.isVisible())).toBe(true); }); it('renders reply placeholder', () => { @@ -150,16 +150,8 @@ describe('Design discussions component', () => { }); it('shows only the first note', () => { - expect( - findDesignNotes() - .at(0) - .isVisible(), - ).toBe(true); - expect( - findDesignNotes() - .at(1) - .isVisible(), - ).toBe(false); + expect(findDesignNotes().at(0).isVisible()).toBe(true); + expect(findDesignNotes().at(1).isVisible()).toBe(false); }); it('renders resolved message', () => { @@ -193,11 +185,7 @@ describe('Design discussions component', () => { }); it('renders the second note', () => { - expect( - findDesignNotes() - .at(1) - .isVisible(), - ).toBe(true); + expect(findDesignNotes().at(1).isVisible()).toBe(true); }); it('renders a reply placeholder', () => { @@ -263,7 +251,7 @@ describe('Design discussions component', () => { describe('when any note from a discussion is active', () => { it.each([notes[0], notes[0].discussion.notes.nodes[1]])( 'applies correct class to all notes in the active discussion', - note => { + (note) => { createComponent( { discussion: mockDiscussion }, { @@ -277,7 +265,7 @@ describe('Design discussions component', () => { expect( wrapper .findAll(DesignNote) - .wrappers.every(designNote => designNote.classes('gl-bg-blue-50')), + .wrappers.every((designNote) => designNote.classes('gl-bg-blue-50')), ).toBe(true); }, ); diff --git a/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js b/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js index 1a80fc4e761..a338a5ef200 100644 --- a/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js +++ b/spec/frontend/design_management/components/design_notes/design_reply_form_spec.js @@ -36,7 +36,7 @@ describe('Design reply form component', () => { it('textarea has focus after component mount', () => { // We need to attach to document, so that `document.activeElement` is properly set in jsdom - createComponent({}, { attachToDocument: true }); + createComponent({}, { attachTo: document.body }); expect(findTextarea().element).toEqual(document.activeElement); }); diff --git a/spec/frontend/design_management/components/design_overlay_spec.js b/spec/frontend/design_management/components/design_overlay_spec.js index f4fd4c70dfc..a026cc39c84 100644 --- a/spec/frontend/design_management/components/design_overlay_spec.js +++ b/spec/frontend/design_management/components/design_overlay_spec.js @@ -13,7 +13,7 @@ describe('Design overlay component', () => { const findAllNotes = () => wrapper.findAll('.js-image-badge'); const findCommentBadge = () => wrapper.find('.comment-indicator'); - const findBadgeAtIndex = noteIndex => findAllNotes().at(noteIndex); + const findBadgeAtIndex = (noteIndex) => findAllNotes().at(noteIndex); const findFirstBadge = () => findBadgeAtIndex(0); const findSecondBadge = () => findBadgeAtIndex(1); @@ -108,7 +108,7 @@ describe('Design overlay component', () => { describe('when no discussion is active', () => { it('should not apply inactive class to any pins', () => { expect( - findAllNotes(0).wrappers.every(designNote => designNote.classes('gl-bg-blue-50')), + findAllNotes(0).wrappers.every((designNote) => designNote.classes('gl-bg-blue-50')), ).toBe(false); }); }); @@ -116,7 +116,7 @@ describe('Design overlay component', () => { describe('when a discussion is active', () => { it.each([notes[0].discussion.notes.nodes[1], notes[0].discussion.notes.nodes[0]])( 'should not apply inactive class to the pin for the active discussion', - note => { + (note) => { wrapper.setData({ activeDiscussion: { id: note.id, diff --git a/spec/frontend/design_management/components/design_presentation_spec.js b/spec/frontend/design_management/components/design_presentation_spec.js index d633d00f2ed..31fd154dc4b 100644 --- a/spec/frontend/design_management/components/design_presentation_spec.js +++ b/spec/frontend/design_management/components/design_presentation_spec.js @@ -1,3 +1,4 @@ +import { nextTick } from 'vue'; import { shallowMount } from '@vue/test-utils'; import DesignPresentation from '~/design_management/components/design_presentation.vue'; import DesignOverlay from '~/design_management/components/design_overlay.vue'; @@ -100,12 +101,12 @@ describe('Design management design presentation component', () => { clientY: endCoords.clientY, }); - return wrapper.vm.$nextTick(); + return nextTick(); }) .then(() => { if (mouseup) { addCommentOverlay.trigger(event.mouseup); - return wrapper.vm.$nextTick(); + return nextTick(); } return undefined; @@ -125,7 +126,7 @@ describe('Design management design presentation component', () => { mockOverlayData, ); - return wrapper.vm.$nextTick().then(() => { + return nextTick().then(() => { expect(wrapper.element).toMatchSnapshot(); }); }); @@ -133,7 +134,7 @@ describe('Design management design presentation component', () => { it('renders empty state when no image provided', () => { createComponent(); - return wrapper.vm.$nextTick().then(() => { + return nextTick().then(() => { expect(wrapper.element).toMatchSnapshot(); }); }); @@ -149,7 +150,7 @@ describe('Design management design presentation component', () => { wrapper.vm.openCommentForm({ x: 1, y: 1 }); - return wrapper.vm.$nextTick().then(() => { + return nextTick().then(() => { expect(wrapper.emitted('openCommentForm')).toEqual([ [{ ...mockOverlayData.overlayDimensions, x: 1, y: 1 }], ]); @@ -166,7 +167,7 @@ describe('Design management design presentation component', () => { mockOverlayData, ); - return wrapper.vm.$nextTick().then(() => { + return nextTick().then(() => { expect(wrapper.vm.currentCommentForm).toBeNull(); expect(wrapper.element).toMatchSnapshot(); }); @@ -182,7 +183,7 @@ describe('Design management design presentation component', () => { mockOverlayData, ); - return wrapper.vm.$nextTick().then(() => { + return nextTick().then(() => { expect(wrapper.vm.currentCommentForm).toBeNull(); expect(wrapper.element).toMatchSnapshot(); }); @@ -206,7 +207,7 @@ describe('Design management design presentation component', () => { }, ); - return wrapper.vm.$nextTick().then(() => { + return nextTick().then(() => { expect(wrapper.vm.currentCommentForm).toEqual({ x: 1, y: 1, @@ -379,7 +380,7 @@ describe('Design management design presentation component', () => { }); describe('onImageResize', () => { - it('sets zoom focal point on initial load', () => { + beforeEach(() => { createComponent( { image: 'test.jpg', @@ -388,22 +389,21 @@ describe('Design management design presentation component', () => { mockOverlayData, ); - wrapper.setMethods({ - shiftZoomFocalPoint: jest.fn(), - scaleZoomFocalPoint: jest.fn(), - scrollToFocalPoint: jest.fn(), - }); - + jest.spyOn(wrapper.vm, 'shiftZoomFocalPoint'); + jest.spyOn(wrapper.vm, 'scaleZoomFocalPoint'); + jest.spyOn(wrapper.vm, 'scrollToFocalPoint'); wrapper.vm.onImageResize({ width: 10, height: 10 }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.shiftZoomFocalPoint).toHaveBeenCalled(); - expect(wrapper.vm.initialLoad).toBe(false); - }); + return nextTick(); + }); + + it('sets zoom focal point on initial load', () => { + expect(wrapper.vm.shiftZoomFocalPoint).toHaveBeenCalled(); + expect(wrapper.vm.initialLoad).toBe(false); }); it('calls scaleZoomFocalPoint and scrollToFocalPoint after initial load', () => { wrapper.vm.onImageResize({ width: 10, height: 10 }); - return wrapper.vm.$nextTick().then(() => { + return nextTick().then(() => { expect(wrapper.vm.scaleZoomFocalPoint).toHaveBeenCalled(); expect(wrapper.vm.scrollToFocalPoint).toHaveBeenCalled(); }); @@ -506,7 +506,7 @@ describe('Design management design presentation component', () => { .$nextTick() .then(() => { addCommentOverlay.trigger('mouseup'); - return wrapper.vm.$nextTick(); + return nextTick(); }) .then(() => { expect(wrapper.emitted('openCommentForm')).toBeDefined(); diff --git a/spec/frontend/design_management/components/design_scaler_spec.js b/spec/frontend/design_management/components/design_scaler_spec.js index 290ec3a18e3..40f53e8d0bf 100644 --- a/spec/frontend/design_management/components/design_scaler_spec.js +++ b/spec/frontend/design_management/components/design_scaler_spec.js @@ -10,7 +10,7 @@ describe('Design management design scaler component', () => { const getResetScaleButton = () => getButtons().at(1); const getIncreaseScaleButton = () => getButtons().at(2); - const setScale = scale => wrapper.vm.setScale(scale); + const setScale = (scale) => wrapper.vm.setScale(scale); const createComponent = () => { wrapper = shallowMount(DesignScaler); diff --git a/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap b/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap index de276bd300b..36a2ffd19c3 100644 --- a/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap +++ b/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap @@ -10,7 +10,10 @@ exports[`Design management list item component when item appears in view after i exports[`Design management list item component with notes renders item with multiple comments 1`] = ` <router-link-stub + ariacurrentvalue="page" class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new" + event="click" + tag="a" to="[object Object]" > <div @@ -81,7 +84,10 @@ exports[`Design management list item component with notes renders item with mult exports[`Design management list item component with notes renders item with single comment 1`] = ` <router-link-stub + ariacurrentvalue="page" class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new" + event="click" + tag="a" to="[object Object]" > <div diff --git a/spec/frontend/design_management/components/toolbar/index_spec.js b/spec/frontend/design_management/components/toolbar/index_spec.js index 2914365b0df..6ac088a2c53 100644 --- a/spec/frontend/design_management/components/toolbar/index_spec.js +++ b/spec/frontend/design_management/components/toolbar/index_spec.js @@ -116,6 +116,8 @@ describe('Design management toolbar component', () => { }); it('renders download button with correct link', () => { + createComponent(); + expect(wrapper.find(GlButton).attributes('href')).toBe( '/-/designs/306/7f747adcd4693afadbe968d7ba7d983349b9012d', ); diff --git a/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap b/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap index 8c6b446794f..63afc3f000d 100644 --- a/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap +++ b/spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap @@ -4,6 +4,7 @@ exports[`Design management design version dropdown component renders design vers <gl-dropdown-stub category="primary" headertext="" + hideheaderborder="true" issueiid="" projectpath="" size="small" @@ -44,6 +45,7 @@ exports[`Design management design version dropdown component renders design vers <gl-dropdown-stub category="primary" headertext="" + hideheaderborder="true" issueiid="" projectpath="" size="small" diff --git a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js index 4ef787ac754..d841aabf2f3 100644 --- a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js +++ b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js @@ -6,7 +6,7 @@ import mockAllVersions from './mock_data/all_versions'; const LATEST_VERSION_ID = 3; const PREVIOUS_VERSION_ID = 2; -const designRouteFactory = versionId => ({ +const designRouteFactory = (versionId) => ({ path: `/designs?version=${versionId}`, query: { version: `${versionId}`, @@ -42,7 +42,7 @@ describe('Design management design version dropdown component', () => { wrapper.destroy(); }); - const findVersionLink = index => wrapper.findAll(GlDropdownItem).at(index); + const findVersionLink = (index) => wrapper.findAll(GlDropdownItem).at(index); it('renders design version dropdown button', () => { createComponent(); diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js index 147169dd9aa..7d28d6f6d11 100644 --- a/spec/frontend/design_management/pages/index_spec.js +++ b/spec/frontend/design_management/pages/index_spec.js @@ -1,14 +1,15 @@ +import { nextTick } from 'vue'; import { createLocalVue, shallowMount } from '@vue/test-utils'; import VueApollo, { ApolloMutation } from 'vue-apollo'; import VueDraggable from 'vuedraggable'; import VueRouter from 'vue-router'; import { GlEmptyState } from '@gitlab/ui'; -import createMockApollo from 'jest/helpers/mock_apollo_helper'; +import createMockApollo from 'helpers/mock_apollo_helper'; import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import getDesignListQuery from 'shared_queries/design_management/get_design_list.query.graphql'; import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql'; import Index from '~/design_management/pages/index.vue'; -import uploadDesignQuery from '~/design_management/graphql/mutations/upload_design.mutation.graphql'; +import uploadDesignMutation from '~/design_management/graphql/mutations/upload_design.mutation.graphql'; import DesignDestroyer from '~/design_management/components/design_destroyer.vue'; import DesignDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue'; import DeleteButton from '~/design_management/components/delete_button.vue'; @@ -113,7 +114,7 @@ describe('Design management index page', () => { async function moveDesigns(localWrapper) { await jest.runOnlyPendingTimers(); - await localWrapper.vm.$nextTick(); + await nextTick(); localWrapper.find(VueDraggable).vm.$emit('input', reorderedDesigns); localWrapper.find(VueDraggable).vm.$emit('change', { @@ -159,7 +160,7 @@ describe('Design management index page', () => { localVue, router, stubs: { DesignDestroyer, ApolloMutation, VueDraggable, ...stubs }, - attachToDocument: true, + attachTo: document.body, provide: { projectPath: 'project-path', issueIid: '1', @@ -200,14 +201,13 @@ describe('Design management index page', () => { expect(wrapper.element).toMatchSnapshot(); }); - it('renders error', () => { + it('renders error', async () => { createComponent(); wrapper.setData({ error: true }); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.element).toMatchSnapshot(); - }); + await nextTick(); + expect(wrapper.element).toMatchSnapshot(); }); it('renders a toolbar with buttons when there are designs', () => { @@ -254,10 +254,10 @@ describe('Design management index page', () => { createComponent({ designCollection: { designs: [], copyState: 'READY' } }); }); - it('renders design dropzone', () => - wrapper.vm.$nextTick().then(() => { - expect(findDropzone().exists()).toBe(true); - })); + it('renders design dropzone', async () => { + await nextTick(); + expect(findDropzone().exists()).toBe(true); + }); it('has correct classes applied to design dropzone', () => { expect(dropzoneClasses()).not.toContain('design-list-item'); @@ -268,10 +268,10 @@ describe('Design management index page', () => { expect(findDropzoneWrapper().classes()).toEqual(['col-12']); }); - it('does not render a toolbar with buttons', () => - wrapper.vm.$nextTick().then(() => { - expect(findToolbar().exists()).toBe(false); - })); + it('does not render a toolbar with buttons', async () => { + await nextTick(); + expect(findToolbar().exists()).toBe(false); + }); }); describe('handling design collection copy state', () => { @@ -290,7 +290,7 @@ describe('Design management index page', () => { }); describe('uploading designs', () => { - it('calls mutation on upload', () => { + it('calls mutation on upload', async () => { createComponent({ stubs: { GlEmptyState } }); const mutationVariables = { @@ -298,7 +298,7 @@ describe('Design management index page', () => { context: { hasUpload: true, }, - mutation: uploadDesignQuery, + mutation: uploadDesignMutation, variables: { files: [{ name: 'test' }], projectPath: 'project-path', @@ -348,21 +348,16 @@ describe('Design management index page', () => { }, }; - return wrapper.vm - .$nextTick() - .then(() => { - findDropzone().vm.$emit('change', [{ name: 'test' }]); - expect(mutate).toHaveBeenCalledWith(mutationVariables); - expect(wrapper.vm.filesToBeSaved).toEqual([{ name: 'test' }]); - expect(wrapper.vm.isSaving).toBeTruthy(); - }) - .then(() => { - expect(dropzoneClasses()).toContain('design-list-item'); - expect(dropzoneClasses()).toContain('design-list-item-new'); - }); + await nextTick(); + findDropzone().vm.$emit('change', [{ name: 'test' }]); + expect(mutate).toHaveBeenCalledWith(mutationVariables); + expect(wrapper.vm.filesToBeSaved).toEqual([{ name: 'test' }]); + expect(wrapper.vm.isSaving).toBeTruthy(); + expect(dropzoneClasses()).toContain('design-list-item'); + expect(dropzoneClasses()).toContain('design-list-item-new'); }); - it('sets isSaving', () => { + it('sets isSaving', async () => { createComponent(); const uploadDesign = wrapper.vm.onUploadDesign([ @@ -373,35 +368,31 @@ describe('Design management index page', () => { expect(wrapper.vm.isSaving).toBe(true); - return uploadDesign.then(() => { - expect(wrapper.vm.isSaving).toBe(false); - }); + await uploadDesign; + expect(wrapper.vm.isSaving).toBe(false); }); - it('updates state appropriately after upload complete', () => { + it('updates state appropriately after upload complete', async () => { createComponent({ stubs: { GlEmptyState } }); wrapper.setData({ filesToBeSaved: [{ name: 'test' }] }); wrapper.vm.onUploadDesignDone(designUploadMutationCreatedResponse); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.filesToBeSaved).toEqual([]); - expect(wrapper.vm.isSaving).toBeFalsy(); - expect(wrapper.vm.isLatestVersion).toBe(true); - }); + await nextTick(); + + expect(wrapper.vm.filesToBeSaved).toEqual([]); + expect(wrapper.vm.isSaving).toBeFalsy(); + expect(wrapper.vm.isLatestVersion).toBe(true); }); - it('updates state appropriately after upload error', () => { + it('updates state appropriately after upload error', async () => { createComponent({ stubs: { GlEmptyState } }); wrapper.setData({ filesToBeSaved: [{ name: 'test' }] }); wrapper.vm.onUploadDesignError(); - return wrapper.vm.$nextTick().then(() => { - expect(wrapper.vm.filesToBeSaved).toEqual([]); - expect(wrapper.vm.isSaving).toBeFalsy(); - expect(createFlash).toHaveBeenCalled(); - - createFlash.mockReset(); - }); + await nextTick(); + expect(wrapper.vm.filesToBeSaved).toEqual([]); + expect(wrapper.vm.isSaving).toBeFalsy(); + expect(createFlash).toHaveBeenCalled(); }); it('does not call mutation if createDesign is false', () => { @@ -415,10 +406,6 @@ describe('Design management index page', () => { describe('upload count limit', () => { const MAXIMUM_FILE_UPLOAD_LIMIT = 10; - afterEach(() => { - createFlash.mockReset(); - }); - it('does not warn when the max files are uploaded', () => { createComponent(); @@ -436,7 +423,7 @@ describe('Design management index page', () => { }); }); - it('flashes warning if designs are skipped', () => { + it('flashes warning if designs are skipped', async () => { createComponent({ mockMutate: () => Promise.resolve({ @@ -450,25 +437,22 @@ describe('Design management index page', () => { }, ]); - return uploadDesign.then(() => { - expect(createFlash).toHaveBeenCalledTimes(1); - expect(createFlash).toHaveBeenCalledWith({ - message: 'Upload skipped. test.jpg did not change.', - types: 'warning', - }); + await uploadDesign; + expect(createFlash).toHaveBeenCalledTimes(1); + expect(createFlash).toHaveBeenCalledWith({ + message: 'Upload skipped. test.jpg did not change.', + types: 'warning', }); }); describe('dragging onto an existing design', () => { + let mockMutate; beforeEach(() => { - createComponent({ designs: mockDesigns, allVersions: [mockVersion] }); + mockMutate = jest.fn().mockResolvedValue(); + createComponent({ designs: mockDesigns, allVersions: [mockVersion], mockMutate }); }); - it('calls onUploadDesign with valid upload', () => { - wrapper.setMethods({ - onUploadDesign: jest.fn(), - }); - + it('uploads designs with valid upload', () => { const mockUploadPayload = [ { name: mockDesigns[0].filename, @@ -478,8 +462,13 @@ describe('Design management index page', () => { const designDropzone = findFirstDropzoneWithDesign(); designDropzone.vm.$emit('change', mockUploadPayload); - expect(wrapper.vm.onUploadDesign).toHaveBeenCalledTimes(1); - expect(wrapper.vm.onUploadDesign).toHaveBeenCalledWith(mockUploadPayload); + const [{ mutation, variables }] = mockMutate.mock.calls[0]; + expect(mutation).toBe(uploadDesignMutation); + expect(variables).toStrictEqual({ + files: mockUploadPayload, + iid: '1', + projectPath: 'project-path', + }); }); it.each` @@ -544,57 +533,39 @@ describe('Design management index page', () => { expect(findToolbar().isVisible()).toBe(true); }); - it('adds two designs to selected designs when their checkboxes are checked', () => { - findDesignCheckboxes() - .at(0) - .trigger('click'); - - return wrapper.vm - .$nextTick() - .then(() => { - findDesignCheckboxes() - .at(1) - .trigger('click'); - - return wrapper.vm.$nextTick(); - }) - .then(() => { - expect(findDeleteButton().exists()).toBe(true); - expect(findSelectAllButton().text()).toBe('Deselect all'); - findDeleteButton().vm.$emit('deleteSelectedDesigns'); - const [{ variables }] = mutate.mock.calls[0]; - expect(variables.filenames).toStrictEqual([ - mockDesigns[0].filename, - mockDesigns[1].filename, - ]); - }); + it('adds two designs to selected designs when their checkboxes are checked', async () => { + findDesignCheckboxes().at(0).trigger('click'); + + await nextTick(); + findDesignCheckboxes().at(1).trigger('click'); + + await nextTick(); + expect(findDeleteButton().exists()).toBe(true); + expect(findSelectAllButton().text()).toBe('Deselect all'); + findDeleteButton().vm.$emit('deleteSelectedDesigns'); + const [{ variables }] = mutate.mock.calls[0]; + expect(variables.filenames).toStrictEqual([mockDesigns[0].filename, mockDesigns[1].filename]); }); - it('adds all designs to selected designs when Select All button is clicked', () => { + it('adds all designs to selected designs when Select All button is clicked', async () => { findSelectAllButton().vm.$emit('click'); - return wrapper.vm.$nextTick().then(() => { - expect(findDeleteButton().props().hasSelectedDesigns).toBe(true); - expect(findSelectAllButton().text()).toBe('Deselect all'); - expect(wrapper.vm.selectedDesigns).toEqual(mockDesigns.map(design => design.filename)); - }); + await nextTick(); + expect(findDeleteButton().props().hasSelectedDesigns).toBe(true); + expect(findSelectAllButton().text()).toBe('Deselect all'); + expect(wrapper.vm.selectedDesigns).toEqual(mockDesigns.map((design) => design.filename)); }); - it('removes all designs from selected designs when at least one design was selected', () => { - findDesignCheckboxes() - .at(0) - .trigger('click'); - - return wrapper.vm - .$nextTick() - .then(() => { - findSelectAllButton().vm.$emit('click'); - }) - .then(() => { - expect(findDeleteButton().props().hasSelectedDesigns).toBe(false); - expect(findSelectAllButton().text()).toBe('Select all'); - expect(wrapper.vm.selectedDesigns).toEqual([]); - }); + it('removes all designs from selected designs when at least one design was selected', async () => { + findDesignCheckboxes().at(0).trigger('click'); + await nextTick(); + + findSelectAllButton().vm.$emit('click'); + await nextTick(); + + expect(findDeleteButton().props().hasSelectedDesigns).toBe(false); + expect(findSelectAllButton().text()).toBe('Select all'); + expect(wrapper.vm.selectedDesigns).toEqual([]); }); }); @@ -632,12 +603,10 @@ describe('Design management index page', () => { describe('pasting a design', () => { let event; + let mockMutate; beforeEach(() => { - createComponent({ designs: mockDesigns, allVersions: [mockVersion] }); - - wrapper.setMethods({ - onUploadDesign: jest.fn(), - }); + mockMutate = jest.fn().mockResolvedValue({}); + createComponent({ designs: mockDesigns, allVersions: [mockVersion], mockMutate }); event = new Event('paste'); event.clipboardData = { @@ -646,36 +615,56 @@ describe('Design management index page', () => { }; }); - it('does not call paste event if designs wrapper is not hovered', () => { + it('does not upload designs if designs wrapper is not hovered', () => { document.dispatchEvent(event); - expect(wrapper.vm.onUploadDesign).not.toHaveBeenCalled(); + expect(mockMutate).not.toHaveBeenCalled(); }); describe('when designs wrapper is hovered', () => { + let realDateNow; + const today = () => new Date('2020-12-25'); + beforeAll(() => { + realDateNow = Date.now; + global.Date.now = today; + }); + + afterAll(() => { + global.Date.now = realDateNow; + }); + beforeEach(() => { findDesignsWrapper().trigger('mouseenter'); }); - it('calls onUploadDesign with valid paste', () => { + it('uploads design with valid paste', () => { document.dispatchEvent(event); - expect(wrapper.vm.onUploadDesign).toHaveBeenCalledTimes(1); - expect(wrapper.vm.onUploadDesign).toHaveBeenCalledWith([ - new File([{ name: 'image.png' }], 'test.png'), - ]); + const [{ mutation, variables }] = mockMutate.mock.calls[0]; + expect(mutation).toBe(uploadDesignMutation); + expect(variables).toStrictEqual({ + files: expect.any(Array), + iid: '1', + projectPath: 'project-path', + }); + expect(variables.files).toEqual(event.clipboardData.files.map((f) => new File([f], ''))); }); it('renames a design if it has an image.png filename', () => { + event.clipboardData.getData = () => 'image.png'; document.dispatchEvent(event); - expect(wrapper.vm.onUploadDesign).toHaveBeenCalledTimes(1); - expect(wrapper.vm.onUploadDesign).toHaveBeenCalledWith([ - new File([{ name: 'image.png' }], `design_${Date.now()}.png`), - ]); + const [{ mutation, variables }] = mockMutate.mock.calls[0]; + expect(mutation).toBe(uploadDesignMutation); + expect(variables).toStrictEqual({ + files: expect.any(Array), + iid: '1', + projectPath: 'project-path', + }); + expect(variables.files[0].name).toEqual(`design_${Date.now()}.png`); }); - it('does not call onUploadDesign with invalid paste', () => { + it('does not call upload with invalid paste', () => { event.clipboardData = { items: [{ type: 'text/plain' }, { type: 'text' }], files: [], @@ -683,28 +672,27 @@ describe('Design management index page', () => { document.dispatchEvent(event); - expect(wrapper.vm.onUploadDesign).not.toHaveBeenCalled(); + expect(mockMutate).not.toHaveBeenCalled(); }); it('removes onPaste listener after mouseleave event', async () => { findDesignsWrapper().trigger('mouseleave'); document.dispatchEvent(event); - expect(wrapper.vm.onUploadDesign).not.toHaveBeenCalled(); + expect(mockMutate).not.toHaveBeenCalled(); }); }); }); describe('when navigating', () => { - it('should trigger a scrollIntoView method if designs route is detected', () => { + it('should trigger a scrollIntoView method if designs route is detected', async () => { router.replace({ path: '/designs', }); createComponent({ loading: true }); - return wrapper.vm.$nextTick().then(() => { - expect(scrollIntoViewMock).toHaveBeenCalled(); - }); + await nextTick(); + expect(scrollIntoViewMock).toHaveBeenCalled(); }); }); @@ -713,14 +701,10 @@ describe('Design management index page', () => { createComponentWithApollo({}); await jest.runOnlyPendingTimers(); - await wrapper.vm.$nextTick(); + await nextTick(); expect(findDesigns()).toHaveLength(3); - expect( - findDesigns() - .at(0) - .props('id'), - ).toBe('1'); + expect(findDesigns().at(0).props('id')).toBe('1'); }); it('calls a mutation with correct parameters and reorders designs', async () => { @@ -730,13 +714,9 @@ describe('Design management index page', () => { expect(moveDesignHandler).toHaveBeenCalled(); - await wrapper.vm.$nextTick(); + await nextTick(); - expect( - findDesigns() - .at(0) - .props('id'), - ).toBe('2'); + expect(findDesigns().at(0).props('id')).toBe('2'); }); it('prevents reordering when reorderDesigns mutation is in progress', async () => { @@ -747,8 +727,8 @@ describe('Design management index page', () => { expect(draggableAttributes().disabled).toBe(true); await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises) - await wrapper.vm.$nextTick(); // kick off the DOM update - await wrapper.vm.$nextTick(); // kick off the DOM update for finally block + await nextTick(); // kick off the DOM update + await nextTick(); // kick off the DOM update for finally block expect(draggableAttributes().disabled).toBe(false); }); @@ -760,7 +740,7 @@ describe('Design management index page', () => { await moveDesigns(wrapper); - await wrapper.vm.$nextTick(); + await nextTick(); expect(createFlash).toHaveBeenCalledWith({ message: 'Houston, we have a problem' }); }); @@ -772,9 +752,9 @@ describe('Design management index page', () => { await moveDesigns(wrapper); - await wrapper.vm.$nextTick(); // kick off the DOM update + await nextTick(); // kick off the DOM update await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises) - await wrapper.vm.$nextTick(); // kick off the DOM update for flash + await nextTick(); // kick off the DOM update for flash expect(createFlash).toHaveBeenCalledWith({ message: 'Something went wrong when reordering designs. Please try again', diff --git a/spec/frontend/design_management/router_spec.js b/spec/frontend/design_management/router_spec.js index fac4f7d368d..0b4e68eea78 100644 --- a/spec/frontend/design_management/router_spec.js +++ b/spec/frontend/design_management/router_spec.js @@ -40,7 +40,7 @@ describe('Design management router', () => { window.location.hash = ''; }); - describe.each([['/'], [{ name: DESIGNS_ROUTE_NAME }]])('root route', routeArg => { + describe.each([['/'], [{ name: DESIGNS_ROUTE_NAME }]])('root route', (routeArg) => { it('pushes home component', () => { const wrapper = factory(routeArg); @@ -50,7 +50,7 @@ describe('Design management router', () => { describe.each([['/designs/1'], [{ name: DESIGN_ROUTE_NAME, params: { id: '1' } }]])( 'designs detail route', - routeArg => { + (routeArg) => { it('pushes designs detail component', () => { const wrapper = factory(routeArg); diff --git a/spec/frontend/design_management/utils/error_messages_spec.js b/spec/frontend/design_management/utils/error_messages_spec.js index f5072c3b6b7..b80dcd9abde 100644 --- a/spec/frontend/design_management/utils/error_messages_spec.js +++ b/spec/frontend/design_management/utils/error_messages_spec.js @@ -3,7 +3,7 @@ import { designUploadSkippedWarning, } from '~/design_management/utils/error_messages'; -const mockFilenames = n => +const mockFilenames = (n) => Array(n) .fill(0) .map((_, i) => ({ filename: `${i + 1}.jpg` })); @@ -14,7 +14,7 @@ describe('Error message', () => { const pluralMsg = 'Could not archive designs. Please try again.'; describe('when [singular=true]', () => { - it.each([[undefined], [true]])('uses singular grammar', singularOption => { + it.each([[undefined], [true]])('uses singular grammar', (singularOption) => { expect(designDeletionError({ singular: singularOption })).toEqual(singularMsg); }); }); |