Commit d7388857 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'leipert-jestodus-take-23' into 'master'

Migrate frontend note specs from karma to jest

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