diff options
Diffstat (limited to 'spec/frontend/design_management_legacy/pages/design')
-rw-r--r-- | spec/frontend/design_management_legacy/pages/design/__snapshots__/index_spec.js.snap | 216 | ||||
-rw-r--r-- | spec/frontend/design_management_legacy/pages/design/index_spec.js | 291 |
2 files changed, 507 insertions, 0 deletions
diff --git a/spec/frontend/design_management_legacy/pages/design/__snapshots__/index_spec.js.snap b/spec/frontend/design_management_legacy/pages/design/__snapshots__/index_spec.js.snap new file mode 100644 index 00000000000..dc5baf37fc6 --- /dev/null +++ b/spec/frontend/design_management_legacy/pages/design/__snapshots__/index_spec.js.snap @@ -0,0 +1,216 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +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" +> + <div + class="d-flex overflow-hidden flex-grow-1 flex-column position-relative" + > + <design-destroyer-stub + filenames="test.jpg" + iid="1" + projectpath="" + /> + + <!----> + + <design-presentation-stub + discussions="[object Object],[object Object]" + image="test.jpg" + imagename="test.jpg" + scale="1" + /> + + <div + class="design-scaler-wrapper position-absolute mb-4 d-flex-center" + > + <design-scaler-stub /> + </div> + </div> + + <div + class="image-notes" + > + <h2 + class="gl-font-weight-bold gl-mt-0" + > + + My precious issue + + </h2> + + <a + class="gl-text-gray-400 gl-text-decoration-none gl-mb-6 gl-display-block" + href="full-issue-url" + > + ull-issue-path + </a> + + <participants-stub + class="gl-mb-4" + numberoflessparticipants="7" + participants="[object Object]" + /> + + <!----> + + <design-discussion-stub + data-testid="unresolved-discussion" + designid="test" + discussion="[object Object]" + discussionwithopenform="" + markdownpreviewpath="//preview_markdown?target_type=Issue" + noteableid="design-id" + /> + + <gl-button-stub + category="primary" + class="link-inherit-color gl-text-body gl-text-decoration-none gl-font-weight-bold gl-mb-4" + data-testid="resolved-comments" + icon="chevron-right" + id="resolved-comments" + size="medium" + variant="link" + > + Resolved Comments (1) + + </gl-button-stub> + + <gl-popover-stub + container="popovercontainer" + cssclasses="" + placement="top" + show="true" + target="resolved-comments" + title="Resolved Comments" + > + <p> + + Comments you resolve can be viewed and unresolved by going to the "Resolved Comments" section below + + </p> + + <a + href="#" + rel="noopener noreferrer" + target="_blank" + > + Learn more about resolving comments + </a> + </gl-popover-stub> + + <gl-collapse-stub + class="gl-mt-3" + > + <design-discussion-stub + data-testid="resolved-discussion" + designid="test" + discussion="[object Object]" + discussionwithopenform="" + markdownpreviewpath="//preview_markdown?target_type=Issue" + noteableid="design-id" + /> + </gl-collapse-stub> + + </div> +</div> +`; + +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" +> + <gl-loading-icon-stub + class="align-self-center" + color="orange" + label="Loading" + size="xl" + /> +</div> +`; + +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" +> + <div + class="d-flex overflow-hidden flex-grow-1 flex-column position-relative" + > + <design-destroyer-stub + filenames="test.jpg" + iid="1" + projectpath="" + /> + + <div + class="p-3" + > + <gl-alert-stub + dismissible="true" + dismisslabel="Dismiss" + primarybuttonlink="" + primarybuttontext="" + secondarybuttonlink="" + secondarybuttontext="" + title="" + variant="danger" + > + + woops + + </gl-alert-stub> + </div> + + <design-presentation-stub + discussions="" + image="test.jpg" + imagename="test.jpg" + scale="1" + /> + + <div + class="design-scaler-wrapper position-absolute mb-4 d-flex-center" + > + <design-scaler-stub /> + </div> + </div> + + <div + class="image-notes" + > + <h2 + class="gl-font-weight-bold gl-mt-0" + > + + My precious issue + + </h2> + + <a + class="gl-text-gray-400 gl-text-decoration-none gl-mb-6 gl-display-block" + href="full-issue-url" + > + ull-issue-path + </a> + + <participants-stub + class="gl-mb-4" + numberoflessparticipants="7" + participants="[object Object]" + /> + + <h2 + class="new-discussion-disclaimer gl-font-base gl-m-0 gl-mb-4" + data-testid="new-discussion-disclaimer" + > + + Click the image where you'd like to start a new discussion + + </h2> + + <!----> + + </div> +</div> +`; diff --git a/spec/frontend/design_management_legacy/pages/design/index_spec.js b/spec/frontend/design_management_legacy/pages/design/index_spec.js new file mode 100644 index 00000000000..5eb4158c715 --- /dev/null +++ b/spec/frontend/design_management_legacy/pages/design/index_spec.js @@ -0,0 +1,291 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import VueRouter from 'vue-router'; +import { GlAlert } from '@gitlab/ui'; +import { ApolloMutation } from 'vue-apollo'; +import { deprecatedCreateFlash as createFlash } from '~/flash'; +import DesignIndex from '~/design_management_legacy/pages/design/index.vue'; +import DesignSidebar from '~/design_management_legacy/components/design_sidebar.vue'; +import DesignPresentation from '~/design_management_legacy/components/design_presentation.vue'; +import createImageDiffNoteMutation from '~/design_management_legacy/graphql/mutations/create_image_diff_note.mutation.graphql'; +import design from '../../mock_data/design'; +import mockResponseWithDesigns from '../../mock_data/designs'; +import mockResponseNoDesigns from '../../mock_data/no_designs'; +import mockAllVersions from '../../mock_data/all_versions'; +import { + DESIGN_NOT_FOUND_ERROR, + DESIGN_VERSION_NOT_EXIST_ERROR, +} from '~/design_management_legacy/utils/error_messages'; +import { DESIGNS_ROUTE_NAME } from '~/design_management_legacy/router/constants'; +import createRouter from '~/design_management_legacy/router'; +import * as utils from '~/design_management_legacy/utils/design_management_utils'; +import { DESIGN_DETAIL_LAYOUT_CLASSLIST } from '~/design_management_legacy/constants'; + +jest.mock('~/flash'); +jest.mock('mousetrap', () => ({ + bind: jest.fn(), + unbind: jest.fn(), +})); + +const focusInput = jest.fn(); + +const DesignReplyForm = { + template: '<div><textarea ref="textarea"></textarea></div>', + methods: { + focusInput, + }, +}; + +const localVue = createLocalVue(); +localVue.use(VueRouter); + +describe('Design management design index page', () => { + let wrapper; + let router; + + const newComment = 'new comment'; + const annotationCoordinates = { + x: 10, + y: 10, + width: 100, + height: 100, + }; + const createDiscussionMutationVariables = { + mutation: createImageDiffNoteMutation, + update: expect.anything(), + variables: { + input: { + body: newComment, + noteableId: design.id, + position: { + headSha: 'headSha', + baseSha: 'baseSha', + startSha: 'startSha', + paths: { + newPath: 'full-design-path', + }, + ...annotationCoordinates, + }, + }, + }, + }; + + const mutate = jest.fn().mockResolvedValue(); + + const findDiscussionForm = () => wrapper.find(DesignReplyForm); + const findSidebar = () => wrapper.find(DesignSidebar); + const findDesignPresentation = () => wrapper.find(DesignPresentation); + + function createComponent(loading = false, data = {}) { + const $apollo = { + queries: { + design: { + loading, + }, + }, + mutate, + }; + + router = createRouter(); + + wrapper = shallowMount(DesignIndex, { + propsData: { id: '1' }, + mocks: { $apollo }, + stubs: { + ApolloMutation, + DesignSidebar, + DesignReplyForm, + }, + data() { + return { + issueIid: '1', + activeDiscussion: { + id: null, + source: null, + }, + ...data, + }; + }, + localVue, + router, + }); + } + + afterEach(() => { + wrapper.destroy(); + }); + + describe('when navigating', () => { + it('applies fullscreen layout', () => { + const mockEl = { + classList: { + add: jest.fn(), + remove: jest.fn(), + }, + }; + jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockEl); + createComponent(true); + + wrapper.vm.$router.push('/designs/test'); + expect(mockEl.classList.add).toHaveBeenCalledTimes(1); + expect(mockEl.classList.add).toHaveBeenCalledWith(...DESIGN_DETAIL_LAYOUT_CLASSLIST); + }); + }); + + it('sets loading state', () => { + createComponent(true); + + expect(wrapper.element).toMatchSnapshot(); + }); + + it('renders design index', () => { + createComponent(false, { design }); + + expect(wrapper.element).toMatchSnapshot(); + expect(wrapper.find(GlAlert).exists()).toBe(false); + }); + + it('passes correct props to sidebar component', () => { + createComponent(false, { design }); + + expect(findSidebar().props()).toEqual({ + design, + markdownPreviewPath: '//preview_markdown?target_type=Issue', + resolvedDiscussionsExpanded: false, + }); + }); + + it('opens a new discussion form', () => { + createComponent(false, { + design: { + ...design, + discussions: { + nodes: [], + }, + }, + }); + + findDesignPresentation().vm.$emit('openCommentForm', { x: 0, y: 0 }); + + return wrapper.vm.$nextTick().then(() => { + expect(findDiscussionForm().exists()).toBe(true); + }); + }); + + it('keeps new discussion form focused', () => { + createComponent(false, { + design: { + ...design, + discussions: { + nodes: [], + }, + }, + annotationCoordinates, + }); + + findDesignPresentation().vm.$emit('openCommentForm', { x: 10, y: 10 }); + + expect(focusInput).toHaveBeenCalled(); + }); + + it('sends a mutation on submitting form and closes form', () => { + createComponent(false, { + design: { + ...design, + discussions: { + nodes: [], + }, + }, + annotationCoordinates, + comment: newComment, + }); + + findDiscussionForm().vm.$emit('submitForm'); + expect(mutate).toHaveBeenCalledWith(createDiscussionMutationVariables); + + return wrapper.vm + .$nextTick() + .then(() => { + return mutate({ variables: createDiscussionMutationVariables }); + }) + .then(() => { + expect(findDiscussionForm().exists()).toBe(false); + }); + }); + + it('closes the form and clears the comment on canceling form', () => { + createComponent(false, { + design: { + ...design, + discussions: { + nodes: [], + }, + }, + annotationCoordinates, + comment: newComment, + }); + + findDiscussionForm().vm.$emit('cancelForm'); + + expect(wrapper.vm.comment).toBe(''); + + return wrapper.vm.$nextTick().then(() => { + expect(findDiscussionForm().exists()).toBe(false); + }); + }); + + describe('with error', () => { + beforeEach(() => { + createComponent(false, { + design: { + ...design, + discussions: { + nodes: [], + }, + }, + errorMessage: 'woops', + }); + }); + + it('GlAlert is rendered in correct position with correct content', () => { + expect(wrapper.element).toMatchSnapshot(); + }); + }); + + describe('onDesignQueryResult', () => { + describe('with no designs', () => { + it('redirects to /designs', () => { + createComponent(true); + router.push = jest.fn(); + + wrapper.vm.onDesignQueryResult({ data: mockResponseNoDesigns, loading: false }); + return wrapper.vm.$nextTick().then(() => { + expect(createFlash).toHaveBeenCalledTimes(1); + expect(createFlash).toHaveBeenCalledWith(DESIGN_NOT_FOUND_ERROR); + expect(router.push).toHaveBeenCalledTimes(1); + expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME }); + }); + }); + }); + + describe('when no design exists for given version', () => { + it('redirects to /designs', () => { + createComponent(true); + wrapper.setData({ + allVersions: mockAllVersions, + }); + + // attempt to query for a version of the design that doesn't exist + router.push({ query: { version: '999' } }); + router.push = jest.fn(); + + wrapper.vm.onDesignQueryResult({ data: mockResponseWithDesigns, loading: false }); + return wrapper.vm.$nextTick().then(() => { + expect(createFlash).toHaveBeenCalledTimes(1); + expect(createFlash).toHaveBeenCalledWith(DESIGN_VERSION_NOT_EXIST_ERROR); + expect(router.push).toHaveBeenCalledTimes(1); + expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME }); + }); + }); + }); + }); +}); |