Commit 60bcc616 authored by Vitaly Slobodin's avatar Vitaly Slobodin

Migrate ee/insights to Jest

Closes https://gitlab.com/gitlab-org/gitlab/-/issues/194290
parent a516e498
......@@ -20,11 +20,11 @@ describe('Insights chart error component', () => {
});
it('renders the component', () => {
expect(wrapper.find('.content-title').text()).toEqual(`${title}: "${chartName}"`);
expect(wrapper.find('.content-title').text()).toBe(`${title}: "${chartName}"`);
const summaries = wrapper.findAll('.content-summary');
expect(summaries.at(0).text()).toEqual(summary);
expect(summaries.at(1).text()).toEqual(error);
expect(summaries.at(0).text()).toBe(summary);
expect(summaries.at(1).text()).toBe(error);
});
});
import { GlColumnChart, GlLineChart, GlStackedColumnChart } from '@gitlab/ui/dist/charts';
import { shallowMount } from '@vue/test-utils';
import { chartInfo, barChartData, lineChartData, stackedBarChartData } from '../mock_data';
import {
chartInfo,
barChartData,
lineChartData,
stackedBarChartData,
} from 'ee_jest/insights/mock_data';
import InsightsChart from 'ee/insights/components/insights_chart.vue';
import InsightsChartError from 'ee/insights/components/insights_chart_error.vue';
import { CHART_TYPES } from 'ee/insights/constants';
......
......@@ -27,7 +27,7 @@ describe('Insights config warning component', () => {
.attributes('src'),
).toContain(image);
expect(wrapper.find('.content-title').text()).toEqual(title);
expect(wrapper.find('.content-summary').text()).toEqual(summary);
expect(wrapper.find('.content-title').text()).toBe(title);
expect(wrapper.find('.content-summary').text()).toBe(summary);
});
});
import Vue from 'vue';
import InsightsPage from 'ee/insights/components/insights_page.vue';
import { createStore } from 'ee/insights/stores';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { chartInfo, pageInfo, pageInfoNoCharts } from '../mock_data';
import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
import { TEST_HOST } from 'helpers/test_constants';
import { chartInfo, pageInfo, pageInfoNoCharts } from 'ee_jest/insights/mock_data';
describe('Insights page component', () => {
let component;
......@@ -11,7 +12,7 @@ describe('Insights page component', () => {
beforeEach(() => {
store = createStore();
spyOn(store, 'dispatch').and.stub();
jest.spyOn(store, 'dispatch').mockImplementation(() => {});
Component = Vue.extend(InsightsPage);
});
......@@ -20,17 +21,16 @@ describe('Insights page component', () => {
});
describe('no chart config available', () => {
it('shows an empty state', done => {
it('shows an empty state', () => {
component = mountComponentWithStore(Component, {
store,
props: {
queryEndpoint: `${gl.TEST_HOST}/query`,
queryEndpoint: `${TEST_HOST}/query`,
pageConfig: pageInfoNoCharts,
},
});
expect(component.$el.querySelector('.js-empty-state')).not.toBe(null);
done();
});
});
......@@ -39,18 +39,17 @@ describe('Insights page component', () => {
component = mountComponentWithStore(Component, {
store,
props: {
queryEndpoint: `${gl.TEST_HOST}/query`,
queryEndpoint: `${TEST_HOST}/query`,
pageConfig: pageInfo,
},
});
});
it('fetches chart data when mounted', done => {
it('fetches chart data when mounted', () => {
expect(store.dispatch).toHaveBeenCalledWith('insights/fetchChartData', {
endpoint: `${gl.TEST_HOST}/query`,
endpoint: `${TEST_HOST}/query`,
chart: chartInfo,
});
done();
});
describe('when charts loading', () => {
......@@ -58,35 +57,29 @@ describe('Insights page component', () => {
component.$store.state.insights.pageLoading = true;
});
it('renders loading state', done => {
Vue.nextTick(() => {
it('renders loading state', () => {
return component.$nextTick(() => {
expect(
component.$el.querySelector('.js-insights-page-container .insights-chart-loading'),
).not.toBe(null);
done();
});
});
it('does not display chart area', done => {
Vue.nextTick(() => {
it('does not display chart area', () => {
return component.$nextTick(() => {
expect(component.$el.querySelector('.js-insights-page-container .insights-charts')).toBe(
null,
);
done();
});
});
});
describe('pageConfig changes', () => {
it('reflects new state', done => {
// Establish rendered state
component.$nextTick();
it('reflects new state', () => {
component.pageConfig = pageInfoNoCharts;
component.$nextTick(() => {
return component.$nextTick(() => {
expect(component.$el.querySelector('.js-empty-state')).not.toBe(null);
done();
});
});
});
......
import Vue from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import Insights from 'ee/insights/components/insights.vue';
import { createStore } from 'ee/insights/stores';
import createRouter from 'ee/insights/insights_router';
import { pageInfo } from '../mock_data';
import { pageInfo } from 'ee_jest/insights/mock_data';
describe('Insights component', () => {
let vm;
......@@ -13,14 +14,14 @@ describe('Insights component', () => {
beforeEach(() => {
store = createStore();
spyOn(store, 'dispatch').and.stub();
jest.spyOn(store, 'dispatch').mockImplementation(() => {});
mountComponent = data => {
const el = null;
const props = data || {
endpoint: gl.TEST_HOST,
queryEndpoint: `${gl.TEST_HOST}/query`,
endpoint: TEST_HOST,
queryEndpoint: `${TEST_HOST}/query`,
};
return new Component({
......@@ -34,22 +35,21 @@ describe('Insights component', () => {
});
afterEach(() => {
store.dispatch.mockReset();
vm.$destroy();
});
it('fetches config data when mounted', done => {
expect(store.dispatch).toHaveBeenCalledWith('insights/fetchConfigData', gl.TEST_HOST);
done();
it('fetches config data when mounted', () => {
expect(store.dispatch).toHaveBeenCalledWith('insights/fetchConfigData', TEST_HOST);
});
describe('when loading config', () => {
it('renders config loading state', done => {
it('renders config loading state', () => {
vm.$store.state.insights.configLoading = true;
vm.$nextTick(() => {
return vm.$nextTick(() => {
expect(vm.$el.querySelector('.insights-config-loading')).not.toBe(null);
expect(vm.$el.querySelector('.insights-wrapper')).toBe(null);
done();
});
});
});
......@@ -68,13 +68,12 @@ describe('Insights component', () => {
};
});
it('has the correct nav tabs', done => {
vm.$nextTick(() => {
it('has the correct nav tabs', () => {
return vm.$nextTick(() => {
expect(vm.$el.querySelector('.js-insights-dropdown')).not.toBe(null);
expect(vm.$el.querySelector('.js-insights-dropdown .dropdown-item').innerText.trim()).toBe(
title,
);
done();
});
});
......@@ -83,12 +82,11 @@ describe('Insights component', () => {
vm.$store.state.insights.pageLoading = true;
});
it('disables the tab selector', done => {
vm.$nextTick(() => {
it('disables the tab selector', () => {
return vm.$nextTick(() => {
expect(
vm.$el.querySelector('.js-insights-dropdown > button').getAttribute('disabled'),
).toBe('disabled');
done();
});
});
});
......@@ -100,12 +98,11 @@ describe('Insights component', () => {
vm.$store.state.insights.configData = null;
});
it('it displays a warning', done => {
vm.$nextTick(() => {
it('it displays a warning', () => {
return vm.$nextTick(() => {
expect(vm.$el.querySelector('.js-empty-state').innerText.trim()).toContain(
'Invalid Insights config file detected',
);
done();
});
});
});
......@@ -128,22 +125,24 @@ describe('Insights component', () => {
window.location.hash = '';
});
it('selects the first tab if invalid', done => {
it('selects the first tab if invalid', () => {
window.location.hash = '#/invalid';
vm.$nextTick(() => {
jest.runOnlyPendingTimers();
return vm.$nextTick(() => {
expect(store.dispatch).toHaveBeenCalledWith('insights/setActiveTab', defaultKey);
});
done();
});
it('selects the specified tab if valid', done => {
it('selects the specified tab if valid', () => {
window.location.hash = `#/${selectedKey}`;
vm.$nextTick(() => {
jest.runOnlyPendingTimers();
return vm.$nextTick(() => {
expect(store.dispatch).toHaveBeenCalledWith('insights/setActiveTab', selectedKey);
});
done();
});
});
});
......@@ -11,7 +11,7 @@ describe('insights router', () => {
it(`sets the activeTab when route changed`, () => {
const route = 'route';
spyOn(store, 'dispatch').and.stub();
jest.spyOn(store, 'dispatch').mockImplementation(() => {});
router.push(`/${route}`);
......
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import testAction from 'spec/helpers/vuex_action_helper';
import createFlash from '~/flash';
import testAction from 'helpers/vuex_action_helper';
import { TEST_HOST } from 'helpers/test_constants';
import actionsModule, * as actions from 'ee/insights/stores/modules/insights/actions';
import * as actions from 'ee/insights/stores/modules/insights/actions';
import { CHART_TYPES } from 'ee/insights/constants';
const ERROR_MESSAGE = 'TEST_ERROR_MESSAGE';
jest.mock('~/flash');
describe('Insights store actions', () => {
const key = 'bugsPerTeam';
const chart = {
......@@ -32,59 +36,50 @@ describe('Insights store actions', () => {
});
describe('requestConfig', () => {
it('commits REQUEST_CONFIG', done => {
testAction(actions.requestConfig, null, null, [{ type: 'REQUEST_CONFIG' }], [], done);
it('commits REQUEST_CONFIG', () => {
return testAction(actions.requestConfig, null, null, [{ type: 'REQUEST_CONFIG' }], []);
});
});
describe('receiveConfigSuccess', () => {
it('commits RECEIVE_CONFIG_SUCCESS', done => {
testAction(
it('commits RECEIVE_CONFIG_SUCCESS', () => {
return testAction(
actions.receiveConfigSuccess,
[configData],
null,
[{ type: 'RECEIVE_CONFIG_SUCCESS', payload: [configData] }],
[],
done,
);
});
});
describe('receiveConfigError', () => {
let flashSpy;
beforeEach(() => {
flashSpy = spyOnDependency(actionsModule, 'createFlash');
});
it('commits RECEIVE_CONFIG_ERROR and shows flash message', done => {
testAction(
it('commits RECEIVE_CONFIG_ERROR and shows flash message', () => {
return testAction(
actions.receiveConfigError,
ERROR_MESSAGE,
null,
[{ type: 'RECEIVE_CONFIG_ERROR' }],
[],
() => {
expect(flashSpy).toHaveBeenCalledWith(
expect(createFlash).toHaveBeenCalledWith(
`There was an error fetching configuration for charts: ${ERROR_MESSAGE}`,
);
done();
},
);
});
it('flashes Unknown Error when error message is falsey', done => {
testAction(
it('flashes Unknown Error when error message is falsey', () => {
return testAction(
actions.receiveConfigError,
null,
null,
jasmine.any(Array),
jasmine.any(Array),
() => {
expect(flashSpy).toHaveBeenCalledWith(
expect(createFlash).toHaveBeenCalledWith(
`There was an error fetching configuration for charts: Unknown Error`,
);
done();
},
);
});
......@@ -103,51 +98,48 @@ describe('Insights store actions', () => {
describe('success calls', () => {
beforeEach(() => {
mock.onGet(gl.TEST_HOST).reply(200, configData);
mock.onGet(TEST_HOST).reply(200, configData);
});
it('calls requestConfig and receiveConfigSuccess', done => {
testAction(
it('calls requestConfig and receiveConfigSuccess', () => {
return testAction(
actions.fetchConfigData,
gl.TEST_HOST,
TEST_HOST,
{},
[],
[{ type: 'requestConfig' }, { type: 'receiveConfigSuccess', payload: configData }],
done,
);
});
});
describe('failed calls', () => {
beforeEach(() => {
mock.onGet(gl.TEST_HOST).reply(500, { message: ERROR_MESSAGE });
mock.onGet(TEST_HOST).reply(500, { message: ERROR_MESSAGE });
});
it('calls receiveConfigError upon error from service', done => {
testAction(
it('calls receiveConfigError upon error from service', () => {
return testAction(
actions.fetchConfigData,
gl.TEST_HOST,
TEST_HOST,
{},
[],
[{ type: 'requestConfig' }, { type: 'receiveConfigError', payload: ERROR_MESSAGE }],
done,
);
});
});
describe('success calls with null data', () => {
beforeEach(() => {
mock.onGet(gl.TEST_HOST).reply(200, null);
mock.onGet(TEST_HOST).reply(200, null);
});
it('calls receiveConfigError upon null config data returned', done => {
testAction(
it('calls receiveConfigError upon null config data returned', () => {
return testAction(
actions.fetchConfigData,
gl.TEST_HOST,
TEST_HOST,
{},
[],
[{ type: 'requestConfig' }, { type: 'receiveConfigError' }],
done,
);
});
});
......@@ -156,8 +148,8 @@ describe('Insights store actions', () => {
describe('receiveChartDataSuccess', () => {
const chartData = { type: CHART_TYPES.BAR, data: {} };
it('commits RECEIVE_CHART_SUCCESS', done => {
testAction(
it('commits RECEIVE_CHART_SUCCESS', () => {
return testAction(
actions.receiveChartDataSuccess,
{ chart, data: chartData },
null,
......@@ -168,7 +160,6 @@ describe('Insights store actions', () => {
},
],
[],
done,
);
});
});
......@@ -176,8 +167,8 @@ describe('Insights store actions', () => {
describe('receiveChartDataError', () => {
const error = 'myError';
it('commits RECEIVE_CHART_ERROR', done => {
testAction(
it('commits RECEIVE_CHART_ERROR', () => {
return testAction(
actions.receiveChartDataError,
{ chart, error },
null,
......@@ -188,7 +179,6 @@ describe('Insights store actions', () => {
},
],
[],
done,
);
});
});
......@@ -196,7 +186,7 @@ describe('Insights store actions', () => {
describe('fetchChartData', () => {
let mock;
let dispatch;
const payload = { endpoint: `${gl.TEST_HOST}/query`, chart };
const payload = { endpoint: `${TEST_HOST}/query`, chart };
const chartData = {
labels: ['January', 'February'],
......@@ -217,7 +207,7 @@ describe('Insights store actions', () => {
};
beforeEach(() => {
dispatch = jasmine.createSpy('dispatch');
dispatch = jest.fn().mockName('dispatch');
mock = new MockAdapter(axios);
});
......@@ -227,47 +217,39 @@ describe('Insights store actions', () => {
describe('successful request', () => {
beforeEach(() => {
mock.onPost(`${gl.TEST_HOST}/query`, chart).reply(200, chartData);
mock.onPost(`${TEST_HOST}/query`, chart).reply(200, chartData);
});
it('calls receiveChartDataSuccess with chart data', done => {
it('calls receiveChartDataSuccess with chart data', () => {
const context = {
dispatch,
};
actions
.fetchChartData(context, payload)
.then(() => {
expect(dispatch.calls.argsFor(0)).toEqual([
'receiveChartDataSuccess',
{ chart, data: chartData },
]);
})
.then(done)
.catch(done.fail);
return actions.fetchChartData(context, payload).then(() => {
expect(dispatch.mock.calls[0]).toEqual([
'receiveChartDataSuccess',
{ chart, data: chartData },
]);
});
});
});
describe('failed request', () => {
beforeEach(() => {
mock.onPost(`${gl.TEST_HOST}/query`, chart).reply(500);
mock.onPost(`${TEST_HOST}/query`, chart).reply(500);
});
it('calls receiveChartDataError with error message', done => {
it('calls receiveChartDataError with error message', () => {
const context = {
dispatch,
};
actions
.fetchChartData(context, payload)
.then(() => {
expect(dispatch.calls.argsFor(0)).toEqual([
'receiveChartDataError',
{ chart, error: 'There was an error gathering the chart data' },
]);
})
.then(done)
.catch(done.fail);
return actions.fetchChartData(context, payload).then(() => {
expect(dispatch.mock.calls[0]).toEqual([
'receiveChartDataError',
{ chart, error: 'There was an error gathering the chart data' },
]);
});
});
});
});
......@@ -279,54 +261,51 @@ describe('Insights store actions', () => {
state = { configData };
});
it('commits SET_ACTIVE_TAB and SET_ACTIVE_PAGE', done => {
testAction(
it('commits SET_ACTIVE_TAB and SET_ACTIVE_PAGE', () => {
return testAction(
actions.setActiveTab,
key,
state,
[{ type: 'SET_ACTIVE_TAB', payload: key }, { type: 'SET_ACTIVE_PAGE', payload: page }],
[],
done,
);
});
it('does not mutate with no configData', done => {
it('does not mutate with no configData', () => {
state = { configData: null };
testAction(actions.setActiveTab, key, state, [], [], done);
testAction(actions.setActiveTab, key, state, [], []);
});
it('does not mutate with no matching tab', done => {
testAction(actions.setActiveTab, 'invalidTab', state, [], [], done);
it('does not mutate with no matching tab', () => {
testAction(actions.setActiveTab, 'invalidTab', state, [], []);
});
});
describe('initChartData', () => {
it('commits INIT_CHART_DATA', done => {
it('commits INIT_CHART_DATA', () => {
const keys = ['a', 'b'];
testAction(
return testAction(
actions.initChartData,
keys,
null,
[{ type: 'INIT_CHART_DATA', payload: keys }],
[],
done,
);
});
});
describe('setPageLoading', () => {
it('commits SET_PAGE_LOADING', done => {
it('commits SET_PAGE_LOADING', () => {
const pageLoading = false;
testAction(
return testAction(
actions.setPageLoading,
pageLoading,
null,
[{ type: 'SET_PAGE_LOADING', payload: false }],
[],
done,
);
});
});
......
......@@ -3,7 +3,7 @@ import mutations from 'ee/insights/stores/modules/insights/mutations';
import * as types from 'ee/insights/stores/modules/insights/mutation_types';
import { CHART_TYPES } from 'ee/insights/constants';
import { configData } from '../../../../javascripts/insights/mock_data';
import { configData } from 'ee_jest/insights/mock_data';
describe('Insights mutations', () => {
let state;
......
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