diff options
Diffstat (limited to 'spec/frontend/design_management/pages')
3 files changed, 133 insertions, 31 deletions
diff --git a/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap b/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap index b80b7fdb43e..2d29b79e31c 100644 --- a/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap +++ b/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap @@ -8,7 +8,7 @@ exports[`Design management index page designs does not render toolbar when there <!----> <div - class="mt-4" + class="gl-mt-6" > <ol class="list-unstyled row" @@ -19,6 +19,7 @@ exports[`Design management index page designs does not render toolbar when there > <design-dropzone-stub class="design-list-item design-list-item-new" + data-qa-selector="design_dropzone_content" hasdesigns="true" /> </li> @@ -91,7 +92,7 @@ exports[`Design management index page designs renders designs list and header wi data-testid="designs-root" > <header - class="row-content-block border-top-0 p-2 d-flex" + class="row-content-block gl-border-t-0 gl-p-3 gl-display-flex" > <div class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-w-full" @@ -110,6 +111,7 @@ exports[`Design management index page designs renders designs list and header wi class="qa-selector-toolbar gl-display-flex gl-align-items-center" > <gl-button-stub + buttontextclasses="" category="primary" class="gl-mr-4 js-select-all" icon="" @@ -126,6 +128,7 @@ exports[`Design management index page designs renders designs list and header wi buttonclass="gl-mr-3" buttonsize="small" buttonvariant="warning" + data-qa-selector="archive_button" > Archive selected @@ -139,7 +142,7 @@ exports[`Design management index page designs renders designs list and header wi </header> <div - class="mt-4" + class="gl-mt-6" > <ol class="list-unstyled row" @@ -150,6 +153,7 @@ exports[`Design management index page designs renders designs list and header wi > <design-dropzone-stub class="design-list-item design-list-item-new" + data-qa-selector="design_dropzone_content" hasdesigns="true" /> </li> @@ -171,6 +175,8 @@ exports[`Design management index page designs renders designs list and header wi <input class="design-checkbox" + data-qa-design="design-1-name" + data-qa-selector="design_checkbox" type="checkbox" /> </li> @@ -192,6 +198,8 @@ exports[`Design management index page designs renders designs list and header wi <input class="design-checkbox" + data-qa-design="design-2-name" + data-qa-selector="design_checkbox" type="checkbox" /> </li> @@ -213,6 +221,8 @@ exports[`Design management index page designs renders designs list and header wi <input class="design-checkbox" + data-qa-design="design-3-name" + data-qa-selector="design_checkbox" type="checkbox" /> </li> @@ -233,7 +243,7 @@ exports[`Design management index page designs renders error 1`] = ` <!----> <div - class="mt-4" + class="gl-mt-6" > <gl-alert-stub dismisslabel="Dismiss" @@ -264,7 +274,7 @@ exports[`Design management index page designs renders loading icon 1`] = ` <!----> <div - class="mt-4" + class="gl-mt-6" > <gl-loading-icon-stub color="orange" @@ -287,7 +297,7 @@ exports[`Design management index page when has no designs renders design dropzon <!----> <div - class="mt-4" + class="gl-mt-6" > <ol class="list-unstyled row" @@ -298,6 +308,7 @@ exports[`Design management index page when has no designs renders design dropzon > <design-dropzone-stub class="" + data-qa-selector="design_dropzone_content" /> </li> </ol> diff --git a/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap b/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap index c849e4d4ed6..3d6c2561ff6 100644 --- a/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap +++ b/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap @@ -2,10 +2,10 @@ exports[`Design management design index page renders design index 1`] = ` <div - class="design-detail js-design-detail fixed-top w-100 position-bottom-0 d-flex justify-content-center flex-column flex-lg-row" + class="design-detail js-design-detail fixed-top gl-w-full gl-bottom-0 gl-display-flex gl-justify-content-center gl-flex-direction-column gl-lg-flex-direction-row" > <div - class="d-flex overflow-hidden flex-grow-1 flex-column position-relative" + class="gl-display-flex gl-overflow-hidden gl-flex-grow-1 gl-flex-direction-column gl-relative" > <design-destroyer-stub filenames="test.jpg" @@ -23,16 +23,26 @@ exports[`Design management design index page renders design index 1`] = ` /> <div - class="design-scaler-wrapper position-absolute mb-4 d-flex-center" + class="design-scaler-wrapper gl-absolute gl-mb-6 gl-display-flex gl-justify-content-center gl-align-items-center" > <design-scaler-stub /> </div> </div> <div - class="image-notes" + class="image-notes gl-pt-0" > - <!----> + <div + class="gl-py-4 gl-mb-4 gl-display-flex gl-justify-content-space-between gl-align-items-center gl-border-b-1 gl-border-b-solid gl-border-b-gray-100" + > + <span> + To Do + </span> + + <design-todo-button-stub + design="[object Object]" + /> + </div> <h2 class="gl-font-weight-bold gl-mt-0" @@ -67,6 +77,7 @@ exports[`Design management design index page renders design index 1`] = ` /> <gl-button-stub + buttontextclasses="" category="primary" class="link-inherit-color gl-text-body gl-text-decoration-none gl-font-weight-bold gl-mb-4" data-testid="resolved-comments" @@ -121,10 +132,10 @@ exports[`Design management design index page renders design index 1`] = ` exports[`Design management design index page sets loading state 1`] = ` <div - class="design-detail js-design-detail fixed-top w-100 position-bottom-0 d-flex justify-content-center flex-column flex-lg-row" + class="design-detail js-design-detail fixed-top gl-w-full gl-bottom-0 gl-display-flex gl-justify-content-center gl-flex-direction-column gl-lg-flex-direction-row" > <gl-loading-icon-stub - class="align-self-center" + class="gl-align-self-center" color="orange" label="Loading" size="xl" @@ -134,10 +145,10 @@ exports[`Design management design index page sets loading state 1`] = ` exports[`Design management design index page with error GlAlert is rendered in correct position with correct content 1`] = ` <div - class="design-detail js-design-detail fixed-top w-100 position-bottom-0 d-flex justify-content-center flex-column flex-lg-row" + class="design-detail js-design-detail fixed-top gl-w-full gl-bottom-0 gl-display-flex gl-justify-content-center gl-flex-direction-column gl-lg-flex-direction-row" > <div - class="d-flex overflow-hidden flex-grow-1 flex-column position-relative" + class="gl-display-flex gl-overflow-hidden gl-flex-grow-1 gl-flex-direction-column gl-relative" > <design-destroyer-stub filenames="test.jpg" @@ -146,7 +157,7 @@ exports[`Design management design index page with error GlAlert is rendered in c /> <div - class="p-3" + class="gl-p-5" > <gl-alert-stub dismissible="true" @@ -172,16 +183,26 @@ exports[`Design management design index page with error GlAlert is rendered in c /> <div - class="design-scaler-wrapper position-absolute mb-4 d-flex-center" + class="design-scaler-wrapper gl-absolute gl-mb-6 gl-display-flex gl-justify-content-center gl-align-items-center" > <design-scaler-stub /> </div> </div> <div - class="image-notes" + class="image-notes gl-pt-0" > - <!----> + <div + class="gl-py-4 gl-mb-4 gl-display-flex gl-justify-content-space-between gl-align-items-center gl-border-b-1 gl-border-b-solid gl-border-b-gray-100" + > + <span> + To Do + </span> + + <design-todo-button-stub + design="[object Object]" + /> + </div> <h2 class="gl-font-weight-bold gl-mt-0" diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js index 661717d29a3..27a91b11448 100644 --- a/spec/frontend/design_management/pages/index_spec.js +++ b/spec/frontend/design_management/pages/index_spec.js @@ -4,6 +4,7 @@ import VueDraggable from 'vuedraggable'; import VueRouter from 'vue-router'; import { GlEmptyState } from '@gitlab/ui'; import createMockApollo from 'jest/helpers/mock_apollo_helper'; +import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import Index from '~/design_management/pages/index.vue'; import uploadDesignQuery from '~/design_management/graphql/mutations/upload_design.mutation.graphql'; import DesignDestroyer from '~/design_management/components/design_destroyer.vue'; @@ -21,6 +22,8 @@ import * as utils from '~/design_management/utils/design_management_utils'; import { DESIGN_DETAIL_LAYOUT_CLASSLIST } from '~/design_management/constants'; import { designListQueryResponse, + designUploadMutationCreatedResponse, + designUploadMutationUpdatedResponse, permissionsQueryResponse, moveDesignMutationResponse, reorderedDesigns, @@ -29,6 +32,7 @@ import { import getDesignListQuery from '~/design_management/graphql/queries/get_design_list.query.graphql'; import permissionsQuery from '~/design_management/graphql/queries/design_permissions.query.graphql'; import moveDesignMutation from '~/design_management/graphql/mutations/move_design.mutation.graphql'; +import { DESIGN_TRACKING_PAGE_NAME } from '~/design_management/utils/tracking'; jest.mock('~/flash.js'); const mockPageEl = { @@ -92,6 +96,8 @@ describe('Design management index page', () => { const findDesignCheckboxes = () => wrapper.findAll('.design-checkbox'); const findSelectAllButton = () => wrapper.find('.js-select-all'); const findToolbar = () => wrapper.find('.qa-selector-toolbar'); + const findDesignCollectionIsCopying = () => + wrapper.find('[data-testid="design-collection-is-copying"'); const findDeleteButton = () => wrapper.find(DeleteButton); const findDropzone = () => wrapper.findAll(DesignDropzone).at(0); const dropzoneClasses = () => findDropzone().classes(); @@ -99,6 +105,7 @@ describe('Design management index page', () => { const findFirstDropzoneWithDesign = () => wrapper.findAll(DesignDropzone).at(1); const findDesignsWrapper = () => wrapper.find('[data-testid="designs-root"]'); const findDesigns = () => wrapper.findAll(Design); + const draggableAttributes = () => wrapper.find(VueDraggable).vm.$attrs; async function moveDesigns(localWrapper) { await jest.runOnlyPendingTimers(); @@ -115,8 +122,8 @@ describe('Design management index page', () => { function createComponent({ loading = false, - designs = [], allVersions = [], + designCollection = { designs: mockDesigns, copyState: 'READY' }, createDesign = true, stubs = {}, mockMutate = jest.fn().mockResolvedValue(), @@ -124,7 +131,7 @@ describe('Design management index page', () => { mutate = mockMutate; const $apollo = { queries: { - designs: { + designCollection: { loading, }, permissions: { @@ -137,8 +144,8 @@ describe('Design management index page', () => { wrapper = shallowMount(Index, { data() { return { - designs, allVersions, + designCollection, permissions: { createDesign, }, @@ -200,13 +207,13 @@ describe('Design management index page', () => { }); it('renders a toolbar with buttons when there are designs', () => { - createComponent({ designs: mockDesigns, allVersions: [mockVersion] }); + createComponent({ allVersions: [mockVersion] }); expect(findToolbar().exists()).toBe(true); }); it('renders designs list and header with upload button', () => { - createComponent({ designs: mockDesigns, allVersions: [mockVersion] }); + createComponent({ allVersions: [mockVersion] }); expect(wrapper.element).toMatchSnapshot(); }); @@ -236,7 +243,7 @@ describe('Design management index page', () => { describe('when has no designs', () => { beforeEach(() => { - createComponent(); + createComponent({ designCollection: { designs: [], copyState: 'READY' } }); }); it('renders design dropzone', () => @@ -259,6 +266,21 @@ describe('Design management index page', () => { })); }); + describe('handling design collection copy state', () => { + it.each` + copyState | isRendered | description + ${'IN_PROGRESS'} | ${true} | ${'renders'} + ${'READY'} | ${false} | ${'does not render'} + ${'ERROR'} | ${false} | ${'does not render'} + `( + '$description the copying message if design collection copyState is $copyState', + ({ copyState, isRendered }) => { + createComponent({ designCollection: { designs: [], copyState } }); + expect(findDesignCollectionIsCopying().exists()).toBe(isRendered); + }, + ); + }); + describe('uploading designs', () => { it('calls mutation on upload', () => { createComponent({ stubs: { GlEmptyState } }); @@ -282,6 +304,10 @@ describe('Design management index page', () => { { __typename: 'Design', id: expect.anything(), + currentUserTodos: { + __typename: 'TodoConnection', + nodes: [], + }, image: '', imageV432x230: '', filename: 'test', @@ -348,7 +374,7 @@ describe('Design management index page', () => { createComponent({ stubs: { GlEmptyState } }); wrapper.setData({ filesToBeSaved: [{ name: 'test' }] }); - wrapper.vm.onUploadDesignDone(); + wrapper.vm.onUploadDesignDone(designUploadMutationCreatedResponse); return wrapper.vm.$nextTick().then(() => { expect(wrapper.vm.filesToBeSaved).toEqual([]); expect(wrapper.vm.isSaving).toBeFalsy(); @@ -460,6 +486,34 @@ describe('Design management index page', () => { expect(createFlash).toHaveBeenCalledWith(message); }); }); + + describe('tracking', () => { + let trackingSpy; + + beforeEach(() => { + trackingSpy = mockTracking('_category_', undefined, jest.spyOn); + + createComponent({ stubs: { GlEmptyState } }); + }); + + afterEach(() => { + unmockTracking(); + }); + + it('tracks design creation', () => { + wrapper.vm.onUploadDesignDone(designUploadMutationCreatedResponse); + + expect(trackingSpy).toHaveBeenCalledTimes(1); + expect(trackingSpy).toHaveBeenCalledWith(DESIGN_TRACKING_PAGE_NAME, 'create_design'); + }); + + it('tracks design modification', () => { + wrapper.vm.onUploadDesignDone(designUploadMutationUpdatedResponse); + + expect(trackingSpy).toHaveBeenCalledTimes(1); + expect(trackingSpy).toHaveBeenCalledWith(DESIGN_TRACKING_PAGE_NAME, 'update_design'); + }); + }); }); describe('on latest version when has designs', () => { @@ -531,13 +585,16 @@ describe('Design management index page', () => { }); it('on latest version when has no designs toolbar buttons are invisible', () => { - createComponent({ designs: [], allVersions: [mockVersion] }); + createComponent({ + designCollection: { designs: [], copyState: 'READY' }, + allVersions: [mockVersion], + }); expect(findToolbar().isVisible()).toBe(false); }); describe('on non-latest version', () => { beforeEach(() => { - createComponent({ designs: mockDesigns, allVersions: [mockVersion] }); + createComponent({ allVersions: [mockVersion] }); }); it('does not render design checkboxes', async () => { @@ -626,9 +683,8 @@ describe('Design management index page', () => { describe('when navigating', () => { it('ensures fullscreen layout is not applied', () => { - createComponent(true); + createComponent({ loading: true }); - wrapper.vm.$router.push('/'); expect(mockPageEl.classList.remove).toHaveBeenCalledTimes(1); expect(mockPageEl.classList.remove).toHaveBeenCalledWith(...DESIGN_DETAIL_LAYOUT_CLASSLIST); }); @@ -637,7 +693,7 @@ describe('Design management index page', () => { router.replace({ path: '/designs', }); - createComponent(true); + createComponent({ loading: true }); return wrapper.vm.$nextTick().then(() => { expect(scrollIntoViewMock).toHaveBeenCalled(); @@ -676,6 +732,20 @@ describe('Design management index page', () => { ).toBe('2'); }); + it('prevents reordering when reorderDesigns mutation is in progress', async () => { + createComponentWithApollo({}); + + await moveDesigns(wrapper); + + 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 + + expect(draggableAttributes().disabled).toBe(false); + }); + it('displays flash if mutation had a recoverable error', async () => { createComponentWithApollo({ moveHandler: jest.fn().mockResolvedValue(moveDesignMutationResponseWithErrors), |