Commit bd002aac authored by Illya Klymov's avatar Illya Klymov

Merge branch 'himkp-jest-pages' into 'master'

Migrate javascripts/pages specs to Jest

Closes #194246

See merge request gitlab-org/gitlab!32506
parents 90d77a1a aae8e127
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
import Vue from 'vue'; import Vue from 'vue';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import Translate from '../../../../../vue_shared/translate'; import Translate from '../../../../../vue_shared/translate';
import illustrationSvg from '../icons/intro_illustration.svg'; // Full path is needed for Jest to be able to correctly mock this file
import illustrationSvg from '~/pages/projects/pipeline_schedules/shared/icons/intro_illustration.svg';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
Vue.use(Translate); Vue.use(Translate);
......
import Vue from 'vue'; import Vue from 'vue';
import { redirectTo } from '~/lib/utils/url_utility';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import stopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue'; import stopJobsModal from '~/pages/admin/jobs/index/components/stop_jobs_modal.vue';
jest.mock('~/lib/utils/url_utility', () => ({
...jest.requireActual('~/lib/utils/url_utility'),
redirectTo: jest.fn(),
}));
describe('stop_jobs_modal.vue', () => { describe('stop_jobs_modal.vue', () => {
const props = { const props = {
url: `${gl.TEST_HOST}/stop_jobs_modal.vue/stopAll`, url: `${gl.TEST_HOST}/stop_jobs_modal.vue/stopAll`,
...@@ -22,8 +27,7 @@ describe('stop_jobs_modal.vue', () => { ...@@ -22,8 +27,7 @@ describe('stop_jobs_modal.vue', () => {
describe('onSubmit', () => { describe('onSubmit', () => {
it('stops jobs and redirects to overview page', done => { it('stops jobs and redirects to overview page', done => {
const responseURL = `${gl.TEST_HOST}/stop_jobs_modal.vue/jobs`; const responseURL = `${gl.TEST_HOST}/stop_jobs_modal.vue/jobs`;
const redirectSpy = spyOnDependency(stopJobsModal, 'redirectTo'); jest.spyOn(axios, 'post').mockImplementation(url => {
spyOn(axios, 'post').and.callFake(url => {
expect(url).toBe(props.url); expect(url).toBe(props.url);
return Promise.resolve({ return Promise.resolve({
request: { request: {
...@@ -34,7 +38,7 @@ describe('stop_jobs_modal.vue', () => { ...@@ -34,7 +38,7 @@ describe('stop_jobs_modal.vue', () => {
vm.onSubmit() vm.onSubmit()
.then(() => { .then(() => {
expect(redirectSpy).toHaveBeenCalledWith(responseURL); expect(redirectTo).toHaveBeenCalledWith(responseURL);
}) })
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
...@@ -42,8 +46,7 @@ describe('stop_jobs_modal.vue', () => { ...@@ -42,8 +46,7 @@ describe('stop_jobs_modal.vue', () => {
it('displays error if stopping jobs failed', done => { it('displays error if stopping jobs failed', done => {
const dummyError = new Error('stopping jobs failed'); const dummyError = new Error('stopping jobs failed');
const redirectSpy = spyOnDependency(stopJobsModal, 'redirectTo'); jest.spyOn(axios, 'post').mockImplementation(url => {
spyOn(axios, 'post').and.callFake(url => {
expect(url).toBe(props.url); expect(url).toBe(props.url);
return Promise.reject(dummyError); return Promise.reject(dummyError);
}); });
...@@ -52,7 +55,7 @@ describe('stop_jobs_modal.vue', () => { ...@@ -52,7 +55,7 @@ describe('stop_jobs_modal.vue', () => {
.then(done.fail) .then(done.fail)
.catch(error => { .catch(error => {
expect(error).toBe(dummyError); expect(error).toBe(dummyError);
expect(redirectSpy).not.toHaveBeenCalled(); expect(redirectTo).not.toHaveBeenCalled();
}) })
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
......
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 promoteLabelModal from '~/pages/projects/labels/components/promote_label_modal.vue'; import promoteLabelModal from '~/pages/projects/labels/components/promote_label_modal.vue';
import eventHub from '~/pages/projects/labels/event_hub'; import eventHub from '~/pages/projects/labels/event_hub';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
...@@ -43,7 +43,7 @@ describe('Promote label modal', () => { ...@@ -43,7 +43,7 @@ describe('Promote label modal', () => {
vm = mountComponent(Component, { vm = mountComponent(Component, {
...labelMockData, ...labelMockData,
}); });
spyOn(eventHub, '$emit'); jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
}); });
afterEach(() => { afterEach(() => {
...@@ -52,7 +52,7 @@ describe('Promote label modal', () => { ...@@ -52,7 +52,7 @@ describe('Promote label modal', () => {
it('redirects when a label is promoted', done => { it('redirects when a label is promoted', done => {
const responseURL = `${gl.TEST_HOST}/dummy/endpoint`; const responseURL = `${gl.TEST_HOST}/dummy/endpoint`;
spyOn(axios, 'post').and.callFake(url => { jest.spyOn(axios, 'post').mockImplementation(url => {
expect(url).toBe(labelMockData.url); expect(url).toBe(labelMockData.url);
expect(eventHub.$emit).toHaveBeenCalledWith( expect(eventHub.$emit).toHaveBeenCalledWith(
'promoteLabelModal.requestStarted', 'promoteLabelModal.requestStarted',
...@@ -79,7 +79,7 @@ describe('Promote label modal', () => { ...@@ -79,7 +79,7 @@ describe('Promote label modal', () => {
it('displays an error if promoting a label failed', done => { it('displays an error if promoting a label failed', done => {
const dummyError = new Error('promoting label failed'); const dummyError = new Error('promoting label failed');
dummyError.response = { status: 500 }; dummyError.response = { status: 500 };
spyOn(axios, 'post').and.callFake(url => { jest.spyOn(axios, 'post').mockImplementation(url => {
expect(url).toBe(labelMockData.url); expect(url).toBe(labelMockData.url);
expect(eventHub.$emit).toHaveBeenCalledWith( expect(eventHub.$emit).toHaveBeenCalledWith(
'promoteLabelModal.requestStarted', 'promoteLabelModal.requestStarted',
......
import Vue from 'vue'; import Vue from 'vue';
import { redirectTo } from '~/lib/utils/url_utility';
import mountComponent from 'spec/helpers/vue_mount_component_helper'; import mountComponent from 'helpers/vue_mount_component_helper';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import deleteMilestoneModal from '~/pages/milestones/shared/components/delete_milestone_modal.vue'; import deleteMilestoneModal from '~/pages/milestones/shared/components/delete_milestone_modal.vue';
import eventHub from '~/pages/milestones/shared/event_hub'; import eventHub from '~/pages/milestones/shared/event_hub';
jest.mock('~/lib/utils/url_utility', () => ({
...jest.requireActual('~/lib/utils/url_utility'),
redirectTo: jest.fn(),
}));
describe('delete_milestone_modal.vue', () => { describe('delete_milestone_modal.vue', () => {
const Component = Vue.extend(deleteMilestoneModal); const Component = Vue.extend(deleteMilestoneModal);
const props = { const props = {
...@@ -23,29 +28,28 @@ describe('delete_milestone_modal.vue', () => { ...@@ -23,29 +28,28 @@ describe('delete_milestone_modal.vue', () => {
describe('onSubmit', () => { describe('onSubmit', () => {
beforeEach(() => { beforeEach(() => {
vm = mountComponent(Component, props); vm = mountComponent(Component, props);
spyOn(eventHub, '$emit'); jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
}); });
it('deletes milestone and redirects to overview page', done => { it('deletes milestone and redirects to overview page', done => {
const responseURL = `${gl.TEST_HOST}/delete_milestone_modal.vue/milestoneOverview`; const responseURL = `${gl.TEST_HOST}/delete_milestone_modal.vue/milestoneOverview`;
spyOn(axios, 'delete').and.callFake(url => { jest.spyOn(axios, 'delete').mockImplementation(url => {
expect(url).toBe(props.milestoneUrl); expect(url).toBe(props.milestoneUrl);
expect(eventHub.$emit).toHaveBeenCalledWith( expect(eventHub.$emit).toHaveBeenCalledWith(
'deleteMilestoneModal.requestStarted', 'deleteMilestoneModal.requestStarted',
props.milestoneUrl, props.milestoneUrl,
); );
eventHub.$emit.calls.reset(); eventHub.$emit.mockReset();
return Promise.resolve({ return Promise.resolve({
request: { request: {
responseURL, responseURL,
}, },
}); });
}); });
const redirectSpy = spyOnDependency(deleteMilestoneModal, 'redirectTo');
vm.onSubmit() vm.onSubmit()
.then(() => { .then(() => {
expect(redirectSpy).toHaveBeenCalledWith(responseURL); expect(redirectTo).toHaveBeenCalledWith(responseURL);
expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', { expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
milestoneUrl: props.milestoneUrl, milestoneUrl: props.milestoneUrl,
successful: true, successful: true,
...@@ -58,21 +62,20 @@ describe('delete_milestone_modal.vue', () => { ...@@ -58,21 +62,20 @@ describe('delete_milestone_modal.vue', () => {
it('displays error if deleting milestone failed', done => { it('displays error if deleting milestone failed', done => {
const dummyError = new Error('deleting milestone failed'); const dummyError = new Error('deleting milestone failed');
dummyError.response = { status: 418 }; dummyError.response = { status: 418 };
spyOn(axios, 'delete').and.callFake(url => { jest.spyOn(axios, 'delete').mockImplementation(url => {
expect(url).toBe(props.milestoneUrl); expect(url).toBe(props.milestoneUrl);
expect(eventHub.$emit).toHaveBeenCalledWith( expect(eventHub.$emit).toHaveBeenCalledWith(
'deleteMilestoneModal.requestStarted', 'deleteMilestoneModal.requestStarted',
props.milestoneUrl, props.milestoneUrl,
); );
eventHub.$emit.calls.reset(); eventHub.$emit.mockReset();
return Promise.reject(dummyError); return Promise.reject(dummyError);
}); });
const redirectSpy = spyOnDependency(deleteMilestoneModal, 'redirectTo');
vm.onSubmit() vm.onSubmit()
.catch(error => { .catch(error => {
expect(error).toBe(dummyError); expect(error).toBe(dummyError);
expect(redirectSpy).not.toHaveBeenCalled(); expect(redirectTo).not.toHaveBeenCalled();
expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', { expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
milestoneUrl: props.milestoneUrl, milestoneUrl: props.milestoneUrl,
successful: false, successful: false,
......
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 promoteMilestoneModal from '~/pages/milestones/shared/components/promote_milestone_modal.vue'; import promoteMilestoneModal from '~/pages/milestones/shared/components/promote_milestone_modal.vue';
import eventHub from '~/pages/milestones/shared/event_hub'; import eventHub from '~/pages/milestones/shared/event_hub';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
...@@ -38,7 +38,7 @@ describe('Promote milestone modal', () => { ...@@ -38,7 +38,7 @@ describe('Promote milestone modal', () => {
vm = mountComponent(Component, { vm = mountComponent(Component, {
...milestoneMockData, ...milestoneMockData,
}); });
spyOn(eventHub, '$emit'); jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
}); });
afterEach(() => { afterEach(() => {
...@@ -47,7 +47,7 @@ describe('Promote milestone modal', () => { ...@@ -47,7 +47,7 @@ describe('Promote milestone modal', () => {
it('redirects when a milestone is promoted', done => { it('redirects when a milestone is promoted', done => {
const responseURL = `${gl.TEST_HOST}/dummy/endpoint`; const responseURL = `${gl.TEST_HOST}/dummy/endpoint`;
spyOn(axios, 'post').and.callFake(url => { jest.spyOn(axios, 'post').mockImplementation(url => {
expect(url).toBe(milestoneMockData.url); expect(url).toBe(milestoneMockData.url);
expect(eventHub.$emit).toHaveBeenCalledWith( expect(eventHub.$emit).toHaveBeenCalledWith(
'promoteMilestoneModal.requestStarted', 'promoteMilestoneModal.requestStarted',
...@@ -74,7 +74,7 @@ describe('Promote milestone modal', () => { ...@@ -74,7 +74,7 @@ describe('Promote milestone modal', () => {
it('displays an error if promoting a milestone failed', done => { it('displays an error if promoting a milestone failed', done => {
const dummyError = new Error('promoting milestone failed'); const dummyError = new Error('promoting milestone failed');
dummyError.response = { status: 500 }; dummyError.response = { status: 500 };
spyOn(axios, 'post').and.callFake(url => { jest.spyOn(axios, 'post').mockImplementation(url => {
expect(url).toBe(milestoneMockData.url); expect(url).toBe(milestoneMockData.url);
expect(eventHub.$emit).toHaveBeenCalledWith( expect(eventHub.$emit).toHaveBeenCalledWith(
'promoteMilestoneModal.requestStarted', 'promoteMilestoneModal.requestStarted',
......
import Vue from 'vue'; import Vue from 'vue';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import PipelineSchedulesCallout from '~/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue'; import PipelineSchedulesCallout from '~/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue';
import '~/pages/projects/pipeline_schedules/shared/icons/intro_illustration.svg';
jest.mock(
'~/pages/projects/pipeline_schedules/shared/icons/intro_illustration.svg',
() => '<svg></svg>',
);
const PipelineSchedulesCalloutComponent = Vue.extend(PipelineSchedulesCallout); const PipelineSchedulesCalloutComponent = Vue.extend(PipelineSchedulesCallout);
const cookieKey = 'pipeline_schedules_callout_dismissed'; const cookieKey = 'pipeline_schedules_callout_dismissed';
const docsUrl = 'help/ci/scheduled_pipelines'; const docsUrl = 'help/ci/scheduled_pipelines';
describe('Pipeline Schedule Callout', function() { describe('Pipeline Schedule Callout', () => {
let calloutComponent;
beforeEach(() => { beforeEach(() => {
setFixtures(` setFixtures(`
<div id='pipeline-schedules-callout' data-docs-url=${docsUrl}></div> <div id='pipeline-schedules-callout' data-docs-url=${docsUrl}></div>
...@@ -15,90 +23,90 @@ describe('Pipeline Schedule Callout', function() { ...@@ -15,90 +23,90 @@ describe('Pipeline Schedule Callout', function() {
describe('independent of cookies', () => { describe('independent of cookies', () => {
beforeEach(() => { beforeEach(() => {
this.calloutComponent = new PipelineSchedulesCalloutComponent().$mount(); calloutComponent = new PipelineSchedulesCalloutComponent().$mount();
}); });
it('the component can be initialized', () => { it('the component can be initialized', () => {
expect(this.calloutComponent).toBeDefined(); expect(calloutComponent).toBeDefined();
}); });
it('correctly sets illustrationSvg', () => { it('correctly sets illustrationSvg', () => {
expect(this.calloutComponent.illustrationSvg).toContain('<svg'); expect(calloutComponent.illustrationSvg).toContain('<svg');
}); });
it('correctly sets docsUrl', () => { it('correctly sets docsUrl', () => {
expect(this.calloutComponent.docsUrl).toContain(docsUrl); expect(calloutComponent.docsUrl).toContain(docsUrl);
}); });
}); });
describe(`when ${cookieKey} cookie is set`, () => { describe(`when ${cookieKey} cookie is set`, () => {
beforeEach(() => { beforeEach(() => {
Cookies.set(cookieKey, true); Cookies.set(cookieKey, true);
this.calloutComponent = new PipelineSchedulesCalloutComponent().$mount(); calloutComponent = new PipelineSchedulesCalloutComponent().$mount();
}); });
it('correctly sets calloutDismissed to true', () => { it('correctly sets calloutDismissed to true', () => {
expect(this.calloutComponent.calloutDismissed).toBe(true); expect(calloutComponent.calloutDismissed).toBe(true);
}); });
it('does not render the callout', () => { it('does not render the callout', () => {
expect(this.calloutComponent.$el.childNodes.length).toBe(0); expect(calloutComponent.$el.childNodes.length).toBe(0);
}); });
}); });
describe('when cookie is not set', () => { describe('when cookie is not set', () => {
beforeEach(() => { beforeEach(() => {
Cookies.remove(cookieKey); Cookies.remove(cookieKey);
this.calloutComponent = new PipelineSchedulesCalloutComponent().$mount(); calloutComponent = new PipelineSchedulesCalloutComponent().$mount();
}); });
it('correctly sets calloutDismissed to false', () => { it('correctly sets calloutDismissed to false', () => {
expect(this.calloutComponent.calloutDismissed).toBe(false); expect(calloutComponent.calloutDismissed).toBe(false);
}); });
it('renders the callout container', () => { it('renders the callout container', () => {
expect(this.calloutComponent.$el.querySelector('.bordered-box')).not.toBeNull(); expect(calloutComponent.$el.querySelector('.bordered-box')).not.toBeNull();
}); });
it('renders the callout svg', () => { it('renders the callout svg', () => {
expect(this.calloutComponent.$el.outerHTML).toContain('<svg'); expect(calloutComponent.$el.outerHTML).toContain('<svg');
}); });
it('renders the callout title', () => { it('renders the callout title', () => {
expect(this.calloutComponent.$el.outerHTML).toContain('Scheduling Pipelines'); expect(calloutComponent.$el.outerHTML).toContain('Scheduling Pipelines');
}); });
it('renders the callout text', () => { it('renders the callout text', () => {
expect(this.calloutComponent.$el.outerHTML).toContain('runs pipelines in the future'); expect(calloutComponent.$el.outerHTML).toContain('runs pipelines in the future');
}); });
it('renders the documentation url', () => { it('renders the documentation url', () => {
expect(this.calloutComponent.$el.outerHTML).toContain(docsUrl); expect(calloutComponent.$el.outerHTML).toContain(docsUrl);
}); });
it('updates calloutDismissed when close button is clicked', done => { it('updates calloutDismissed when close button is clicked', done => {
this.calloutComponent.$el.querySelector('#dismiss-callout-btn').click(); calloutComponent.$el.querySelector('#dismiss-callout-btn').click();
Vue.nextTick(() => { Vue.nextTick(() => {
expect(this.calloutComponent.calloutDismissed).toBe(true); expect(calloutComponent.calloutDismissed).toBe(true);
done(); done();
}); });
}); });
it('#dismissCallout updates calloutDismissed', done => { it('#dismissCallout updates calloutDismissed', done => {
this.calloutComponent.dismissCallout(); calloutComponent.dismissCallout();
Vue.nextTick(() => { Vue.nextTick(() => {
expect(this.calloutComponent.calloutDismissed).toBe(true); expect(calloutComponent.calloutDismissed).toBe(true);
done(); done();
}); });
}); });
it('is hidden when close button is clicked', done => { it('is hidden when close button is clicked', done => {
this.calloutComponent.$el.querySelector('#dismiss-callout-btn').click(); calloutComponent.$el.querySelector('#dismiss-callout-btn').click();
Vue.nextTick(() => { Vue.nextTick(() => {
expect(this.calloutComponent.$el.childNodes.length).toBe(0); expect(calloutComponent.$el.childNodes.length).toBe(0);
done(); done();
}); });
}); });
......
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