diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 14:34:42 +0000 |
commit | 9f46488805e86b1bc341ea1620b866016c2ce5ed (patch) | |
tree | f9748c7e287041e37d6da49e0a29c9511dc34768 /spec/frontend/design_management/pages/design | |
parent | dfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff) | |
download | gitlab-ce-9f46488805e86b1bc341ea1620b866016c2ce5ed.tar.gz |
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'spec/frontend/design_management/pages/design')
-rw-r--r-- | spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap | 184 | ||||
-rw-r--r-- | spec/frontend/design_management/pages/design/index_spec.js | 301 |
2 files changed, 485 insertions, 0 deletions
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 new file mode 100644 index 00000000000..76e481ee518 --- /dev/null +++ b/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap @@ -0,0 +1,184 @@ +// 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]" + 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-size-20-deprecated-no-really-do-not-use-me font-weight-bold mt-0" + > + + My precious issue + + </h2> + + <a + class="text-tertiary text-decoration-none mb-3 d-block" + href="full-issue-url" + > + ull-issue-path + </a> + + <participants-stub + class="mb-4" + numberoflessparticipants="7" + participants="[object Object]" + /> + + <div + class="design-discussion-wrapper" + > + <div + class="badge badge-pill" + type="button" + > + 1 + </div> + + <div + class="design-discussion bordered-box position-relative" + data-qa-selector="design_discussion_content" + > + <design-note-stub + class="" + markdownpreviewpath="//preview_markdown?target_type=Issue" + note="[object Object]" + /> + + <div + class="reply-wrapper" + > + <reply-placeholder-stub + buttontext="Reply..." + class="qa-discussion-reply" + /> + </div> + </div> + </div> + + <!----> + </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-size-20-deprecated-no-really-do-not-use-me font-weight-bold mt-0" + > + + My precious issue + + </h2> + + <a + class="text-tertiary text-decoration-none mb-3 d-block" + href="full-issue-url" + > + ull-issue-path + </a> + + <participants-stub + class="mb-4" + numberoflessparticipants="7" + participants="[object Object]" + /> + + <h2 + class="new-discussion-disclaimer gl-font-base m-0" + > + + Click the image where you'd like to start a new discussion + + </h2> + </div> +</div> +`; diff --git a/spec/frontend/design_management/pages/design/index_spec.js b/spec/frontend/design_management/pages/design/index_spec.js new file mode 100644 index 00000000000..9e2f071a983 --- /dev/null +++ b/spec/frontend/design_management/pages/design/index_spec.js @@ -0,0 +1,301 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlAlert } from '@gitlab/ui'; +import { ApolloMutation } from 'vue-apollo'; +import createFlash from '~/flash'; +import DesignIndex from '~/design_management/pages/design/index.vue'; +import DesignDiscussion from '~/design_management/components/design_notes/design_discussion.vue'; +import DesignReplyForm from '~/design_management/components/design_notes/design_reply_form.vue'; +import Participants from '~/sidebar/components/participants/participants.vue'; +import createImageDiffNoteMutation from '~/design_management/graphql/mutations/createImageDiffNote.mutation.graphql'; +import updateActiveDiscussionMutation from '~/design_management/graphql/mutations/update_active_discussion.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/utils/error_messages'; +import { DESIGNS_ROUTE_NAME } from '~/design_management/router/constants'; + +jest.mock('~/flash'); +jest.mock('mousetrap', () => ({ + bind: jest.fn(), + unbind: jest.fn(), +})); + +describe('Design management design index page', () => { + let wrapper; + 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 updateActiveDiscussionMutationVariables = { + mutation: updateActiveDiscussionMutation, + variables: { + id: design.discussions.nodes[0].notes.nodes[0].id, + source: 'discussion', + }, + }; + + const mutate = jest.fn().mockResolvedValue(); + const routerPush = jest.fn(); + + const findDiscussions = () => wrapper.findAll(DesignDiscussion); + const findDiscussionForm = () => wrapper.find(DesignReplyForm); + const findParticipants = () => wrapper.find(Participants); + const findDiscussionsWrapper = () => wrapper.find('.image-notes'); + + function createComponent(loading = false, data = {}, { routeQuery = {} } = {}) { + const $apollo = { + queries: { + design: { + loading, + }, + }, + mutate, + }; + + const $router = { + push: routerPush, + }; + + const $route = { + query: routeQuery, + }; + + wrapper = shallowMount(DesignIndex, { + propsData: { id: '1' }, + mocks: { $apollo, $router, $route }, + stubs: { + ApolloMutation, + DesignDiscussion, + }, + data() { + return { + issueIid: '1', + activeDiscussion: { + id: null, + source: null, + }, + ...data, + }; + }, + }); + } + + afterEach(() => { + wrapper.destroy(); + }); + + 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('renders participants', () => { + createComponent(false, { design }); + + expect(findParticipants().exists()).toBe(true); + }); + + it('passes the correct amount of participants to the Participants component', () => { + createComponent(false, { design }); + + expect(findParticipants().props('participants')).toHaveLength(1); + }); + + describe('when has no discussions', () => { + beforeEach(() => { + createComponent(false, { + design: { + ...design, + discussions: { + nodes: [], + }, + }, + }); + }); + + it('does not render discussions', () => { + expect(findDiscussions().exists()).toBe(false); + }); + + it('renders a message about possibility to create a new discussion', () => { + expect(wrapper.find('.new-discussion-disclaimer').exists()).toBe(true); + }); + }); + + describe('when has discussions', () => { + beforeEach(() => { + createComponent(false, { design }); + }); + + it('renders correct amount of discussions', () => { + expect(findDiscussions()).toHaveLength(1); + }); + + it('sends a mutation to set an active discussion when clicking on a discussion', () => { + findDiscussions() + .at(0) + .trigger('click'); + + expect(mutate).toHaveBeenCalledWith(updateActiveDiscussionMutationVariables); + }); + + it('sends a mutation to reset an active discussion when clicking outside of discussion', () => { + findDiscussionsWrapper().trigger('click'); + + expect(mutate).toHaveBeenCalledWith({ + ...updateActiveDiscussionMutationVariables, + variables: { id: undefined, source: 'discussion' }, + }); + }); + }); + + it('opens a new discussion form', () => { + createComponent(false, { + design: { + ...design, + discussions: { + nodes: [], + }, + }, + }); + + wrapper.vm.openCommentForm({ x: 0, y: 0 }); + + return wrapper.vm.$nextTick().then(() => { + expect(findDiscussionForm().exists()).toBe(true); + }); + }); + + 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); + + wrapper.vm.onDesignQueryResult({ data: mockResponseNoDesigns, loading: false }); + return wrapper.vm.$nextTick().then(() => { + expect(createFlash).toHaveBeenCalledTimes(1); + expect(createFlash).toHaveBeenCalledWith(DESIGN_NOT_FOUND_ERROR); + expect(routerPush).toHaveBeenCalledTimes(1); + expect(routerPush).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME }); + }); + }); + }); + + describe('when no design exists for given version', () => { + it('redirects to /designs', () => { + // attempt to query for a version of the design that doesn't exist + createComponent(true, {}, { routeQuery: { version: '999' } }); + wrapper.setData({ + allVersions: mockAllVersions, + }); + + 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(routerPush).toHaveBeenCalledTimes(1); + expect(routerPush).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME }); + }); + }); + }); + }); +}); |