Commit 910c7f5f authored by Winnie Hellmann's avatar Winnie Hellmann

Refactor note_form_spec.js to use Vue test utils

parent 13c723f1
import Vue from 'vue'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import createStore from '~/notes/stores'; import createStore from '~/notes/stores';
import issueNoteForm from '~/notes/components/note_form.vue'; import NoteForm from '~/notes/components/note_form.vue';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { noteableDataMock, notesDataMock } from '../mock_data'; import { noteableDataMock, notesDataMock } from '../mock_data';
import { keyboardDownEvent } from '../../issue_show/helpers';
describe('issue_note_form component', () => { describe('issue_note_form component', () => {
let store; let store;
let vm; let wrapper;
let props; let props;
beforeEach(() => { beforeEach(() => {
const Component = Vue.extend(issueNoteForm);
store = createStore(); store = createStore();
store.dispatch('setNoteableData', noteableDataMock); store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock); store.dispatch('setNotesData', notesDataMock);
...@@ -22,26 +20,35 @@ describe('issue_note_form component', () => { ...@@ -22,26 +20,35 @@ describe('issue_note_form component', () => {
noteId: '545', noteId: '545',
}; };
vm = new Component({ const localVue = createLocalVue();
wrapper = shallowMount(NoteForm, {
store, store,
propsData: props, propsData: props,
}).$mount(); // see https://gitlab.com/gitlab-org/gitlab-ce/issues/56317 for the following
localVue,
sync: false,
});
}); });
afterEach(() => { afterEach(() => {
vm.$destroy(); wrapper.destroy();
}); });
describe('noteHash', () => { describe('noteHash', () => {
it('returns note hash string based on `noteId`', () => { it('returns note hash string based on `noteId`', () => {
expect(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', done => {
vm.noteId = ''; wrapper.setProps({
Vue.nextTick() ...props,
noteId: '',
});
wrapper.vm
.$nextTick()
.then(() => { .then(() => {
expect(vm.noteHash).toBe('#'); expect(wrapper.vm.noteHash).toBe('#');
}) })
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
...@@ -50,95 +57,127 @@ describe('issue_note_form component', () => { ...@@ -50,95 +57,127 @@ describe('issue_note_form component', () => {
describe('conflicts editing', () => { describe('conflicts editing', () => {
it('should show conflict message if note changes outside the component', done => { it('should show conflict message if note changes outside the component', done => {
vm.isEditing = true; wrapper.setProps({
vm.noteBody = 'Foo'; ...props,
isEditing: true,
noteBody: 'Foo',
});
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.';
Vue.nextTick(() => { wrapper.vm
.$nextTick()
.then(() => {
const conflictWarning = wrapper.find('.js-conflict-edit-warning');
expect(conflictWarning.exists()).toBe(true);
expect( expect(
vm.$el conflictWarning
.querySelector('.js-conflict-edit-warning') .text()
.textContent.replace(/\s+/g, ' ') .replace(/\s+/g, ' ')
.trim(), .trim(),
).toEqual(message); ).toBe(message);
done(); })
}); .then(done)
.catch(done.fail);
}); });
}); });
describe('form', () => { describe('form', () => {
it('should render text area with placeholder', () => { it('should render text area with placeholder', () => {
expect(vm.$el.querySelector('textarea').getAttribute('placeholder')).toEqual( const textarea = wrapper.find('textarea');
expect(textarea.attributes('placeholder')).toEqual(
'Write a comment or drag your files here…', 'Write a comment or drag your files here…',
); );
}); });
it('should link to markdown docs', () => { it('should link to markdown docs', () => {
const { markdownDocsPath } = notesDataMock; const { markdownDocsPath } = notesDataMock;
const markdownField = wrapper.find(MarkdownField);
const markdownFieldProps = markdownField.props();
expect(vm.$el.querySelector(`a[href="${markdownDocsPath}"]`).textContent.trim()).toEqual( expect(markdownFieldProps.markdownDocsPath).toBe(markdownDocsPath);
'Markdown',
);
}); });
describe('keyboard events', () => { describe('keyboard events', () => {
let textarea;
beforeEach(() => {
textarea = wrapper.find('textarea');
textarea.setValue('Foo');
});
describe('up', () => { describe('up', () => {
it('should ender edit mode', () => { it('should ender edit mode', () => {
spyOn(vm, 'editMyLastNote').and.callThrough(); // TODO: do not spy on vm
vm.$el.querySelector('textarea').value = 'Foo'; spyOn(wrapper.vm, 'editMyLastNote').and.callThrough();
vm.$el.querySelector('textarea').dispatchEvent(keyboardDownEvent(38, true));
expect(vm.editMyLastNote).toHaveBeenCalled(); textarea.trigger('keydown.up');
expect(wrapper.vm.editMyLastNote).toHaveBeenCalled();
}); });
}); });
describe('enter', () => { describe('enter', () => {
it('should save note when cmd+enter is pressed', () => { it('should save note when cmd+enter is pressed', () => {
spyOn(vm, 'handleUpdate').and.callThrough(); textarea.trigger('keydown.enter', { metaKey: true });
vm.$el.querySelector('textarea').value = 'Foo';
vm.$el.querySelector('textarea').dispatchEvent(keyboardDownEvent(13, true)); const { handleFormUpdate } = wrapper.emitted();
expect(vm.handleUpdate).toHaveBeenCalled(); expect(handleFormUpdate.length).toBe(1);
}); });
it('should save note when ctrl+enter is pressed', () => { it('should save note when ctrl+enter is pressed', () => {
spyOn(vm, 'handleUpdate').and.callThrough(); textarea.trigger('keydown.enter', { ctrlKey: true });
vm.$el.querySelector('textarea').value = 'Foo';
vm.$el.querySelector('textarea').dispatchEvent(keyboardDownEvent(13, false, true)); const { handleFormUpdate } = wrapper.emitted();
expect(vm.handleUpdate).toHaveBeenCalled(); expect(handleFormUpdate.length).toBe(1);
}); });
}); });
}); });
describe('actions', () => { describe('actions', () => {
it('should be possible to cancel', done => { it('should be possible to cancel', done => {
spyOn(vm, 'cancelHandler').and.callThrough(); // TODO: do not spy on vm
vm.isEditing = true; spyOn(wrapper.vm, 'cancelHandler').and.callThrough();
wrapper.setProps({
...props,
isEditing: true,
});
Vue.nextTick(() => { wrapper.vm
vm.$el.querySelector('.note-edit-cancel').click(); .$nextTick()
.then(() => {
const cancelButton = wrapper.find('.note-edit-cancel');
cancelButton.trigger('click');
Vue.nextTick(() => { expect(wrapper.vm.cancelHandler).toHaveBeenCalled();
expect(vm.cancelHandler).toHaveBeenCalled(); })
done(); .then(done)
}); .catch(done.fail);
});
}); });
it('should be possible to update the note', done => { it('should be possible to update the note', done => {
vm.isEditing = true; wrapper.setProps({
...props,
isEditing: true,
});
Vue.nextTick(() => { wrapper.vm
vm.$el.querySelector('textarea').value = 'Foo'; .$nextTick()
vm.$el.querySelector('.js-vue-issue-save').click(); .then(() => {
const textarea = wrapper.find('textarea');
textarea.setValue('Foo');
const saveButton = wrapper.find('.js-vue-issue-save');
saveButton.trigger('click');
Vue.nextTick(() => { expect(wrapper.vm.isSubmitting).toEqual(true);
expect(vm.isSubmitting).toEqual(true); })
done(); .then(done)
}); .catch(done.fail);
});
}); });
}); });
}); });
......
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