Commit 7ae3722b authored by Lukas 'Eipi' Eipert's avatar Lukas 'Eipi' Eipert Committed by Natalia Tepluhina

Migrate all notes specs to jest

We are migrating all specs in javascripts/notes to frontend/notes
parent 9ae6dc68
...@@ -48,7 +48,7 @@ export default { ...@@ -48,7 +48,7 @@ export default {
}, },
}, },
mounted() { mounted() {
if (!this.hasTruncatedDiffLines) { if (this.isTextFile && !this.hasTruncatedDiffLines) {
this.fetchDiff(); this.fetchDiff();
} }
}, },
......
...@@ -3,7 +3,7 @@ import { mount } from '@vue/test-utils'; ...@@ -3,7 +3,7 @@ import { mount } from '@vue/test-utils';
import createStore from '~/notes/stores'; import createStore from '~/notes/stores';
import diffDiscussionHeader from '~/notes/components/diff_discussion_header.vue'; import diffDiscussionHeader from '~/notes/components/diff_discussion_header.vue';
import { discussionMock } from '../../../javascripts/notes/mock_data'; import { discussionMock } from '../mock_data';
import mockDiffFile from '../../diffs/mock_data/diff_discussions'; import mockDiffFile from '../../diffs/mock_data/diff_discussions';
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json'; const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
......
import Vue from 'vue'; import { mount } from '@vue/test-utils';
import { mountComponentWithStore } from 'spec/helpers';
import DiffWithNote from '~/notes/components/diff_with_note.vue'; import DiffWithNote from '~/notes/components/diff_with_note.vue';
import { createStore } from '~/mr_notes/stores'; import { createStore } from '~/mr_notes/stores';
...@@ -8,25 +7,17 @@ const imageDiscussionFixture = 'merge_requests/image_diff_discussion.json'; ...@@ -8,25 +7,17 @@ const imageDiscussionFixture = 'merge_requests/image_diff_discussion.json';
describe('diff_with_note', () => { describe('diff_with_note', () => {
let store; let store;
let vm; let wrapper;
const diffDiscussionMock = getJSONFixture(discussionFixture)[0];
const diffDiscussion = diffDiscussionMock;
const Component = Vue.extend(DiffWithNote);
const props = {
discussion: diffDiscussion,
};
const selectors = { const selectors = {
get container() {
return vm.$el;
},
get diffTable() { get diffTable() {
return this.container.querySelector('.diff-content table'); return wrapper.find('.diff-content table');
}, },
get diffRows() { get diffRows() {
return this.container.querySelectorAll('.diff-content .line_holder'); return wrapper.findAll('.diff-content .line_holder');
}, },
get noteRow() { get noteRow() {
return this.container.querySelector('.diff-content .notes_holder'); return wrapper.find('.diff-content .notes_holder');
}, },
}; };
...@@ -44,25 +35,33 @@ describe('diff_with_note', () => { ...@@ -44,25 +35,33 @@ describe('diff_with_note', () => {
describe('text diff', () => { describe('text diff', () => {
beforeEach(() => { beforeEach(() => {
vm = mountComponentWithStore(Component, { props, store }); const diffDiscussion = getJSONFixture(discussionFixture)[0];
wrapper = mount(DiffWithNote, {
propsData: {
discussion: diffDiscussion,
},
store,
});
}); });
it('removes trailing "+" char', () => { it('removes trailing "+" char', () => {
const richText = vm.$el.querySelectorAll('.line_holder')[4].querySelector('.line_content') const richText = wrapper.vm.$el
.textContent[0]; .querySelectorAll('.line_holder')[4]
.querySelector('.line_content').textContent[0];
expect(richText).not.toEqual('+'); expect(richText).not.toEqual('+');
}); });
it('removes trailing "-" char', () => { it('removes trailing "-" char', () => {
const richText = vm.$el.querySelector('#LC13').parentNode.textContent[0]; const richText = wrapper.vm.$el.querySelector('#LC13').parentNode.textContent[0];
expect(richText).not.toEqual('-'); expect(richText).not.toEqual('-');
}); });
it('shows text diff', () => { it('shows text diff', () => {
expect(selectors.container).toHaveClass('text-file'); expect(wrapper.classes('text-file')).toBe(true);
expect(selectors.diffTable).toExist(); expect(selectors.diffTable.exists()).toBe(true);
}); });
it('shows diff lines', () => { it('shows diff lines', () => {
...@@ -70,20 +69,18 @@ describe('diff_with_note', () => { ...@@ -70,20 +69,18 @@ describe('diff_with_note', () => {
}); });
it('shows notes row', () => { it('shows notes row', () => {
expect(selectors.noteRow).toExist(); expect(selectors.noteRow.exists()).toBe(true);
}); });
}); });
describe('image diff', () => { describe('image diff', () => {
beforeEach(() => { beforeEach(() => {
const imageDiffDiscussionMock = getJSONFixture(imageDiscussionFixture)[0]; const imageDiscussion = getJSONFixture(imageDiscussionFixture)[0];
props.discussion = imageDiffDiscussionMock; wrapper = mount(DiffWithNote, { propsData: { discussion: imageDiscussion }, store });
}); });
it('shows image diff', () => { it('shows image diff', () => {
vm = mountComponentWithStore(Component, { props, store }); expect(selectors.diffTable.exists()).toBe(false);
expect(selectors.diffTable).not.toExist();
}); });
}); });
}); });
import Vue from 'vue'; import Vue from 'vue';
import createStore from '~/notes/stores'; import Vuex from 'vuex';
import { createLocalVue, mount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import notesModule from '~/notes/stores/modules';
import DiscussionFilter from '~/notes/components/discussion_filter.vue'; import DiscussionFilter from '~/notes/components/discussion_filter.vue';
import { DISCUSSION_FILTERS_DEFAULT_VALUE, DISCUSSION_FILTER_TYPES } from '~/notes/constants'; import { DISCUSSION_FILTERS_DEFAULT_VALUE, DISCUSSION_FILTER_TYPES } from '~/notes/constants';
import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper';
import { discussionFiltersMock, discussionMock } from '../mock_data'; import { discussionFiltersMock, discussionMock } from '../mock_data';
import { TEST_HOST } from 'jest/helpers/test_constants';
const localVue = createLocalVue();
localVue.use(Vuex);
const DISCUSSION_PATH = `${TEST_HOST}/example`;
describe('DiscussionFilter component', () => { describe('DiscussionFilter component', () => {
let vm; let wrapper;
let store; let store;
let eventHub; let eventHub;
let mock;
const mountComponent = () => { const filterDiscussion = jest.fn();
store = createStore();
const mountComponent = () => {
const discussions = [ const discussions = [
{ {
...discussionMock, ...discussionMock,
...@@ -20,83 +34,101 @@ describe('DiscussionFilter component', () => { ...@@ -20,83 +34,101 @@ describe('DiscussionFilter component', () => {
notes: [{ ...discussionMock.notes[0], resolvable: true, resolved: true }], notes: [{ ...discussionMock.notes[0], resolvable: true, resolved: true }],
}, },
]; ];
const Component = Vue.extend(DiscussionFilter);
const selectedValue = DISCUSSION_FILTERS_DEFAULT_VALUE; const defaultStore = { ...notesModule() };
const props = { filters: discussionFiltersMock, selectedValue };
store = new Vuex.Store({
...defaultStore,
actions: {
...defaultStore.actions,
filterDiscussion,
},
});
store.state.notesData.discussionsPath = DISCUSSION_PATH;
store.state.discussions = discussions; store.state.discussions = discussions;
return mountComponentWithStore(Component, {
el: null, return mount(DiscussionFilter, {
store, store,
props, propsData: {
filters: discussionFiltersMock,
selectedValue: DISCUSSION_FILTERS_DEFAULT_VALUE,
},
localVue,
}); });
}; };
beforeEach(() => { beforeEach(() => {
mock = new AxiosMockAdapter(axios);
// We are mocking the discussions retrieval,
// as it doesn't matter for our tests here
mock.onGet(DISCUSSION_PATH).reply(200, '');
window.mrTabs = undefined; window.mrTabs = undefined;
vm = mountComponent(); wrapper = mountComponent();
}); });
afterEach(() => { afterEach(() => {
vm.$destroy(); wrapper.vm.$destroy();
mock.restore();
}); });
it('renders the all filters', () => { it('renders the all filters', () => {
expect(vm.$el.querySelectorAll('.dropdown-menu li').length).toEqual( expect(wrapper.findAll('.dropdown-menu li').length).toBe(discussionFiltersMock.length);
discussionFiltersMock.length,
);
}); });
it('renders the default selected item', () => { it('renders the default selected item', () => {
expect(vm.$el.querySelector('#discussion-filter-dropdown').textContent.trim()).toEqual( expect(
discussionFiltersMock[0].title, wrapper
); .find('#discussion-filter-dropdown')
.text()
.trim(),
).toBe(discussionFiltersMock[0].title);
}); });
it('updates to the selected item', () => { it('updates to the selected item', () => {
const filterItem = vm.$el.querySelector( const filterItem = wrapper.find(
`.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.HISTORY}"] button`, `.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.HISTORY}"] button`,
); );
filterItem.click();
expect(vm.currentFilter.title).toEqual(filterItem.textContent.trim()); filterItem.trigger('click');
expect(wrapper.vm.currentFilter.title).toBe(filterItem.text().trim());
}); });
it('only updates when selected filter changes', () => { it('only updates when selected filter changes', () => {
const filterItem = vm.$el.querySelector( wrapper
`.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.ALL}"] button`, .find(`.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.ALL}"] button`)
); .trigger('click');
spyOn(vm, 'filterDiscussion');
filterItem.click();
expect(vm.filterDiscussion).not.toHaveBeenCalled(); expect(filterDiscussion).not.toHaveBeenCalled();
}); });
it('disables commenting when "Show history only" filter is applied', () => { it('disables commenting when "Show history only" filter is applied', () => {
const filterItem = vm.$el.querySelector( const filterItem = wrapper.find(
`.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.HISTORY}"] button`, `.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.HISTORY}"] button`,
); );
filterItem.click(); filterItem.trigger('click');
expect(vm.$store.state.commentsDisabled).toBe(true); expect(wrapper.vm.$store.state.commentsDisabled).toBe(true);
}); });
it('enables commenting when "Show history only" filter is not applied', () => { it('enables commenting when "Show history only" filter is not applied', () => {
const filterItem = vm.$el.querySelector( const filterItem = wrapper.find(
`.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.ALL}"] button`, `.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.ALL}"] button`,
); );
filterItem.click(); filterItem.trigger('click');
expect(vm.$store.state.commentsDisabled).toBe(false); expect(wrapper.vm.$store.state.commentsDisabled).toBe(false);
}); });
it('renders a dropdown divider for the default filter', () => { it('renders a dropdown divider for the default filter', () => {
const defaultFilter = vm.$el.querySelector( const defaultFilter = wrapper.findAll(
`.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.ALL}"]`, `.dropdown-menu li[data-filter-type="${DISCUSSION_FILTER_TYPES.ALL}"] > *`,
); );
expect(defaultFilter.lastChild.classList).toContain('dropdown-divider'); expect(defaultFilter.at(defaultFilter.length - 1).classes('dropdown-divider')).toBe(true);
}); });
describe('Merge request tabs', () => { describe('Merge request tabs', () => {
...@@ -108,7 +140,7 @@ describe('DiscussionFilter component', () => { ...@@ -108,7 +140,7 @@ describe('DiscussionFilter component', () => {
currentTab: 'show', currentTab: 'show',
}; };
vm = mountComponent(); wrapper = mountComponent();
}); });
afterEach(() => { afterEach(() => {
...@@ -118,8 +150,8 @@ describe('DiscussionFilter component', () => { ...@@ -118,8 +150,8 @@ describe('DiscussionFilter component', () => {
it('only renders when discussion tab is active', done => { it('only renders when discussion tab is active', done => {
eventHub.$emit('MergeRequestTabChange', 'commit'); eventHub.$emit('MergeRequestTabChange', 'commit');
vm.$nextTick(() => { wrapper.vm.$nextTick(() => {
expect(vm.$el.querySelector).toBeUndefined(); expect(wrapper.isEmpty()).toBe(true);
done(); done();
}); });
}); });
...@@ -132,54 +164,54 @@ describe('DiscussionFilter component', () => { ...@@ -132,54 +164,54 @@ describe('DiscussionFilter component', () => {
it('updates the filter when the URL links to a note', done => { it('updates the filter when the URL links to a note', done => {
window.location.hash = `note_${discussionMock.notes[0].id}`; window.location.hash = `note_${discussionMock.notes[0].id}`;
vm.currentValue = discussionFiltersMock[2].value; wrapper.vm.currentValue = discussionFiltersMock[2].value;
vm.handleLocationHash(); wrapper.vm.handleLocationHash();
vm.$nextTick(() => { wrapper.vm.$nextTick(() => {
expect(vm.currentValue).toEqual(DISCUSSION_FILTERS_DEFAULT_VALUE); expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE);
done(); done();
}); });
}); });
it('does not update the filter when the current filter is "Show all activity"', done => { it('does not update the filter when the current filter is "Show all activity"', done => {
window.location.hash = `note_${discussionMock.notes[0].id}`; window.location.hash = `note_${discussionMock.notes[0].id}`;
vm.handleLocationHash(); wrapper.vm.handleLocationHash();
vm.$nextTick(() => { wrapper.vm.$nextTick(() => {
expect(vm.currentValue).toEqual(DISCUSSION_FILTERS_DEFAULT_VALUE); expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE);
done(); done();
}); });
}); });
it('only updates filter when the URL links to a note', done => { it('only updates filter when the URL links to a note', done => {
window.location.hash = `testing123`; window.location.hash = `testing123`;
vm.handleLocationHash(); wrapper.vm.handleLocationHash();
vm.$nextTick(() => { wrapper.vm.$nextTick(() => {
expect(vm.currentValue).toEqual(DISCUSSION_FILTERS_DEFAULT_VALUE); expect(wrapper.vm.currentValue).toBe(DISCUSSION_FILTERS_DEFAULT_VALUE);
done(); done();
}); });
}); });
it('fetches discussions when there is a hash', done => { it('fetches discussions when there is a hash', done => {
window.location.hash = `note_${discussionMock.notes[0].id}`; window.location.hash = `note_${discussionMock.notes[0].id}`;
vm.currentValue = discussionFiltersMock[2].value; wrapper.vm.currentValue = discussionFiltersMock[2].value;
spyOn(vm, 'selectFilter'); jest.spyOn(wrapper.vm, 'selectFilter').mockImplementation(() => {});
vm.handleLocationHash(); wrapper.vm.handleLocationHash();
vm.$nextTick(() => { wrapper.vm.$nextTick(() => {
expect(vm.selectFilter).toHaveBeenCalled(); expect(wrapper.vm.selectFilter).toHaveBeenCalled();
done(); done();
}); });
}); });
it('does not fetch discussions when there is no hash', done => { it('does not fetch discussions when there is no hash', done => {
window.location.hash = ''; window.location.hash = '';
spyOn(vm, 'selectFilter'); jest.spyOn(wrapper.vm, 'selectFilter').mockImplementation(() => {});
vm.handleLocationHash(); wrapper.vm.handleLocationHash();
vm.$nextTick(() => { wrapper.vm.$nextTick(() => {
expect(vm.selectFilter).not.toHaveBeenCalled(); expect(wrapper.vm.selectFilter).not.toHaveBeenCalled();
done(); done();
}); });
}); });
......
import Vue from 'vue'; import Vue from 'vue';
import AxiosMockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import createStore from '~/notes/stores'; import createStore from '~/notes/stores';
import awardsNote from '~/notes/components/note_awards_list.vue'; import awardsNote from '~/notes/components/note_awards_list.vue';
import { noteableDataMock, notesDataMock } from '../mock_data'; import { noteableDataMock, notesDataMock } from '../mock_data';
import { TEST_HOST } from 'jest/helpers/test_constants';
describe('note_awards_list component', () => { describe('note_awards_list component', () => {
let store; let store;
let vm; let vm;
let awardsMock; let awardsMock;
let mock;
const toggleAwardPath = `${TEST_HOST}/gitlab-org/gitlab-foss/notes/545/toggle_award_emoji`;
beforeEach(() => { beforeEach(() => {
mock = new AxiosMockAdapter(axios);
mock.onPost(toggleAwardPath).reply(200, '');
const Component = Vue.extend(awardsNote); const Component = Vue.extend(awardsNote);
store = createStore(); store = createStore();
...@@ -32,12 +42,13 @@ describe('note_awards_list component', () => { ...@@ -32,12 +42,13 @@ describe('note_awards_list component', () => {
noteAuthorId: 2, noteAuthorId: 2,
noteId: '545', noteId: '545',
canAwardEmoji: true, canAwardEmoji: true,
toggleAwardPath: '/gitlab-org/gitlab-foss/notes/545/toggle_award_emoji', toggleAwardPath,
}, },
}).$mount(); }).$mount();
}); });
afterEach(() => { afterEach(() => {
mock.restore();
vm.$destroy(); vm.$destroy();
}); });
...@@ -49,8 +60,8 @@ describe('note_awards_list component', () => { ...@@ -49,8 +60,8 @@ describe('note_awards_list component', () => {
}); });
it('should be possible to remove awarded emoji', () => { it('should be possible to remove awarded emoji', () => {
spyOn(vm, 'handleAward').and.callThrough(); jest.spyOn(vm, 'handleAward');
spyOn(vm, 'toggleAwardRequest').and.callThrough(); jest.spyOn(vm, 'toggleAwardRequest');
vm.$el.querySelector('.js-awards-block button').click(); vm.$el.querySelector('.js-awards-block button').click();
expect(vm.handleAward).toHaveBeenCalledWith('flag_tz'); expect(vm.handleAward).toHaveBeenCalledWith('flag_tz');
...@@ -138,7 +149,7 @@ describe('note_awards_list component', () => { ...@@ -138,7 +149,7 @@ describe('note_awards_list component', () => {
}); });
it('should not be possible to remove awarded emoji', () => { it('should not be possible to remove awarded emoji', () => {
spyOn(vm, 'toggleAwardRequest').and.callThrough(); jest.spyOn(vm, 'toggleAwardRequest');
vm.$el.querySelector('.js-awards-block button').click(); vm.$el.querySelector('.js-awards-block button').click();
......
...@@ -4,6 +4,10 @@ import NoteForm from '~/notes/components/note_form.vue'; ...@@ -4,6 +4,10 @@ import NoteForm from '~/notes/components/note_form.vue';
import MarkdownField from '~/vue_shared/components/markdown/field.vue'; import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { noteableDataMock, notesDataMock } from '../mock_data'; import { noteableDataMock, notesDataMock } from '../mock_data';
import { getDraft, updateDraft } from '~/lib/utils/autosave';
jest.mock('~/lib/utils/autosave');
describe('issue_note_form component', () => { describe('issue_note_form component', () => {
const dummyAutosaveKey = 'some-autosave-key'; const dummyAutosaveKey = 'some-autosave-key';
const dummyDraft = 'dummy draft content'; const dummyDraft = 'dummy draft content';
...@@ -23,7 +27,7 @@ describe('issue_note_form component', () => { ...@@ -23,7 +27,7 @@ describe('issue_note_form component', () => {
}; };
beforeEach(() => { beforeEach(() => {
spyOnDependency(NoteForm, 'getDraft').and.callFake(key => { getDraft.mockImplementation(key => {
if (key === dummyAutosaveKey) { if (key === dummyAutosaveKey) {
return dummyDraft; return dummyDraft;
} }
...@@ -55,19 +59,15 @@ describe('issue_note_form component', () => { ...@@ -55,19 +59,15 @@ describe('issue_note_form component', () => {
expect(wrapper.vm.noteHash).toBe(`#note_${props.noteId}`); expect(wrapper.vm.noteHash).toBe(`#note_${props.noteId}`);
}); });
it('return note hash as `#` when `noteId` is empty', done => { it('return note hash as `#` when `noteId` is empty', () => {
wrapper.setProps({ wrapper.setProps({
...props, ...props,
noteId: '', noteId: '',
}); });
wrapper.vm return wrapper.vm.$nextTick().then(() => {
.$nextTick()
.then(() => {
expect(wrapper.vm.noteHash).toBe('#'); expect(wrapper.vm.noteHash).toBe('#');
}) });
.then(done)
.catch(done.fail);
}); });
}); });
...@@ -76,7 +76,7 @@ describe('issue_note_form component', () => { ...@@ -76,7 +76,7 @@ describe('issue_note_form component', () => {
wrapper = createComponentWrapper(); wrapper = createComponentWrapper();
}); });
it('should show conflict message if note changes outside the component', done => { it('should show conflict message if note changes outside the component', () => {
wrapper.setProps({ wrapper.setProps({
...props, ...props,
isEditing: true, isEditing: true,
...@@ -86,9 +86,7 @@ describe('issue_note_form component', () => { ...@@ -86,9 +86,7 @@ describe('issue_note_form component', () => {
const message = const message =
'This comment has changed since you started editing, please review the updated comment to ensure information is not lost.'; 'This comment has changed since you started editing, please review the updated comment to ensure information is not lost.';
wrapper.vm return wrapper.vm.$nextTick().then(() => {
.$nextTick()
.then(() => {
const conflictWarning = wrapper.find('.js-conflict-edit-warning'); const conflictWarning = wrapper.find('.js-conflict-edit-warning');
expect(conflictWarning.exists()).toBe(true); expect(conflictWarning.exists()).toBe(true);
...@@ -98,9 +96,7 @@ describe('issue_note_form component', () => { ...@@ -98,9 +96,7 @@ describe('issue_note_form component', () => {
.replace(/\s+/g, ' ') .replace(/\s+/g, ' ')
.trim(), .trim(),
).toBe(message); ).toBe(message);
}) });
.then(done)
.catch(done.fail);
}); });
}); });
...@@ -136,7 +132,7 @@ describe('issue_note_form component', () => { ...@@ -136,7 +132,7 @@ describe('issue_note_form component', () => {
describe('up', () => { describe('up', () => {
it('should ender edit mode', () => { it('should ender edit mode', () => {
// TODO: do not spy on vm // TODO: do not spy on vm
spyOn(wrapper.vm, 'editMyLastNote').and.callThrough(); jest.spyOn(wrapper.vm, 'editMyLastNote');
textarea.trigger('keydown.up'); textarea.trigger('keydown.up');
...@@ -164,61 +160,50 @@ describe('issue_note_form component', () => { ...@@ -164,61 +160,50 @@ describe('issue_note_form component', () => {
}); });
describe('actions', () => { describe('actions', () => {
it('should be possible to cancel', done => { it('should be possible to cancel', () => {
// TODO: do not spy on vm // TODO: do not spy on vm
spyOn(wrapper.vm, 'cancelHandler').and.callThrough(); jest.spyOn(wrapper.vm, 'cancelHandler');
wrapper.setProps({ wrapper.setProps({
...props, ...props,
isEditing: true, isEditing: true,
}); });
wrapper.vm return wrapper.vm.$nextTick().then(() => {
.$nextTick()
.then(() => {
const cancelButton = wrapper.find('.note-edit-cancel'); const cancelButton = wrapper.find('.note-edit-cancel');
cancelButton.trigger('click'); cancelButton.trigger('click');
expect(wrapper.vm.cancelHandler).toHaveBeenCalled(); expect(wrapper.vm.cancelHandler).toHaveBeenCalled();
}) });
.then(done)
.catch(done.fail);
}); });
it('should be possible to update the note', done => { it('should be possible to update the note', () => {
wrapper.setProps({ wrapper.setProps({
...props, ...props,
isEditing: true, isEditing: true,
}); });
wrapper.vm return wrapper.vm.$nextTick().then(() => {
.$nextTick()
.then(() => {
const textarea = wrapper.find('textarea'); const textarea = wrapper.find('textarea');
textarea.setValue('Foo'); textarea.setValue('Foo');
const saveButton = wrapper.find('.js-vue-issue-save'); const saveButton = wrapper.find('.js-vue-issue-save');
saveButton.trigger('click'); saveButton.trigger('click');
expect(wrapper.vm.isSubmitting).toEqual(true); expect(wrapper.vm.isSubmitting).toBe(true);
}) });
.then(done)
.catch(done.fail);
}); });
}); });
}); });
describe('with autosaveKey', () => { describe('with autosaveKey', () => {
describe('with draft', () => { describe('with draft', () => {
beforeEach(done => { beforeEach(() => {
Object.assign(props, { Object.assign(props, {
noteBody: '', noteBody: '',
autosaveKey: dummyAutosaveKey, autosaveKey: dummyAutosaveKey,
}); });
wrapper = createComponentWrapper(); wrapper = createComponentWrapper();
wrapper.vm return wrapper.vm.$nextTick();
.$nextTick()
.then(done)
.catch(done.fail);
}); });
it('displays the draft in textarea', () => { it('displays the draft in textarea', () => {
...@@ -229,17 +214,14 @@ describe('issue_note_form component', () => { ...@@ -229,17 +214,14 @@ describe('issue_note_form component', () => {
}); });
describe('without draft', () => { describe('without draft', () => {
beforeEach(done => { beforeEach(() => {
Object.assign(props, { Object.assign(props, {
noteBody: '', noteBody: '',
autosaveKey: 'some key without draft', autosaveKey: 'some key without draft',
}); });
wrapper = createComponentWrapper(); wrapper = createComponentWrapper();
wrapper.vm return wrapper.vm.$nextTick();
.$nextTick()
.then(done)
.catch(done.fail);
}); });
it('leaves the textarea empty', () => { it('leaves the textarea empty', () => {
...@@ -250,7 +232,6 @@ describe('issue_note_form component', () => { ...@@ -250,7 +232,6 @@ describe('issue_note_form component', () => {
}); });
it('updates the draft if textarea content changes', () => { it('updates the draft if textarea content changes', () => {
const updateDraftSpy = spyOnDependency(NoteForm, 'updateDraft').and.stub();
Object.assign(props, { Object.assign(props, {
noteBody: '', noteBody: '',
autosaveKey: dummyAutosaveKey, autosaveKey: dummyAutosaveKey,
...@@ -261,7 +242,7 @@ describe('issue_note_form component', () => { ...@@ -261,7 +242,7 @@ describe('issue_note_form component', () => {
textarea.setValue(dummyContent); textarea.setValue(dummyContent);
expect(updateDraftSpy).toHaveBeenCalledWith(dummyAutosaveKey, dummyContent); expect(updateDraft).toHaveBeenCalledWith(dummyAutosaveKey, dummyContent);
}); });
}); });
}); });
...@@ -12,8 +12,8 @@ import { ...@@ -12,8 +12,8 @@ import {
loggedOutnoteableData, loggedOutnoteableData,
userDataMock, userDataMock,
} from '../mock_data'; } from '../mock_data';
import mockDiffFile from '../../diffs/mock_data/diff_file'; import mockDiffFile from 'jest/diffs/mock_data/diff_file';
import { trimText } from '../../helpers/text_helper'; import { trimText } from 'helpers/text_helper';
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json'; const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
...@@ -47,27 +47,24 @@ describe('noteable_discussion component', () => { ...@@ -47,27 +47,24 @@ describe('noteable_discussion component', () => {
expect(wrapper.find('.discussion-header').exists()).toBe(false); expect(wrapper.find('.discussion-header').exists()).toBe(false);
}); });
it('should render thread header', done => { it('should render thread header', () => {
const discussion = { ...discussionMock }; const discussion = { ...discussionMock };
discussion.diff_file = mockDiffFile; discussion.diff_file = mockDiffFile;
discussion.diff_discussion = true; discussion.diff_discussion = true;
discussion.expanded = false;
wrapper.setProps({ discussion }); wrapper.setProps({ discussion });
wrapper.vm return wrapper.vm.$nextTick().then(() => {
.$nextTick()
.then(() => {
expect(wrapper.find('.discussion-header').exists()).toBe(true); expect(wrapper.find('.discussion-header').exists()).toBe(true);
}) });
.then(done)
.catch(done.fail);
}); });
describe('actions', () => { describe('actions', () => {
it('should toggle reply form', done => { it('should toggle reply form', () => {
const replyPlaceholder = wrapper.find(ReplyPlaceholder); const replyPlaceholder = wrapper.find(ReplyPlaceholder);
wrapper.vm return wrapper.vm
.$nextTick() .$nextTick()
.then(() => { .then(() => {
expect(wrapper.vm.isReplying).toEqual(false); expect(wrapper.vm.isReplying).toEqual(false);
...@@ -89,9 +86,7 @@ describe('noteable_discussion component', () => { ...@@ -89,9 +86,7 @@ describe('noteable_discussion component', () => {
expect(noteFormProps.line).toBe(null); expect(noteFormProps.line).toBe(null);
expect(noteFormProps.saveButtonTitle).toBe('Comment'); expect(noteFormProps.saveButtonTitle).toBe('Comment');
expect(noteFormProps.autosaveKey).toBe(`Note/Issue/${discussionMock.id}/Reply`); expect(noteFormProps.autosaveKey).toBe(`Note/Issue/${discussionMock.id}/Reply`);
}) });
.then(done)
.catch(done.fail);
}); });
it('does not render jump to thread button', () => { it('does not render jump to thread button', () => {
...@@ -115,7 +110,7 @@ describe('noteable_discussion component', () => { ...@@ -115,7 +110,7 @@ describe('noteable_discussion component', () => {
}); });
describe('for unresolved thread', () => { describe('for unresolved thread', () => {
beforeEach(done => { beforeEach(() => {
const discussion = { const discussion = {
...getJSONFixture(discussionWithTwoUnresolvedNotes)[0], ...getJSONFixture(discussionWithTwoUnresolvedNotes)[0],
expanded: true, expanded: true,
...@@ -131,10 +126,7 @@ describe('noteable_discussion component', () => { ...@@ -131,10 +126,7 @@ describe('noteable_discussion component', () => {
wrapper.setProps({ discussion }); wrapper.setProps({ discussion });
wrapper.vm return wrapper.vm.$nextTick();
.$nextTick()
.then(done)
.catch(done.fail);
}); });
it('displays a button to resolve with issue', () => { it('displays a button to resolve with issue', () => {
......
...@@ -86,7 +86,7 @@ describe('issue_note', () => { ...@@ -86,7 +86,7 @@ describe('issue_note', () => {
it('prevents note preview xss', done => { it('prevents note preview xss', done => {
const imgSrc = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; const imgSrc = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
const noteBody = `<img src="${imgSrc}" onload="alert(1)" />`; const noteBody = `<img src="${imgSrc}" onload="alert(1)" />`;
const alertSpy = spyOn(window, 'alert'); const alertSpy = jest.spyOn(window, 'alert');
store.hotUpdate({ store.hotUpdate({
actions: { actions: {
updateNote() {}, updateNote() {},
...@@ -96,11 +96,11 @@ describe('issue_note', () => { ...@@ -96,11 +96,11 @@ describe('issue_note', () => {
noteBodyComponent.vm.$emit('handleFormUpdate', noteBody, null, () => {}); noteBodyComponent.vm.$emit('handleFormUpdate', noteBody, null, () => {});
setTimeout(() => { setImmediate(() => {
expect(alertSpy).not.toHaveBeenCalled(); expect(alertSpy).not.toHaveBeenCalled();
expect(wrapper.vm.note.note_html).toEqual(escape(noteBody)); expect(wrapper.vm.note.note_html).toEqual(escape(noteBody));
done(); done();
}, 0); });
}); });
describe('cancel edit', () => { describe('cancel edit', () => {
......
import Vue from 'vue'; import Vue from 'vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'helpers/vue_mount_component_helper';
import toggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue'; import toggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue';
import { note } from '../mock_data'; import { note } from '../mock_data';
...@@ -44,7 +44,7 @@ describe('toggle replies widget for notes', () => { ...@@ -44,7 +44,7 @@ describe('toggle replies widget for notes', () => {
}); });
it('should emit toggle event when the replies text clicked', () => { it('should emit toggle event when the replies text clicked', () => {
const spy = spyOn(vm, '$emit'); const spy = jest.spyOn(vm, '$emit');
vm.$el.querySelector('.js-replies-text').click(); vm.$el.querySelector('.js-replies-text').click();
...@@ -68,7 +68,7 @@ describe('toggle replies widget for notes', () => { ...@@ -68,7 +68,7 @@ describe('toggle replies widget for notes', () => {
}); });
it('should emit toggle event when the collapse replies text called', () => { it('should emit toggle event when the collapse replies text called', () => {
const spy = spyOn(vm, '$emit'); const spy = jest.spyOn(vm, '$emit');
vm.$el.querySelector('.js-collapse-replies').click(); vm.$el.querySelector('.js-collapse-replies').click();
......
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import initMRPage from '~/mr_notes/index'; import initMRPage from '~/mr_notes/index';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { userDataMock, notesDataMock, noteableDataMock } from '../notes/mock_data'; import { userDataMock, notesDataMock, noteableDataMock } from '../../frontend/notes/mock_data';
import diffFileMockData from '../diffs/mock_data/diff_file'; import diffFileMockData from '../diffs/mock_data/diff_file';
export default function initVueMRPage() { export default function initVueMRPage() {
......
export * from '../../frontend/notes/helpers.js';
export * from '../../frontend/notes/mock_data.js';
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment