summaryrefslogtreecommitdiff
path: root/spec/frontend/batch_comments/components
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/batch_comments/components')
-rw-r--r--spec/frontend/batch_comments/components/diff_file_drafts_spec.js61
-rw-r--r--spec/frontend/batch_comments/components/draft_note_spec.js125
-rw-r--r--spec/frontend/batch_comments/components/drafts_count_spec.js43
-rw-r--r--spec/frontend/batch_comments/components/preview_item_spec.js130
-rw-r--r--spec/frontend/batch_comments/components/publish_button_spec.js52
-rw-r--r--spec/frontend/batch_comments/components/publish_dropdown_spec.js96
6 files changed, 507 insertions, 0 deletions
diff --git a/spec/frontend/batch_comments/components/diff_file_drafts_spec.js b/spec/frontend/batch_comments/components/diff_file_drafts_spec.js
new file mode 100644
index 00000000000..6e0b61db9fa
--- /dev/null
+++ b/spec/frontend/batch_comments/components/diff_file_drafts_spec.js
@@ -0,0 +1,61 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import DiffFileDrafts from '~/batch_comments/components/diff_file_drafts.vue';
+import DraftNote from '~/batch_comments/components/draft_note.vue';
+
+const localVue = createLocalVue();
+
+localVue.use(Vuex);
+
+describe('Batch comments diff file drafts component', () => {
+ let vm;
+
+ function factory() {
+ const store = new Vuex.Store({
+ modules: {
+ batchComments: {
+ namespaced: true,
+ getters: {
+ draftsForFile: () => () => [{ id: 1 }, { id: 2 }],
+ },
+ },
+ },
+ });
+
+ vm = shallowMount(localVue.extend(DiffFileDrafts), {
+ store,
+ localVue,
+ propsData: { fileHash: 'filehash' },
+ });
+ }
+
+ afterEach(() => {
+ vm.destroy();
+ });
+
+ it('renders list of draft notes', () => {
+ factory();
+
+ expect(vm.findAll(DraftNote).length).toEqual(2);
+ });
+
+ it('renders index of draft note', () => {
+ factory();
+
+ expect(vm.findAll('.js-diff-notes-index').length).toEqual(2);
+
+ expect(
+ vm
+ .findAll('.js-diff-notes-index')
+ .at(0)
+ .text(),
+ ).toEqual('1');
+
+ expect(
+ vm
+ .findAll('.js-diff-notes-index')
+ .at(1)
+ .text(),
+ ).toEqual('2');
+ });
+});
diff --git a/spec/frontend/batch_comments/components/draft_note_spec.js b/spec/frontend/batch_comments/components/draft_note_spec.js
new file mode 100644
index 00000000000..eea7f25dbc1
--- /dev/null
+++ b/spec/frontend/batch_comments/components/draft_note_spec.js
@@ -0,0 +1,125 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import DraftNote from '~/batch_comments/components/draft_note.vue';
+import { createStore } from '~/batch_comments/stores';
+import NoteableNote from '~/notes/components/noteable_note.vue';
+import '~/behaviors/markdown/render_gfm';
+import { createDraft } from '../mock_data';
+
+const localVue = createLocalVue();
+
+describe('Batch comments draft note component', () => {
+ let wrapper;
+ let draft;
+
+ beforeEach(() => {
+ const store = createStore();
+
+ draft = createDraft();
+
+ wrapper = shallowMount(localVue.extend(DraftNote), {
+ store,
+ propsData: { draft },
+ localVue,
+ });
+
+ jest.spyOn(wrapper.vm.$store, 'dispatch').mockImplementation();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders template', () => {
+ expect(wrapper.find('.draft-pending-label').exists()).toBe(true);
+
+ const note = wrapper.find(NoteableNote);
+
+ expect(note.exists()).toBe(true);
+ expect(note.props().note).toEqual(draft);
+ });
+
+ describe('add comment now', () => {
+ it('dispatches publishSingleDraft when clicking', () => {
+ const publishNowButton = wrapper.find({ ref: 'publishNowButton' });
+ publishNowButton.vm.$emit('click');
+
+ expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith(
+ 'batchComments/publishSingleDraft',
+ 1,
+ );
+ });
+
+ it('sets as loading when draft is publishing', done => {
+ wrapper.vm.$store.state.batchComments.currentlyPublishingDrafts.push(1);
+
+ wrapper.vm.$nextTick(() => {
+ const publishNowButton = wrapper.find({ ref: 'publishNowButton' });
+
+ expect(publishNowButton.props().loading).toBe(true);
+
+ done();
+ });
+ });
+ });
+
+ describe('update', () => {
+ it('dispatches updateDraft', done => {
+ const note = wrapper.find(NoteableNote);
+
+ note.vm.$emit('handleEdit');
+
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ const formData = {
+ note: draft,
+ noteText: 'a',
+ resolveDiscussion: false,
+ };
+
+ note.vm.$emit('handleUpdateNote', formData);
+
+ expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith(
+ 'batchComments/updateDraft',
+ formData,
+ );
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('deleteDraft', () => {
+ it('dispatches deleteDraft', () => {
+ jest.spyOn(window, 'confirm').mockImplementation(() => true);
+
+ const note = wrapper.find(NoteableNote);
+
+ note.vm.$emit('handleDeleteNote', draft);
+
+ expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith('batchComments/deleteDraft', draft);
+ });
+ });
+
+ describe('quick actions', () => {
+ it('renders referenced commands', done => {
+ wrapper.setProps({
+ draft: {
+ ...draft,
+ references: {
+ commands: 'test command',
+ },
+ },
+ });
+
+ wrapper.vm.$nextTick(() => {
+ const referencedCommands = wrapper.find('.referenced-commands');
+
+ expect(referencedCommands.exists()).toBe(true);
+ expect(referencedCommands.text()).toContain('test command');
+
+ done();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/batch_comments/components/drafts_count_spec.js b/spec/frontend/batch_comments/components/drafts_count_spec.js
new file mode 100644
index 00000000000..9d9fffce7e7
--- /dev/null
+++ b/spec/frontend/batch_comments/components/drafts_count_spec.js
@@ -0,0 +1,43 @@
+import Vue from 'vue';
+import DraftsCount from '~/batch_comments/components/drafts_count.vue';
+import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { createStore } from '~/batch_comments/stores';
+
+describe('Batch comments drafts count component', () => {
+ let vm;
+ let Component;
+
+ beforeAll(() => {
+ Component = Vue.extend(DraftsCount);
+ });
+
+ beforeEach(() => {
+ const store = createStore();
+
+ store.state.batchComments.drafts.push('comment');
+
+ vm = mountComponentWithStore(Component, { store });
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders count', () => {
+ expect(vm.$el.querySelector('.drafts-count-number').textContent).toBe('1');
+ });
+
+ it('renders screen reader text', done => {
+ const el = vm.$el.querySelector('.sr-only');
+
+ expect(el.textContent).toContain('draft');
+
+ vm.$store.state.batchComments.drafts.push('comment 2');
+
+ vm.$nextTick(() => {
+ expect(el.textContent).toContain('drafts');
+
+ done();
+ });
+ });
+});
diff --git a/spec/frontend/batch_comments/components/preview_item_spec.js b/spec/frontend/batch_comments/components/preview_item_spec.js
new file mode 100644
index 00000000000..7d951fd7799
--- /dev/null
+++ b/spec/frontend/batch_comments/components/preview_item_spec.js
@@ -0,0 +1,130 @@
+import Vue from 'vue';
+import PreviewItem from '~/batch_comments/components/preview_item.vue';
+import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { createStore } from '~/batch_comments/stores';
+import diffsModule from '~/diffs/store/modules';
+import notesModule from '~/notes/stores/modules';
+import '~/behaviors/markdown/render_gfm';
+import { createDraft } from '../mock_data';
+
+describe('Batch comments draft preview item component', () => {
+ let vm;
+ let Component;
+ let draft;
+
+ function createComponent(isLast = false, extra = {}, extendStore = () => {}) {
+ const store = createStore();
+ store.registerModule('diffs', diffsModule());
+ store.registerModule('notes', notesModule());
+
+ extendStore(store);
+
+ draft = {
+ ...createDraft(),
+ ...extra,
+ };
+
+ vm = mountComponentWithStore(Component, { store, props: { draft, isLast } });
+ }
+
+ beforeAll(() => {
+ Component = Vue.extend(PreviewItem);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders text content', () => {
+ createComponent(false, { note_html: '<img src="" /><p>Hello world</p>' });
+
+ expect(vm.$el.querySelector('.review-preview-item-content').innerHTML).toEqual(
+ '<p>Hello world</p>',
+ );
+ });
+
+ it('adds is last class', () => {
+ createComponent(true);
+
+ expect(vm.$el.classList).toContain('is-last');
+ });
+
+ it('scrolls to draft on click', () => {
+ createComponent();
+
+ jest.spyOn(vm.$store, 'dispatch').mockImplementation();
+
+ vm.$el.click();
+
+ expect(vm.$store.dispatch).toHaveBeenCalledWith('batchComments/scrollToDraft', vm.draft);
+ });
+
+ describe('for file', () => {
+ it('renders file path', () => {
+ createComponent(false, { file_path: 'index.js', file_hash: 'abc', position: {} });
+
+ expect(vm.$el.querySelector('.review-preview-item-header-text').textContent).toContain(
+ 'index.js',
+ );
+ });
+
+ it('renders new line position', () => {
+ createComponent(false, {
+ file_path: 'index.js',
+ file_hash: 'abc',
+ position: { new_line: 1 },
+ });
+
+ expect(vm.$el.querySelector('.bold').textContent).toContain(':1');
+ });
+
+ it('renders old line position', () => {
+ createComponent(false, {
+ file_path: 'index.js',
+ file_hash: 'abc',
+ position: { old_line: 2 },
+ });
+
+ expect(vm.$el.querySelector('.bold').textContent).toContain(':2');
+ });
+
+ it('renders image position', () => {
+ createComponent(false, {
+ file_path: 'index.js',
+ file_hash: 'abc',
+ position: { position_type: 'image', x: 10, y: 20 },
+ });
+
+ expect(vm.$el.querySelector('.bold').textContent).toContain('10x 20y');
+ });
+ });
+
+ describe('for thread', () => {
+ beforeEach(() => {
+ createComponent(false, { discussion_id: '1', resolve_discussion: true }, store => {
+ store.state.notes.discussions.push({
+ id: '1',
+ notes: [
+ {
+ author: {
+ name: 'Author Name',
+ },
+ },
+ ],
+ });
+ });
+ });
+
+ it('renders title', () => {
+ expect(vm.$el.querySelector('.review-preview-item-header-text').textContent).toContain(
+ "Author Name's thread",
+ );
+ });
+
+ it('it renders thread resolved text', () => {
+ expect(vm.$el.querySelector('.draft-note-resolution').textContent).toContain(
+ 'Thread will be resolved',
+ );
+ });
+ });
+});
diff --git a/spec/frontend/batch_comments/components/publish_button_spec.js b/spec/frontend/batch_comments/components/publish_button_spec.js
new file mode 100644
index 00000000000..97f3a1c8939
--- /dev/null
+++ b/spec/frontend/batch_comments/components/publish_button_spec.js
@@ -0,0 +1,52 @@
+import Vue from 'vue';
+import PublishButton from '~/batch_comments/components/publish_button.vue';
+import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { createStore } from '~/batch_comments/stores';
+
+describe('Batch comments publish button component', () => {
+ let vm;
+ let Component;
+
+ beforeAll(() => {
+ Component = Vue.extend(PublishButton);
+ });
+
+ beforeEach(() => {
+ const store = createStore();
+
+ vm = mountComponentWithStore(Component, { store, props: { shouldPublish: true } });
+
+ jest.spyOn(vm.$store, 'dispatch').mockImplementation();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('dispatches publishReview on click', () => {
+ vm.$el.click();
+
+ expect(vm.$store.dispatch).toHaveBeenCalledWith('batchComments/publishReview', undefined);
+ });
+
+ it('dispatches toggleReviewDropdown when shouldPublish is false on click', () => {
+ vm.shouldPublish = false;
+
+ vm.$el.click();
+
+ expect(vm.$store.dispatch).toHaveBeenCalledWith(
+ 'batchComments/toggleReviewDropdown',
+ undefined,
+ );
+ });
+
+ it('sets loading when isPublishing is true', done => {
+ vm.$store.state.batchComments.isPublishing = true;
+
+ vm.$nextTick(() => {
+ expect(vm.$el.getAttribute('disabled')).toBe('disabled');
+
+ done();
+ });
+ });
+});
diff --git a/spec/frontend/batch_comments/components/publish_dropdown_spec.js b/spec/frontend/batch_comments/components/publish_dropdown_spec.js
new file mode 100644
index 00000000000..b50ae340691
--- /dev/null
+++ b/spec/frontend/batch_comments/components/publish_dropdown_spec.js
@@ -0,0 +1,96 @@
+import Vue from 'vue';
+import PreviewDropdown from '~/batch_comments/components/preview_dropdown.vue';
+import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { createStore } from '~/mr_notes/stores';
+import '~/behaviors/markdown/render_gfm';
+import { createDraft } from '../mock_data';
+
+describe('Batch comments publish dropdown component', () => {
+ let vm;
+ let Component;
+
+ function createComponent(extendStore = () => {}) {
+ const store = createStore();
+ store.state.batchComments.drafts.push(createDraft(), { ...createDraft(), id: 2 });
+
+ extendStore(store);
+
+ vm = mountComponentWithStore(Component, { store });
+ }
+
+ beforeAll(() => {
+ Component = Vue.extend(PreviewDropdown);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('toggles dropdown when clicking button', done => {
+ createComponent();
+
+ jest.spyOn(vm.$store, 'dispatch');
+
+ vm.$el.querySelector('.review-preview-dropdown-toggle').click();
+
+ expect(vm.$store.dispatch).toHaveBeenCalledWith(
+ 'batchComments/toggleReviewDropdown',
+ expect.anything(),
+ );
+
+ setImmediate(() => {
+ expect(vm.$el.classList).toContain('show');
+
+ done();
+ });
+ });
+
+ it('toggles dropdown when clicking body', () => {
+ createComponent();
+
+ vm.$store.state.batchComments.showPreviewDropdown = true;
+
+ jest.spyOn(vm.$store, 'dispatch').mockImplementation();
+
+ document.body.click();
+
+ expect(vm.$store.dispatch).toHaveBeenCalledWith(
+ 'batchComments/toggleReviewDropdown',
+ undefined,
+ );
+ });
+
+ it('renders list of drafts', () => {
+ createComponent(store => {
+ Object.assign(store.state.notes, {
+ isNotesFetched: true,
+ });
+ });
+
+ expect(vm.$el.querySelectorAll('.dropdown-content li').length).toBe(2);
+ });
+
+ it('adds is-last class to last item', () => {
+ createComponent(store => {
+ Object.assign(store.state.notes, {
+ isNotesFetched: true,
+ });
+ });
+
+ expect(vm.$el.querySelectorAll('.dropdown-content li')[1].querySelector('.is-last')).not.toBe(
+ null,
+ );
+ });
+
+ it('renders draft count in dropdown title', () => {
+ createComponent();
+
+ expect(vm.$el.querySelector('.dropdown-title').textContent).toContain('2 pending comments');
+ });
+
+ it('renders publish button in footer', () => {
+ createComponent();
+
+ expect(vm.$el.querySelector('.dropdown-footer .js-publish-draft-button')).not.toBe(null);
+ });
+});