diff options
Diffstat (limited to 'spec/frontend/design_management/components/design_notes/design_discussion_spec.js')
-rw-r--r-- | spec/frontend/design_management/components/design_notes/design_discussion_spec.js | 241 |
1 files changed, 213 insertions, 28 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 b16b26ff82f..557f53e864f 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 @@ -1,16 +1,33 @@ -import { shallowMount } from '@vue/test-utils'; -import { ApolloMutation } from 'vue-apollo'; +import { mount } from '@vue/test-utils'; +import { GlLoadingIcon } from '@gitlab/ui'; +import notes from '../../mock_data/notes'; import DesignDiscussion from '~/design_management/components/design_notes/design_discussion.vue'; import DesignNote from '~/design_management/components/design_notes/design_note.vue'; import DesignReplyForm from '~/design_management/components/design_notes/design_reply_form.vue'; import createNoteMutation from '~/design_management/graphql/mutations/createNote.mutation.graphql'; +import toggleResolveDiscussionMutation from '~/design_management/graphql/mutations/toggle_resolve_discussion.mutation.graphql'; import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue'; +import ToggleRepliesWidget from '~/design_management/components/design_notes/toggle_replies_widget.vue'; + +const discussion = { + id: '0', + resolved: false, + resolvable: true, + notes, +}; describe('Design discussions component', () => { let wrapper; + const findDesignNotes = () => wrapper.findAll(DesignNote); const findReplyPlaceholder = () => wrapper.find(ReplyPlaceholder); const findReplyForm = () => wrapper.find(DesignReplyForm); + const findRepliesWidget = () => wrapper.find(ToggleRepliesWidget); + const findResolveButton = () => wrapper.find('[data-testid="resolve-button"]'); + const findResolveIcon = () => wrapper.find('[data-testid="resolve-icon"]'); + const findResolvedMessage = () => wrapper.find('[data-testid="resolved-message"]'); + const findResolveLoadingIcon = () => wrapper.find(GlLoadingIcon); + const findResolveCheckbox = () => wrapper.find('[data-testid="resolve-checkbox"]'); const mutationVariables = { mutation: createNoteMutation, @@ -29,22 +46,14 @@ describe('Design discussions component', () => { }; function createComponent(props = {}, data = {}) { - wrapper = shallowMount(DesignDiscussion, { + wrapper = mount(DesignDiscussion, { propsData: { - discussion: { - id: '0', - notes: [ - { - id: '1', - }, - { - id: '2', - }, - ], - }, + resolvedDiscussionsExpanded: true, + discussion, noteableId: 'noteable-id', designId: 'design-id', discussionIndex: 1, + discussionWithOpenForm: '', ...props, }, data() { @@ -52,11 +61,12 @@ describe('Design discussions component', () => { ...data, }; }, - stubs: { - ReplyPlaceholder, - ApolloMutation, + mocks: { + $apollo, + $route: { + hash: '#note_1', + }, }, - mocks: { $apollo }, }); } @@ -64,19 +74,147 @@ describe('Design discussions component', () => { wrapper.destroy(); }); - it('renders correct amount of discussion notes', () => { - createComponent(); - expect(wrapper.findAll(DesignNote)).toHaveLength(2); + describe('when discussion is not resolvable', () => { + beforeEach(() => { + createComponent({ + discussion: { + ...discussion, + resolvable: false, + }, + }); + }); + + it('does not render an icon to resolve a thread', () => { + expect(findResolveIcon().exists()).toBe(false); + }); + + it('does not render a checkbox in reply form', () => { + findReplyPlaceholder().vm.$emit('onMouseDown'); + + return wrapper.vm.$nextTick().then(() => { + expect(findResolveCheckbox().exists()).toBe(false); + }); + }); }); - it('renders reply placeholder by default', () => { - createComponent(); - expect(findReplyPlaceholder().exists()).toBe(true); + describe('when discussion is unresolved', () => { + beforeEach(() => { + createComponent(); + }); + + it('renders correct amount of discussion notes', () => { + expect(findDesignNotes()).toHaveLength(2); + expect(findDesignNotes().wrappers.every(w => w.isVisible())).toBe(true); + }); + + it('renders reply placeholder', () => { + expect(findReplyPlaceholder().isVisible()).toBe(true); + }); + + it('does not render toggle replies widget', () => { + expect(findRepliesWidget().exists()).toBe(false); + }); + + it('renders a correct icon to resolve a thread', () => { + expect(findResolveIcon().props('name')).toBe('check-circle'); + }); + + it('renders a checkbox with Resolve thread text in reply form', () => { + findReplyPlaceholder().vm.$emit('onClick'); + wrapper.setProps({ discussionWithOpenForm: discussion.id }); + + return wrapper.vm.$nextTick().then(() => { + expect(findResolveCheckbox().text()).toBe('Resolve thread'); + }); + }); + + it('does not render resolved message', () => { + expect(findResolvedMessage().exists()).toBe(false); + }); + }); + + describe('when discussion is resolved', () => { + beforeEach(() => { + createComponent({ + discussion: { + ...discussion, + resolved: true, + resolvedBy: notes[0].author, + resolvedAt: '2020-05-08T07:10:45Z', + }, + }); + }); + + it('shows only the first note', () => { + expect( + findDesignNotes() + .at(0) + .isVisible(), + ).toBe(true); + expect( + findDesignNotes() + .at(1) + .isVisible(), + ).toBe(false); + }); + + it('renders resolved message', () => { + expect(findResolvedMessage().exists()).toBe(true); + }); + + it('does not show renders reply placeholder', () => { + expect(findReplyPlaceholder().isVisible()).toBe(false); + }); + + it('renders toggle replies widget with correct props', () => { + expect(findRepliesWidget().exists()).toBe(true); + expect(findRepliesWidget().props()).toEqual({ + collapsed: true, + replies: notes.slice(1), + }); + }); + + it('renders a correct icon to resolve a thread', () => { + expect(findResolveIcon().props('name')).toBe('check-circle-filled'); + }); + + describe('when replies are expanded', () => { + beforeEach(() => { + findRepliesWidget().vm.$emit('toggle'); + return wrapper.vm.$nextTick(); + }); + + it('renders replies widget with collapsed prop equal to false', () => { + expect(findRepliesWidget().props('collapsed')).toBe(false); + }); + + it('renders the second note', () => { + expect( + findDesignNotes() + .at(1) + .isVisible(), + ).toBe(true); + }); + + it('renders a reply placeholder', () => { + expect(findReplyPlaceholder().isVisible()).toBe(true); + }); + + it('renders a checkbox with Unresolve thread text in reply form', () => { + findReplyPlaceholder().vm.$emit('onClick'); + wrapper.setProps({ discussionWithOpenForm: discussion.id }); + + return wrapper.vm.$nextTick().then(() => { + expect(findResolveCheckbox().text()).toBe('Unresolve thread'); + }); + }); + }); }); it('hides reply placeholder and opens form on placeholder click', () => { createComponent(); - findReplyPlaceholder().trigger('click'); + findReplyPlaceholder().vm.$emit('onClick'); + wrapper.setProps({ discussionWithOpenForm: discussion.id }); return wrapper.vm.$nextTick().then(() => { expect(findReplyPlaceholder().exists()).toBe(false); @@ -85,7 +223,10 @@ describe('Design discussions component', () => { }); it('calls mutation on submitting form and closes the form', () => { - createComponent({}, { discussionComment: 'test', isFormRendered: true }); + createComponent( + { discussionWithOpenForm: discussion.id }, + { discussionComment: 'test', isFormRendered: true }, + ); findReplyForm().vm.$emit('submitForm'); expect(mutate).toHaveBeenCalledWith(mutationVariables); @@ -100,7 +241,10 @@ describe('Design discussions component', () => { }); it('clears the discussion comment on closing comment form', () => { - createComponent({}, { discussionComment: 'test', isFormRendered: true }); + createComponent( + { discussionWithOpenForm: discussion.id }, + { discussionComment: 'test', isFormRendered: true }, + ); return wrapper.vm .$nextTick() @@ -120,7 +264,7 @@ describe('Design discussions component', () => { {}, { activeDiscussion: { - id: '1', + id: notes[0].id, source: 'pin', }, }, @@ -130,4 +274,45 @@ describe('Design discussions component', () => { true, ); }); + + it('calls toggleResolveDiscussion mutation on resolve thread button click', () => { + createComponent(); + findResolveButton().trigger('click'); + expect(mutate).toHaveBeenCalledWith({ + mutation: toggleResolveDiscussionMutation, + variables: { + id: discussion.id, + resolve: true, + }, + }); + return wrapper.vm.$nextTick(() => { + expect(findResolveLoadingIcon().exists()).toBe(true); + }); + }); + + it('calls toggleResolveDiscussion mutation after adding a note if checkbox was checked', () => { + createComponent( + { discussionWithOpenForm: discussion.id }, + { discussionComment: 'test', isFormRendered: true }, + ); + findResolveButton().trigger('click'); + findReplyForm().vm.$emit('submitForm'); + + return mutate().then(() => { + expect(mutate).toHaveBeenCalledWith({ + mutation: toggleResolveDiscussionMutation, + variables: { + id: discussion.id, + resolve: true, + }, + }); + }); + }); + + it('emits openForm event on opening the form', () => { + createComponent(); + findReplyPlaceholder().vm.$emit('onClick'); + + expect(wrapper.emitted('openForm')).toBeTruthy(); + }); }); |