Commit 8ccae7fa authored by Paul Slaughter's avatar Paul Slaughter

Merge branch '27258-migrate-boards-to-jest' into 'master'

First round of karma to jest migration for boards

See merge request gitlab-org/gitlab!27607
parents e16b3f39 2e606cc5
...@@ -11,9 +11,9 @@ describe('Boards blank state', () => { ...@@ -11,9 +11,9 @@ describe('Boards blank state', () => {
boardsStore.create(); boardsStore.create();
spyOn(boardsStore, 'addList').and.stub(); jest.spyOn(boardsStore, 'addList').mockImplementation();
spyOn(boardsStore, 'removeList').and.stub(); jest.spyOn(boardsStore, 'removeList').mockImplementation();
spyOn(boardsStore, 'generateDefaultLists').and.callFake( jest.spyOn(boardsStore, 'generateDefaultLists').mockImplementation(
() => () =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
if (fail) { if (fail) {
...@@ -39,7 +39,7 @@ describe('Boards blank state', () => { ...@@ -39,7 +39,7 @@ describe('Boards blank state', () => {
vm = new Comp(); vm = new Comp();
setTimeout(() => { setImmediate(() => {
vm.$mount(); vm.$mount();
done(); done();
}); });
...@@ -60,7 +60,7 @@ describe('Boards blank state', () => { ...@@ -60,7 +60,7 @@ describe('Boards blank state', () => {
it('clears blank state', done => { it('clears blank state', done => {
vm.$el.querySelector('.btn-default').click(); vm.$el.querySelector('.btn-default').click();
setTimeout(() => { setImmediate(() => {
expect(boardsStore.welcomeIsHidden()).toBeTruthy(); expect(boardsStore.welcomeIsHidden()).toBeTruthy();
done(); done();
...@@ -70,15 +70,11 @@ describe('Boards blank state', () => { ...@@ -70,15 +70,11 @@ describe('Boards blank state', () => {
it('creates pre-defined labels', done => { it('creates pre-defined labels', done => {
vm.$el.querySelector('.btn-success').click(); vm.$el.querySelector('.btn-success').click();
setTimeout(() => { setImmediate(() => {
expect(boardsStore.addList).toHaveBeenCalledTimes(2); expect(boardsStore.addList).toHaveBeenCalledTimes(2);
expect(boardsStore.addList).toHaveBeenCalledWith( expect(boardsStore.addList).toHaveBeenCalledWith(expect.objectContaining({ title: 'To Do' }));
jasmine.objectContaining({ title: 'To Do' }),
);
expect(boardsStore.addList).toHaveBeenCalledWith( expect(boardsStore.addList).toHaveBeenCalledWith(expect.objectContaining({ title: 'Doing' }));
jasmine.objectContaining({ title: 'Doing' }),
);
done(); done();
}); });
...@@ -89,7 +85,7 @@ describe('Boards blank state', () => { ...@@ -89,7 +85,7 @@ describe('Boards blank state', () => {
vm.$el.querySelector('.btn-success').click(); vm.$el.querySelector('.btn-success').click();
setTimeout(() => { setImmediate(() => {
expect(boardsStore.welcomeIsHidden()).toBeFalsy(); expect(boardsStore.welcomeIsHidden()).toBeFalsy();
expect(boardsStore.removeList).toHaveBeenCalledWith(undefined, 'label'); expect(boardsStore.removeList).toHaveBeenCalledWith(undefined, 'label');
......
/* global List */ /* global List */
import $ from 'jquery';
import Vue from 'vue'; import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
...@@ -14,6 +15,9 @@ describe('Issue boards new issue form', () => { ...@@ -14,6 +15,9 @@ describe('Issue boards new issue form', () => {
let list; let list;
let mock; let mock;
let newIssueMock; let newIssueMock;
const jQueryMock = {
enable: jest.fn(),
};
const promiseReturn = { const promiseReturn = {
data: { data: {
iid: 100, iid: 100,
...@@ -28,7 +32,7 @@ describe('Issue boards new issue form', () => { ...@@ -28,7 +32,7 @@ describe('Issue boards new issue form', () => {
return vm.submit(dummySubmitEvent); return vm.submit(dummySubmitEvent);
}; };
beforeEach(done => { beforeEach(() => {
setFixtures('<div class="test-container"></div>'); setFixtures('<div class="test-container"></div>');
const BoardNewIssueComp = Vue.extend(boardNewIssue); const BoardNewIssueComp = Vue.extend(boardNewIssue);
...@@ -41,7 +45,7 @@ describe('Issue boards new issue form', () => { ...@@ -41,7 +45,7 @@ describe('Issue boards new issue form', () => {
list = new List(listObj); list = new List(listObj);
newIssueMock = Promise.resolve(promiseReturn); newIssueMock = Promise.resolve(promiseReturn);
spyOn(list, 'newIssue').and.callFake(() => newIssueMock); jest.spyOn(list, 'newIssue').mockImplementation(() => newIssueMock);
vm = new BoardNewIssueComp({ vm = new BoardNewIssueComp({
propsData: { propsData: {
...@@ -49,9 +53,9 @@ describe('Issue boards new issue form', () => { ...@@ -49,9 +53,9 @@ describe('Issue boards new issue form', () => {
}, },
}).$mount(document.querySelector('.test-container')); }).$mount(document.querySelector('.test-container'));
Vue.nextTick() $.fn.extend(jQueryMock);
.then(done)
.catch(done.fail); return Vue.nextTick();
}); });
afterEach(() => { afterEach(() => {
...@@ -59,142 +63,116 @@ describe('Issue boards new issue form', () => { ...@@ -59,142 +63,116 @@ describe('Issue boards new issue form', () => {
mock.restore(); mock.restore();
}); });
it('calls submit if submit button is clicked', done => { it('calls submit if submit button is clicked', () => {
spyOn(vm, 'submit').and.callFake(e => e.preventDefault()); jest.spyOn(vm, 'submit').mockImplementation(e => e.preventDefault());
vm.title = 'Testing Title'; vm.title = 'Testing Title';
Vue.nextTick() return Vue.nextTick().then(() => {
.then(() => { vm.$el.querySelector('.btn-success').click();
vm.$el.querySelector('.btn-success').click();
expect(vm.submit.calls.count()).toBe(1); expect(vm.submit.mock.calls.length).toBe(1);
}) });
.then(done)
.catch(done.fail);
}); });
it('disables submit button if title is empty', () => { it('disables submit button if title is empty', () => {
expect(vm.$el.querySelector('.btn-success').disabled).toBe(true); expect(vm.$el.querySelector('.btn-success').disabled).toBe(true);
}); });
it('enables submit button if title is not empty', done => { it('enables submit button if title is not empty', () => {
vm.title = 'Testing Title'; vm.title = 'Testing Title';
Vue.nextTick() return Vue.nextTick().then(() => {
.then(() => { expect(vm.$el.querySelector('.form-control').value).toBe('Testing Title');
expect(vm.$el.querySelector('.form-control').value).toBe('Testing Title'); expect(vm.$el.querySelector('.btn-success').disabled).not.toBe(true);
expect(vm.$el.querySelector('.btn-success').disabled).not.toBe(true); });
})
.then(done)
.catch(done.fail);
}); });
it('clears title after clicking cancel', done => { it('clears title after clicking cancel', () => {
vm.$el.querySelector('.btn-default').click(); vm.$el.querySelector('.btn-default').click();
Vue.nextTick() return Vue.nextTick().then(() => {
.then(() => { expect(vm.title).toBe('');
expect(vm.title).toBe(''); });
})
.then(done)
.catch(done.fail);
}); });
it('does not create new issue if title is empty', done => { it('does not create new issue if title is empty', () => {
submitIssue() return submitIssue().then(() => {
.then(() => { expect(list.newIssue).not.toHaveBeenCalled();
expect(list.newIssue).not.toHaveBeenCalled(); });
})
.then(done)
.catch(done.fail);
}); });
describe('submit success', () => { describe('submit success', () => {
it('creates new issue', done => { it('creates new issue', () => {
vm.title = 'submit title'; vm.title = 'submit title';
Vue.nextTick() return Vue.nextTick()
.then(submitIssue) .then(submitIssue)
.then(() => { .then(() => {
expect(list.newIssue).toHaveBeenCalled(); expect(list.newIssue).toHaveBeenCalled();
}) });
.then(done)
.catch(done.fail);
}); });
it('enables button after submit', done => { it('enables button after submit', () => {
vm.title = 'submit issue'; vm.title = 'submit issue';
Vue.nextTick() return Vue.nextTick()
.then(submitIssue) .then(submitIssue)
.then(() => { .then(() => {
expect(vm.$el.querySelector('.btn-success').disabled).toBe(false); expect(jQueryMock.enable).toHaveBeenCalled();
}) });
.then(done)
.catch(done.fail);
}); });
it('clears title after submit', done => { it('clears title after submit', () => {
vm.title = 'submit issue'; vm.title = 'submit issue';
Vue.nextTick() return Vue.nextTick()
.then(submitIssue) .then(submitIssue)
.then(() => { .then(() => {
expect(vm.title).toBe(''); expect(vm.title).toBe('');
}) });
.then(done)
.catch(done.fail);
}); });
it('sets detail issue after submit', done => { it('sets detail issue after submit', () => {
expect(boardsStore.detail.issue.title).toBe(undefined); expect(boardsStore.detail.issue.title).toBe(undefined);
vm.title = 'submit issue'; vm.title = 'submit issue';
Vue.nextTick() return Vue.nextTick()
.then(submitIssue) .then(submitIssue)
.then(() => { .then(() => {
expect(boardsStore.detail.issue.title).toBe('submit issue'); expect(boardsStore.detail.issue.title).toBe('submit issue');
}) });
.then(done)
.catch(done.fail);
}); });
it('sets detail list after submit', done => { it('sets detail list after submit', () => {
vm.title = 'submit issue'; vm.title = 'submit issue';
Vue.nextTick() return Vue.nextTick()
.then(submitIssue) .then(submitIssue)
.then(() => { .then(() => {
expect(boardsStore.detail.list.id).toBe(list.id); expect(boardsStore.detail.list.id).toBe(list.id);
}) });
.then(done)
.catch(done.fail);
}); });
it('sets detail weight after submit', done => { it('sets detail weight after submit', () => {
boardsStore.weightFeatureAvailable = true; boardsStore.weightFeatureAvailable = true;
vm.title = 'submit issue'; vm.title = 'submit issue';
Vue.nextTick() return Vue.nextTick()
.then(submitIssue) .then(submitIssue)
.then(() => { .then(() => {
expect(boardsStore.detail.list.weight).toBe(list.weight); expect(boardsStore.detail.list.weight).toBe(list.weight);
}) });
.then(done)
.catch(done.fail);
}); });
it('does not set detail weight after submit', done => { it('does not set detail weight after submit', () => {
boardsStore.weightFeatureAvailable = false; boardsStore.weightFeatureAvailable = false;
vm.title = 'submit issue'; vm.title = 'submit issue';
Vue.nextTick() return Vue.nextTick()
.then(submitIssue) .then(submitIssue)
.then(() => { .then(() => {
expect(boardsStore.detail.list.weight).toBe(list.weight); expect(boardsStore.detail.list.weight).toBe(list.weight);
}) });
.then(done)
.catch(done.fail);
}); });
}); });
...@@ -204,24 +182,21 @@ describe('Issue boards new issue form', () => { ...@@ -204,24 +182,21 @@ describe('Issue boards new issue form', () => {
vm.title = 'error'; vm.title = 'error';
}); });
it('removes issue', done => { it('removes issue', () => {
Vue.nextTick() const lengthBefore = list.issues.length;
return Vue.nextTick()
.then(submitIssue) .then(submitIssue)
.then(() => { .then(() => {
expect(list.issues.length).toBe(1); expect(list.issues.length).toBe(lengthBefore);
}) });
.then(done)
.catch(done.fail);
}); });
it('shows error', done => { it('shows error', () => {
Vue.nextTick() return Vue.nextTick()
.then(submitIssue) .then(submitIssue)
.then(() => { .then(() => {
expect(vm.error).toBe(true); expect(vm.error).toBe(true);
}) });
.then(done)
.catch(done.fail);
}); });
}); });
}); });
import $ from 'jquery'; import { mount } from '@vue/test-utils';
import Vue from 'vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import boardsStore from '~/boards/stores/boards_store'; import boardsStore from '~/boards/stores/boards_store';
import boardForm from '~/boards/components/board_form.vue'; import boardForm from '~/boards/components/board_form.vue';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
describe('board_form.vue', () => { describe('board_form.vue', () => {
const props = { let wrapper;
const propsData = {
canAdminBoard: false, canAdminBoard: false,
labelsPath: `${gl.TEST_HOST}/labels/path`, labelsPath: `${gl.TEST_HOST}/labels/path`,
milestonePath: `${gl.TEST_HOST}/milestone/path`, milestonePath: `${gl.TEST_HOST}/milestone/path`,
}; };
let vm;
const findModal = () => wrapper.find(DeprecatedModal);
beforeEach(() => { beforeEach(() => {
spyOn($, 'ajax');
boardsStore.state.currentPage = 'edit'; boardsStore.state.currentPage = 'edit';
const Component = Vue.extend(boardForm); wrapper = mount(boardForm, { propsData });
vm = mountComponent(Component, props);
}); });
afterEach(() => { afterEach(() => {
vm.$destroy(); wrapper.destroy();
wrapper = null;
}); });
describe('methods', () => { describe('methods', () => {
describe('cancel', () => { describe('cancel', () => {
it('resets currentPage', done => { it('resets currentPage', () => {
vm.cancel(); wrapper.vm.cancel();
expect(boardsStore.state.currentPage).toBe('');
Vue.nextTick()
.then(() => {
expect(boardsStore.state.currentPage).toBe('');
})
.then(done)
.catch(done.fail);
}); });
}); });
}); });
describe('buttons', () => { describe('buttons', () => {
it('cancel button triggers cancel()', done => { it('cancel button triggers cancel()', () => {
spyOn(vm, 'cancel'); wrapper.setMethods({ cancel: jest.fn() });
findModal().vm.$emit('cancel');
Vue.nextTick()
.then(() => { return wrapper.vm.$nextTick().then(() => {
const cancelButton = vm.$el.querySelector('button[data-dismiss="modal"]'); expect(wrapper.vm.cancel).toHaveBeenCalled();
cancelButton.click(); });
expect(vm.cancel).toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
}); });
}); });
}); });
...@@ -174,7 +174,7 @@ describe('Issue model', () => { ...@@ -174,7 +174,7 @@ describe('Issue model', () => {
describe('update', () => { describe('update', () => {
it('passes assignee ids when there are assignees', done => { it('passes assignee ids when there are assignees', done => {
spyOn(axios, 'patch').and.callFake((url, data) => { jest.spyOn(axios, 'patch').mockImplementation((url, data) => {
expect(data.issue.assignee_ids).toEqual([1]); expect(data.issue.assignee_ids).toEqual([1]);
done(); done();
return Promise.resolve(); return Promise.resolve();
...@@ -184,7 +184,7 @@ describe('Issue model', () => { ...@@ -184,7 +184,7 @@ describe('Issue model', () => {
}); });
it('passes assignee ids of [0] when there are no assignees', done => { it('passes assignee ids of [0] when there are no assignees', done => {
spyOn(axios, 'patch').and.callFake((url, data) => { jest.spyOn(axios, 'patch').mockImplementation((url, data) => {
expect(data.issue.assignee_ids).toEqual([0]); expect(data.issue.assignee_ids).toEqual([0]);
done(); done();
return Promise.resolve(); return Promise.resolve();
......
import boardsStore from '~/boards/stores/boards_store';
export const boardObj = { export const boardObj = {
id: 1, id: 1,
name: 'test', name: 'test',
...@@ -89,3 +91,54 @@ export const mockMilestone = { ...@@ -89,3 +91,54 @@ export const mockMilestone = {
start_date: '2018-01-01', start_date: '2018-01-01',
due_date: '2019-12-31', due_date: '2019-12-31',
}; };
export const BoardsMockData = {
GET: {
'/test/-/boards/1/lists/300/issues?id=300&page=1': {
issues: [
{
title: 'Testing',
id: 1,
iid: 1,
confidential: false,
labels: [],
assignees: [],
},
],
},
'/test/issue-boards/-/milestones.json': [
{
id: 1,
title: 'test',
},
],
},
POST: {
'/test/-/boards/1/lists': listObj,
},
PUT: {
'/test/issue-boards/-/board/1/lists{/id}': {},
},
DELETE: {
'/test/issue-boards/-/board/1/lists{/id}': {},
},
};
export const boardsMockInterceptor = config => {
const body = BoardsMockData[config.method.toUpperCase()][config.url];
return [200, body];
};
export const setMockEndpoints = (opts = {}) => {
const boardsEndpoint = opts.boardsEndpoint || '/test/issue-boards/-/boards.json';
const listsEndpoint = opts.listsEndpoint || '/test/-/boards/1/lists';
const bulkUpdatePath = opts.bulkUpdatePath || '';
const boardId = opts.boardId || '1';
boardsStore.setEndpoints({
boardsEndpoint,
listsEndpoint,
bulkUpdatePath,
boardId,
});
};
import boardsStore from '~/boards/stores/boards_store';
import { listObj } from '../../frontend/boards/mock_data';
export * from '../../frontend/boards/mock_data'; export * from '../../frontend/boards/mock_data';
export const BoardsMockData = {
GET: {
'/test/-/boards/1/lists/300/issues?id=300&page=1': {
issues: [
{
title: 'Testing',
id: 1,
iid: 1,
confidential: false,
labels: [],
assignees: [],
},
],
},
'/test/issue-boards/-/milestones.json': [
{
id: 1,
title: 'test',
},
],
},
POST: {
'/test/-/boards/1/lists': listObj,
},
PUT: {
'/test/issue-boards/-/board/1/lists{/id}': {},
},
DELETE: {
'/test/issue-boards/-/board/1/lists{/id}': {},
},
};
export const boardsMockInterceptor = config => {
const body = BoardsMockData[config.method.toUpperCase()][config.url];
return [200, body];
};
export const setMockEndpoints = (opts = {}) => {
const boardsEndpoint = opts.boardsEndpoint || '/test/issue-boards/-/boards.json';
const listsEndpoint = opts.listsEndpoint || '/test/-/boards/1/lists';
const bulkUpdatePath = opts.bulkUpdatePath || '';
const boardId = opts.boardId || '1';
boardsStore.setEndpoints({
boardsEndpoint,
listsEndpoint,
bulkUpdatePath,
boardId,
});
};
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