noteable_discussion_spec.js 5 KB
Newer Older
1
import { mount, createLocalVue } from '@vue/test-utils';
Felipe Artur's avatar
Felipe Artur committed
2 3
import createStore from '~/notes/stores';
import noteableDiscussion from '~/notes/components/noteable_discussion.vue';
4
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
5
import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
6
import NoteForm from '~/notes/components/note_form.vue';
Felipe Artur's avatar
Felipe Artur committed
7
import '~/behaviors/markdown/render_gfm';
Simon Knox's avatar
Simon Knox committed
8
import { noteableDataMock, discussionMock, notesDataMock } from '../mock_data';
Fatih Acet's avatar
Fatih Acet committed
9
import mockDiffFile from '../../diffs/mock_data/diff_file';
Filipa Lacerda's avatar
Filipa Lacerda committed
10

11 12
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';

13 14
const localVue = createLocalVue();

Felipe Artur's avatar
Felipe Artur committed
15 16
describe('noteable_discussion component', () => {
  let store;
17
  let wrapper;
18

19
  preloadFixtures(discussionWithTwoUnresolvedNotes);
20

21
  beforeEach(() => {
22
    window.mrTabs = {};
Felipe Artur's avatar
Felipe Artur committed
23
    store = createStore();
Simon Knox's avatar
Simon Knox committed
24
    store.dispatch('setNoteableData', noteableDataMock);
25
    store.dispatch('setNotesData', notesDataMock);
26

27
    wrapper = mount(localVue.extend(noteableDiscussion), {
28
      store,
29
      propsData: { discussion: discussionMock },
30 31 32
      localVue,
      sync: false,
    });
33 34
  });

35
  afterEach(() => {
36
    wrapper.destroy();
37
  });
38

39
  it('should not render thread header for non diff threads', () => {
40
    expect(wrapper.find('.discussion-header').exists()).toBe(false);
Fatih Acet's avatar
Fatih Acet committed
41 42
  });

43
  it('should render thread header', done => {
Fatih Acet's avatar
Fatih Acet committed
44 45 46
    const discussion = { ...discussionMock };
    discussion.diff_file = mockDiffFile;
    discussion.diff_discussion = true;
47

48
    wrapper.setProps({ discussion });
Fatih Acet's avatar
Fatih Acet committed
49

50 51 52 53 54 55 56
    wrapper.vm
      .$nextTick()
      .then(() => {
        expect(wrapper.find('.discussion-header').exists()).toBe(true);
      })
      .then(done)
      .catch(done.fail);
57
  });
58

59
  describe('actions', () => {
60
    it('should toggle reply form', done => {
61 62 63 64 65 66 67 68 69 70 71 72
      const replyPlaceholder = wrapper.find(ReplyPlaceholder);

      wrapper.vm
        .$nextTick()
        .then(() => {
          expect(wrapper.vm.isReplying).toEqual(false);

          replyPlaceholder.vm.$emit('onClick');
        })
        .then(() => wrapper.vm.$nextTick())
        .then(() => {
          expect(wrapper.vm.isReplying).toEqual(true);
73 74 75 76 77 78 79 80 81 82 83

          const noteForm = wrapper.find(NoteForm);

          expect(noteForm.exists()).toBe(true);

          const noteFormProps = noteForm.props();

          expect(noteFormProps.discussion).toBe(discussionMock);
          expect(noteFormProps.isEditing).toBe(false);
          expect(noteFormProps.line).toBe(null);
          expect(noteFormProps.saveButtonTitle).toBe('Comment');
84
          expect(noteFormProps.autosaveKey).toBe(`Note/Issue/${discussionMock.id}/Reply`);
85 86 87
        })
        .then(done)
        .catch(done.fail);
88
    });
89

90
    it('does not render jump to thread button', () => {
91 92 93
      expect(wrapper.find('*[data-original-title="Jump to next unresolved thread"]').exists()).toBe(
        false,
      );
94
    });
95
  });
Felipe Artur's avatar
Felipe Artur committed
96 97 98

  describe('methods', () => {
    describe('jumpToNextDiscussion', () => {
99
      it('expands next unresolved thread', done => {
100 101
        const discussion2 = getJSONFixture(discussionWithTwoUnresolvedNotes)[0];
        discussion2.resolved = false;
102
        discussion2.active = true;
103
        discussion2.id = 'next'; // prepare this for being identified as next one (to be jumped to)
104
        store.dispatch('setInitialNotes', [discussionMock, discussion2]);
105 106
        window.mrTabs.currentAction = 'show';

107 108
        wrapper.vm
          .$nextTick()
109
          .then(() => {
110
            spyOn(wrapper.vm, 'expandDiscussion').and.stub();
111 112

            const nextDiscussionId = discussion2.id;
Felipe Artur's avatar
Felipe Artur committed
113

114
            setFixtures(`<div class="discussion" data-discussion-id="${nextDiscussionId}"></div>`);
115

116
            wrapper.vm.jumpToNextDiscussion();
117

118 119 120
            expect(wrapper.vm.expandDiscussion).toHaveBeenCalledWith({
              discussionId: nextDiscussionId,
            });
121 122 123
          })
          .then(done)
          .catch(done.fail);
Felipe Artur's avatar
Felipe Artur committed
124 125 126
      });
    });
  });
127

128
  describe('for resolved thread', () => {
129 130 131 132 133 134 135 136 137 138 139 140
    beforeEach(() => {
      const discussion = getJSONFixture(discussionWithTwoUnresolvedNotes)[0];
      wrapper.setProps({ discussion });
    });

    it('does not display a button to resolve with issue', () => {
      const button = wrapper.find(ResolveWithIssueButton);

      expect(button.exists()).toBe(false);
    });
  });

141
  describe('for unresolved thread', () => {
142 143 144 145 146 147 148 149
    beforeEach(done => {
      const discussion = {
        ...getJSONFixture(discussionWithTwoUnresolvedNotes)[0],
        expanded: true,
      };
      discussion.notes = discussion.notes.map(note => ({
        ...note,
        resolved: false,
150 151 152 153
        current_user: {
          ...note.current_user,
          can_resolve: true,
        },
154 155 156
      }));

      wrapper.setProps({ discussion });
157

158 159 160 161 162 163 164 165 166 167 168 169
      wrapper.vm
        .$nextTick()
        .then(done)
        .catch(done.fail);
    });

    it('displays a button to resolve with issue', () => {
      const button = wrapper.find(ResolveWithIssueButton);

      expect(button.exists()).toBe(true);
    });
  });
170
});