Commit 71a949f0 authored by Martin Wortschack's avatar Martin Wortschack Committed by Filipa Lacerda

Add "no data" message to charts

Refactor loading behavior

- Let's fetch the main chart first (instead of the MR table)
and use the responde to determine
whether the user has access to a given group
parent 8897a392
...@@ -26,15 +26,18 @@ export const fetchChartData = ({ dispatch, getters, rootState }, chartKey) => { ...@@ -26,15 +26,18 @@ export const fetchChartData = ({ dispatch, getters, rootState }, chartKey) => {
const { data } = response; const { data } = response;
dispatch('receiveChartDataSuccess', { chartKey, data }); dispatch('receiveChartDataSuccess', { chartKey, data });
}) })
.catch(() => dispatch('receiveChartDataError', chartKey)); .catch(error => dispatch('receiveChartDataError', { chartKey, error }));
}; };
export const receiveChartDataSuccess = ({ commit }, { chartKey, data = {} }) => { export const receiveChartDataSuccess = ({ commit }, { chartKey, data = {} }) => {
commit(types.RECEIVE_CHART_DATA_SUCCESS, { chartKey, data }); commit(types.RECEIVE_CHART_DATA_SUCCESS, { chartKey, data });
}; };
export const receiveChartDataError = ({ commit }, chartKey) => { export const receiveChartDataError = ({ commit }, { chartKey, error }) => {
commit(types.RECEIVE_CHART_DATA_ERROR, chartKey); const {
response: { status },
} = error;
commit(types.RECEIVE_CHART_DATA_ERROR, { chartKey, status });
}; };
export const setMetricType = ({ commit, dispatch }, { chartKey, metricType }) => { export const setMetricType = ({ commit, dispatch }, { chartKey, metricType }) => {
......
import _ from 'underscore';
import httpStatus from '~/lib/utils/http_status';
import { import {
chartKeys, chartKeys,
metricTypes, metricTypes,
...@@ -43,11 +45,11 @@ export const getChartData = state => chartKey => { ...@@ -43,11 +45,11 @@ export const getChartData = state => chartKey => {
}; };
}); });
return { return dataWithSelected;
full: dataWithSelected,
};
}; };
export const chartHasData = state => chartKey => !_.isEmpty(state.charts[chartKey].data);
export const getMetricDropdownLabel = state => chartKey => export const getMetricDropdownLabel = state => chartKey =>
metricTypes.find(m => m.key === state.charts[chartKey].params.metricType).label; metricTypes.find(m => m.key === state.charts[chartKey].params.metricType).label;
...@@ -108,5 +110,8 @@ export const getColumnChartDatazoomOption = state => chartKey => { ...@@ -108,5 +110,8 @@ export const getColumnChartDatazoomOption = state => chartKey => {
export const isSelectedMetric = state => ({ metric, chartKey }) => export const isSelectedMetric = state => ({ metric, chartKey }) =>
state.charts[chartKey].params.metricType === metric; state.charts[chartKey].params.metricType === metric;
export const hasNoAccessError = state =>
state.charts[chartKeys.main].hasError === httpStatus.FORBIDDEN;
// prevent babel-plugin-rewire from generating an invalid default during karma tests // prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {}; export default () => {};
...@@ -13,9 +13,9 @@ export default { ...@@ -13,9 +13,9 @@ export default {
state.charts[chartKey].hasError = false; state.charts[chartKey].hasError = false;
state.charts[chartKey].data = data; state.charts[chartKey].data = data;
}, },
[types.RECEIVE_CHART_DATA_ERROR](state, chartKey) { [types.RECEIVE_CHART_DATA_ERROR](state, { chartKey, status }) {
state.charts[chartKey].isLoading = false; state.charts[chartKey].isLoading = false;
state.charts[chartKey].hasError = true; state.charts[chartKey].hasError = status;
state.charts[chartKey].data = {}; state.charts[chartKey].data = {};
}, },
[types.SET_METRIC_TYPE](state, { chartKey, metricType }) { [types.SET_METRIC_TYPE](state, { chartKey, metricType }) {
......
import * as types from './mutation_types'; import * as types from './mutation_types';
import { chartKeys } from '../../../constants';
export const setGroupNamespace = ({ commit, dispatch }, groupNamespace) => { export const setGroupNamespace = ({ commit, dispatch }, groupNamespace) => {
commit(types.SET_GROUP_NAMESPACE, groupNamespace); commit(types.SET_GROUP_NAMESPACE, groupNamespace);
// let's fetch the merge requests first to see if the user has access to the selected group // let's fetch the main chart data first to see if the user has access to the selected group
// if there's no 403, then we fetch all chart data // if there's no 403, then we fetch all remaining chart data and table data
return dispatch('table/fetchMergeRequests', null, { root: true }).then(() => return dispatch('charts/fetchChartData', chartKeys.main, { root: true }).then(() => {
dispatch('charts/fetchAllChartData', null, { root: true }), dispatch('charts/fetchChartData', chartKeys.timeBasedHistogram, { root: true });
); dispatch('charts/fetchChartData', chartKeys.commitBasedHistogram, { root: true });
dispatch('table/fetchMergeRequests', null, { root: true });
});
}; };
export const setProjectPath = ({ commit, dispatch }, projectPath) => { export const setProjectPath = ({ commit, dispatch }, projectPath) => {
commit(types.SET_PROJECT_PATH, projectPath); commit(types.SET_PROJECT_PATH, projectPath);
dispatch('charts/fetchAllChartData', null, { root: true }); return dispatch('charts/fetchChartData', chartKeys.main, { root: true }).then(() => {
dispatch('table/fetchMergeRequests', null, { root: true }); dispatch('charts/fetchChartData', chartKeys.timeBasedHistogram, { root: true });
dispatch('charts/fetchChartData', chartKeys.commitBasedHistogram, { root: true });
dispatch('table/fetchMergeRequests', null, { root: true });
});
}; };
export const setPath = ({ commit, dispatch }, path) => { export const setPath = ({ commit, dispatch }, path) => {
commit(types.SET_PATH, path); commit(types.SET_PATH, path);
dispatch('charts/fetchAllChartData', null, { root: true }); return dispatch('charts/fetchChartData', chartKeys.main, { root: true }).then(() => {
dispatch('table/fetchMergeRequests', null, { root: true }); dispatch('charts/fetchChartData', chartKeys.timeBasedHistogram, { root: true });
dispatch('charts/fetchChartData', chartKeys.commitBasedHistogram, { root: true });
dispatch('table/fetchMergeRequests', null, { root: true });
});
}; };
export const setDaysInPast = ({ commit, dispatch }, days) => { export const setDaysInPast = ({ commit, dispatch }, days) => {
commit(types.SET_DAYS_IN_PAST, days); commit(types.SET_DAYS_IN_PAST, days);
dispatch('charts/fetchAllChartData', null, { root: true }); return dispatch('charts/fetchChartData', chartKeys.main, { root: true }).then(() => {
dispatch('table/fetchMergeRequests', null, { root: true }); dispatch('charts/fetchChartData', chartKeys.timeBasedHistogram, { root: true });
dispatch('charts/fetchChartData', chartKeys.commitBasedHistogram, { root: true });
dispatch('table/fetchMergeRequests', null, { root: true });
});
}; };
// prevent babel-plugin-rewire from generating an invalid default during karma tests // prevent babel-plugin-rewire from generating an invalid default during karma tests
......
import httpStatus from '~/lib/utils/http_status';
import { chartKeys, tableSortOrder, daysToMergeMetric } from '../../../constants'; import { chartKeys, tableSortOrder, daysToMergeMetric } from '../../../constants';
export const sortIcon = state => tableSortOrder[state.sortOrder].icon; export const sortIcon = state => tableSortOrder[state.sortOrder].icon;
...@@ -20,7 +19,5 @@ export const columnMetricLabel = (state, _getters, _rootState, rootGetters) => ...@@ -20,7 +19,5 @@ export const columnMetricLabel = (state, _getters, _rootState, rootGetters) =>
export const isSelectedSortField = state => sortField => state.sortField === sortField; export const isSelectedSortField = state => sortField => state.sortField === sortField;
export const hasNoAccessError = state => state.hasError === httpStatus.FORBIDDEN;
// prevent babel-plugin-rewire from generating an invalid default during karma tests // prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {}; export default () => {};
...@@ -75,7 +75,7 @@ describe('ProductivityApp component', () => { ...@@ -75,7 +75,7 @@ describe('ProductivityApp component', () => {
describe('and user has no access to the group', () => { describe('and user has no access to the group', () => {
beforeEach(() => { beforeEach(() => {
store.state.table.hasError = 403; store.state.charts.charts[chartKeys.main].hasError = 403;
}); });
it('renders the no access illustration', () => { it('renders the no access illustration', () => {
...@@ -88,7 +88,7 @@ describe('ProductivityApp component', () => { ...@@ -88,7 +88,7 @@ describe('ProductivityApp component', () => {
describe('and user has access to the group', () => { describe('and user has access to the group', () => {
beforeEach(() => { beforeEach(() => {
store.state.table.hasError = false; store.state.charts.charts[chartKeys.main].hasError = false;
}); });
describe('Time to merge chart', () => { describe('Time to merge chart', () => {
...@@ -115,34 +115,57 @@ describe('ProductivityApp component', () => { ...@@ -115,34 +115,57 @@ describe('ProductivityApp component', () => {
store.state.charts.charts[chartKeys.main].isLoading = false; store.state.charts.charts[chartKeys.main].isLoading = false;
}); });
it('renders a column chart', () => { describe('and the chart has data', () => {
expect( beforeEach(() => {
store.state.charts.charts[chartKeys.main].data = { 1: 2, 2: 3 };
});
it('renders a column chart', () => {
expect(
findTimeToMergeSection()
.find(GlColumnChart)
.exists(),
).toBe(true);
});
it('calls onMainChartItemClicked when chartItemClicked is emitted on the column chart ', () => {
const data = {
chart: null,
params: {
data: {
value: [0, 1],
},
},
};
findTimeToMergeSection() findTimeToMergeSection()
.find(GlColumnChart) .find(GlColumnChart)
.exists(), .vm.$emit('chartItemClicked', data);
).toBe(true);
});
it('calls onMainChartItemClicked when chartItemClicked is emitted on the column chart ', () => { expect(onMainChartItemClickedMock).toHaveBeenCalledWith(data);
const data = { });
chart: null, });
params: {
data: {
value: [0, 1],
},
},
};
findTimeToMergeSection() describe("and the chart doesn't have any data", () => {
.find(GlColumnChart) beforeEach(() => {
.vm.$emit('chartItemClicked', data); store.state.charts.charts[chartKeys.main].data = null;
});
expect(onMainChartItemClickedMock).toHaveBeenCalledWith(data); it('renders a "no data" message', () => {
expect(findTimeToMergeSection().text()).toContain(
'There is no data available. Please change your selection.',
);
});
}); });
}); });
}); });
describe('Time based histogram', () => { describe('Time based histogram', () => {
beforeEach(() => {
store.state.charts.charts[chartKeys.main].isLoading = false;
store.state.charts.charts[chartKeys.main].data = { 1: 2, 2: 3 };
});
describe('when chart is loading', () => { describe('when chart is loading', () => {
beforeEach(() => { beforeEach(() => {
store.state.charts.charts[chartKeys.timeBasedHistogram].isLoading = true; store.state.charts.charts[chartKeys.timeBasedHistogram].isLoading = true;
...@@ -162,37 +185,60 @@ describe('ProductivityApp component', () => { ...@@ -162,37 +185,60 @@ describe('ProductivityApp component', () => {
store.state.charts.charts[chartKeys.timeBasedHistogram].isLoading = false; store.state.charts.charts[chartKeys.timeBasedHistogram].isLoading = false;
}); });
it('renders a metric type dropdown', () => { describe('and the chart has data', () => {
expect( beforeEach(() => {
store.state.charts.charts[chartKeys.timeBasedHistogram].data = { 1: 2, 2: 3 };
});
it('renders a metric type dropdown', () => {
expect(
findTimeBasedSection()
.find(GlDropdown)
.exists(),
).toBe(true);
});
it('should change the metric type', () => {
findTimeBasedSection() findTimeBasedSection()
.find(GlDropdown) .findAll(GlDropdownItem)
.exists(), .at(0)
).toBe(true); .vm.$emit('click');
});
it('should change the metric type', () => { expect(actionSpies.setMetricType).toHaveBeenCalledWith({
findTimeBasedSection() metricType: 'time_to_first_comment',
.findAll(GlDropdownItem) chartKey: chartKeys.timeBasedHistogram,
.at(0) });
.vm.$emit('click'); });
expect(actionSpies.setMetricType).toHaveBeenCalledWith({ it('renders a column chart', () => {
metricType: 'time_to_first_comment', expect(
chartKey: chartKeys.timeBasedHistogram, findTimeBasedSection()
.find(GlColumnChart)
.exists(),
).toBe(true);
}); });
}); });
it('renders a column chart', () => { describe("and the chart doesn't have any data", () => {
expect( beforeEach(() => {
findTimeBasedSection() store.state.charts.charts[chartKeys.timeBasedHistogram].data = null;
.find(GlColumnChart) });
.exists(),
).toBe(true); it('renders a "no data" message', () => {
expect(findTimeBasedSection().text()).toContain(
'There is no data for the selected metric. Please change your selection.',
);
});
}); });
}); });
}); });
describe('Commit based histogram', () => { describe('Commit based histogram', () => {
beforeEach(() => {
store.state.charts.charts[chartKeys.main].isLoading = false;
store.state.charts.charts[chartKeys.main].data = { 1: 2, 2: 3 };
});
describe('when chart is loading', () => { describe('when chart is loading', () => {
beforeEach(() => { beforeEach(() => {
store.state.charts.charts[chartKeys.commitBasedHistogram].isLoading = true; store.state.charts.charts[chartKeys.commitBasedHistogram].isLoading = true;
...@@ -212,37 +258,60 @@ describe('ProductivityApp component', () => { ...@@ -212,37 +258,60 @@ describe('ProductivityApp component', () => {
store.state.charts.charts[chartKeys.commitBasedHistogram].isLoading = false; store.state.charts.charts[chartKeys.commitBasedHistogram].isLoading = false;
}); });
it('renders a metric type dropdown', () => { describe('and the chart has data', () => {
expect( beforeEach(() => {
store.state.charts.charts[chartKeys.commitBasedHistogram].data = { 1: 2, 2: 3 };
});
it('renders a metric type dropdown', () => {
expect(
findCommitBasedSection()
.find(GlDropdown)
.exists(),
).toBe(true);
});
it('should change the metric type', () => {
findCommitBasedSection() findCommitBasedSection()
.find(GlDropdown) .findAll(GlDropdownItem)
.exists(), .at(0)
).toBe(true); .vm.$emit('click');
});
it('should change the metric type', () => { expect(actionSpies.setMetricType).toHaveBeenCalledWith({
findCommitBasedSection() metricType: 'commits_count',
.findAll(GlDropdownItem) chartKey: chartKeys.commitBasedHistogram,
.at(0) });
.vm.$emit('click'); });
expect(actionSpies.setMetricType).toHaveBeenCalledWith({ it('renders a column chart', () => {
metricType: 'commits_count', expect(
chartKey: chartKeys.commitBasedHistogram, findCommitBasedSection()
.find(GlColumnChart)
.exists(),
).toBe(true);
}); });
}); });
it('renders a column chart', () => { describe("and the chart doesn't have any data", () => {
expect( beforeEach(() => {
findCommitBasedSection() store.state.charts.charts[chartKeys.commitBasedHistogram].data = null;
.find(GlColumnChart) });
.exists(),
).toBe(true); it('renders a "no data" message', () => {
expect(findTimeBasedSection().text()).toContain(
'There is no data for the selected metric. Please change your selection.',
);
});
}); });
}); });
}); });
describe('MR table', () => { describe('MR table', () => {
beforeEach(() => {
store.state.charts.charts[chartKeys.main].isLoading = false;
store.state.charts.charts[chartKeys.main].data = { 1: 2, 2: 3 };
});
describe('when isLoadingTable is true', () => { describe('when isLoadingTable is true', () => {
beforeEach(() => { beforeEach(() => {
store.state.table.isLoadingTable = true; store.state.table.isLoadingTable = true;
...@@ -260,6 +329,7 @@ describe('ProductivityApp component', () => { ...@@ -260,6 +329,7 @@ describe('ProductivityApp component', () => {
describe('when isLoadingTable is false', () => { describe('when isLoadingTable is false', () => {
beforeEach(() => { beforeEach(() => {
store.state.table.isLoadingTable = false; store.state.table.isLoadingTable = false;
store.state.table.mergeRequests = [{ id: 1, title: 'This is a test MR' }];
}); });
it('renders the MR table', () => { it('renders the MR table', () => {
......
...@@ -79,7 +79,7 @@ describe('Productivity analytics chart actions', () => { ...@@ -79,7 +79,7 @@ describe('Productivity analytics chart actions', () => {
describe('error', () => { describe('error', () => {
beforeEach(() => { beforeEach(() => {
mock.onGet(mockedState.endpoint).replyOnce(500, chartKey); mock.onGet(mockedState.endpoint).replyOnce(500);
}); });
it('dispatches error', done => { it('dispatches error', done => {
...@@ -95,7 +95,10 @@ describe('Productivity analytics chart actions', () => { ...@@ -95,7 +95,10 @@ describe('Productivity analytics chart actions', () => {
}, },
{ {
type: 'receiveChartDataError', type: 'receiveChartDataError',
payload: chartKey, payload: {
chartKey,
error: new Error('Request failed with status code 500'),
},
}, },
], ],
done, done,
...@@ -137,14 +140,18 @@ describe('Productivity analytics chart actions', () => { ...@@ -137,14 +140,18 @@ describe('Productivity analytics chart actions', () => {
describe('receiveChartDataError', () => { describe('receiveChartDataError', () => {
it('should commit error', done => { it('should commit error', done => {
const error = { response: { status: 500 } };
testAction( testAction(
actions.receiveChartDataError, actions.receiveChartDataError,
chartKey, { chartKey, error },
mockedContext.state, mockedContext.state,
[ [
{ {
type: types.RECEIVE_CHART_DATA_ERROR, type: types.RECEIVE_CHART_DATA_ERROR,
payload: chartKey, payload: {
chartKey,
status: 500,
},
}, },
], ],
[], [],
......
...@@ -38,12 +38,10 @@ describe('Productivity analytics chart getters', () => { ...@@ -38,12 +38,10 @@ describe('Productivity analytics chart getters', () => {
selected: ['5'], selected: ['5'],
}; };
const chartData = { const chartData = [
full: [ { value: ['1', 32], itemStyle: {} },
{ value: ['1', 32], itemStyle: {} }, { value: ['5', 17], itemStyle: columnHighlightStyle },
{ value: ['5', 17], itemStyle: columnHighlightStyle }, ];
],
};
expect(getters.getChartData(state)(chartKey)).toEqual(chartData); expect(getters.getChartData(state)(chartKey)).toEqual(chartData);
}); });
...@@ -179,4 +177,16 @@ describe('Productivity analytics chart getters', () => { ...@@ -179,4 +177,16 @@ describe('Productivity analytics chart getters', () => {
}); });
}); });
}); });
describe('hasNoAccessError', () => {
it('returns true if "hasError" is set to 403', () => {
state.charts[chartKeys.main].hasError = 403;
expect(getters.hasNoAccessError(state)).toEqual(true);
});
it('returns false if "hasError" is not set to 403', () => {
state.charts[chartKeys.main].hasError = false;
expect(getters.hasNoAccessError(state)).toEqual(false);
});
});
}); });
...@@ -40,11 +40,12 @@ describe('Productivity analytics chart mutations', () => { ...@@ -40,11 +40,12 @@ describe('Productivity analytics chart mutations', () => {
}); });
describe(types.RECEIVE_CHART_DATA_ERROR, () => { describe(types.RECEIVE_CHART_DATA_ERROR, () => {
it('sets isError and clears data', () => { it('sets isError to error code and clears data', () => {
mutations[types.RECEIVE_CHART_DATA_ERROR](state, chartKey); const status = 500;
mutations[types.RECEIVE_CHART_DATA_ERROR](state, { chartKey, status });
expect(state.charts[chartKey].isLoading).toBe(false); expect(state.charts[chartKey].isLoading).toBe(false);
expect(state.charts[chartKey].hasError).toBe(true); expect(state.charts[chartKey].hasError).toBe(status);
expect(state.charts[chartKey].data).toEqual({}); expect(state.charts[chartKey].data).toEqual({});
}); });
}); });
......
import testAction from 'helpers/vuex_action_helper';
import * as actions from 'ee/analytics/productivity_analytics/store/modules/filters/actions'; import * as actions from 'ee/analytics/productivity_analytics/store/modules/filters/actions';
import * as types from 'ee/analytics/productivity_analytics/store/modules/filters/mutation_types'; import * as types from 'ee/analytics/productivity_analytics/store/modules/filters/mutation_types';
import getInitialState from 'ee/analytics/productivity_analytics/store/modules/filters/state'; import { chartKeys } from 'ee/analytics/productivity_analytics/constants';
describe('Productivity analytics filter actions', () => { describe('Productivity analytics filter actions', () => {
const groupNamespace = 'gitlab-org'; const groupNamespace = 'gitlab-org';
const projectPath = 'gitlab-org/gitlab-test'; const projectPath = 'gitlab-org/gitlab-test';
const path = 'author_username=root';
const daysInPast = 90;
describe('setGroupNamespace', () => { describe('setGroupNamespace', () => {
it('commits the SET_GROUP_NAMESPACE mutation', done => { it('commits the SET_GROUP_NAMESPACE mutation', done => {
...@@ -20,13 +21,25 @@ describe('Productivity analytics filter actions', () => { ...@@ -20,13 +21,25 @@ describe('Productivity analytics filter actions', () => {
expect(store.commit).toHaveBeenCalledWith(types.SET_GROUP_NAMESPACE, groupNamespace); expect(store.commit).toHaveBeenCalledWith(types.SET_GROUP_NAMESPACE, groupNamespace);
expect(store.dispatch.mock.calls[0]).toEqual([ expect(store.dispatch.mock.calls[0]).toEqual([
'table/fetchMergeRequests', 'charts/fetchChartData',
jasmine.any(Object), chartKeys.main,
{ root: true }, { root: true },
]); ]);
expect(store.dispatch.mock.calls[1]).toEqual([ expect(store.dispatch.mock.calls[1]).toEqual([
'charts/fetchAllChartData', 'charts/fetchChartData',
chartKeys.timeBasedHistogram,
{ root: true },
]);
expect(store.dispatch.mock.calls[2]).toEqual([
'charts/fetchChartData',
chartKeys.commitBasedHistogram,
{ root: true },
]);
expect(store.dispatch.mock.calls[3]).toEqual([
'table/fetchMergeRequests',
jasmine.any(Object), jasmine.any(Object),
{ root: true }, { root: true },
]); ]);
...@@ -37,80 +50,125 @@ describe('Productivity analytics filter actions', () => { ...@@ -37,80 +50,125 @@ describe('Productivity analytics filter actions', () => {
}); });
describe('setProjectPath', () => { describe('setProjectPath', () => {
it('commits the SET_PROJECT_PATH mutation', done => it('commits the SET_PROJECT_PATH mutation', done => {
testAction( const store = {
actions.setProjectPath, commit: jest.fn(),
projectPath, dispatch: jest.fn(() => Promise.resolve()),
getInitialState(), };
[
{ actions
type: types.SET_PROJECT_PATH, .setProjectPath(store, projectPath)
payload: projectPath, .then(() => {
}, expect(store.commit).toHaveBeenCalledWith(types.SET_PROJECT_PATH, projectPath);
],
[ expect(store.dispatch.mock.calls[0]).toEqual([
{ 'charts/fetchChartData',
type: 'charts/fetchAllChartData', chartKeys.main,
payload: null, { root: true },
}, ]);
{
type: 'table/fetchMergeRequests', expect(store.dispatch.mock.calls[1]).toEqual([
payload: null, 'charts/fetchChartData',
}, chartKeys.timeBasedHistogram,
], { root: true },
done, ]);
));
expect(store.dispatch.mock.calls[2]).toEqual([
'charts/fetchChartData',
chartKeys.commitBasedHistogram,
{ root: true },
]);
expect(store.dispatch.mock.calls[3]).toEqual([
'table/fetchMergeRequests',
jasmine.any(Object),
{ root: true },
]);
})
.then(done)
.catch(done.fail);
});
}); });
describe('setPath', () => { describe('setPath', () => {
it('commits the SET_PATH mutation', done => it('commits the SET_PATH mutation', done => {
testAction( const store = {
actions.setPath, commit: jest.fn(),
'author_username=root', dispatch: jest.fn(() => Promise.resolve()),
getInitialState(), };
[
{ actions
type: types.SET_PATH, .setPath(store, path)
payload: 'author_username=root', .then(() => {
}, expect(store.commit).toHaveBeenCalledWith(types.SET_PATH, path);
],
[ expect(store.dispatch.mock.calls[0]).toEqual([
{ 'charts/fetchChartData',
type: 'charts/fetchAllChartData', chartKeys.main,
payload: null, { root: true },
}, ]);
{
type: 'table/fetchMergeRequests', expect(store.dispatch.mock.calls[1]).toEqual([
payload: null, 'charts/fetchChartData',
}, chartKeys.timeBasedHistogram,
], { root: true },
done, ]);
));
expect(store.dispatch.mock.calls[2]).toEqual([
'charts/fetchChartData',
chartKeys.commitBasedHistogram,
{ root: true },
]);
expect(store.dispatch.mock.calls[3]).toEqual([
'table/fetchMergeRequests',
jasmine.any(Object),
{ root: true },
]);
})
.then(done)
.catch(done.fail);
});
}); });
describe('setDaysInPast', () => { describe('setDaysInPast', () => {
it('commits the SET_DAYS_IN_PAST mutation', done => it('commits the SET_DAYS_IN_PAST mutation', done => {
testAction( const store = {
actions.setDaysInPast, commit: jest.fn(),
90, dispatch: jest.fn(() => Promise.resolve()),
getInitialState(), };
[
{ actions
type: types.SET_DAYS_IN_PAST, .setDaysInPast(store, daysInPast)
payload: 90, .then(() => {
}, expect(store.commit).toHaveBeenCalledWith(types.SET_DAYS_IN_PAST, daysInPast);
],
[ expect(store.dispatch.mock.calls[0]).toEqual([
{ 'charts/fetchChartData',
type: 'charts/fetchAllChartData', chartKeys.main,
payload: null, { root: true },
}, ]);
{
type: 'table/fetchMergeRequests', expect(store.dispatch.mock.calls[1]).toEqual([
payload: null, 'charts/fetchChartData',
}, chartKeys.timeBasedHistogram,
], { root: true },
done, ]);
));
expect(store.dispatch.mock.calls[2]).toEqual([
'charts/fetchChartData',
chartKeys.commitBasedHistogram,
{ root: true },
]);
expect(store.dispatch.mock.calls[3]).toEqual([
'table/fetchMergeRequests',
jasmine.any(Object),
{ root: true },
]);
})
.then(done)
.catch(done.fail);
});
}); });
}); });
...@@ -76,16 +76,4 @@ describe('Productivity analytics table getters', () => { ...@@ -76,16 +76,4 @@ describe('Productivity analytics table getters', () => {
expect(getters.tableSortOptions(null, null, null, rootGetters)).toEqual(expected); expect(getters.tableSortOptions(null, null, null, rootGetters)).toEqual(expected);
}); });
}); });
describe('hasNoAccessError', () => {
it('returns true if "hasError" is set to 403', () => {
state.hasError = 403;
expect(getters.hasNoAccessError(state)).toEqual(true);
});
it('returns false if "hasError" is not set to 403', () => {
state.hasError = false;
expect(getters.hasNoAccessError(state)).toEqual(false);
});
});
}); });
...@@ -15547,6 +15547,12 @@ msgstr "" ...@@ -15547,6 +15547,12 @@ msgstr ""
msgid "There is already a repository with that name on disk" msgid "There is already a repository with that name on disk"
msgstr "" msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
msgid "There is no data for the selected metric. Please change your selection."
msgstr ""
msgid "There was a problem communicating with your device." msgid "There was a problem communicating with your device."
msgstr "" msgstr ""
......
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