Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/monitoring/store')
-rw-r--r--spec/frontend/monitoring/store/actions_spec.js125
-rw-r--r--spec/frontend/monitoring/store/getters_spec.js119
-rw-r--r--spec/frontend/monitoring/store/mutations_spec.js149
3 files changed, 259 insertions, 134 deletions
diff --git a/spec/frontend/monitoring/store/actions_spec.js b/spec/frontend/monitoring/store/actions_spec.js
index 22f2b2e3c77..5c7ab4e6a1f 100644
--- a/spec/frontend/monitoring/store/actions_spec.js
+++ b/spec/frontend/monitoring/store/actions_spec.js
@@ -1,10 +1,11 @@
import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
+import { backoffMockImplementation } from 'jest/helpers/backoff_helper';
import Tracking from '~/tracking';
import axios from '~/lib/utils/axios_utils';
import statusCodes from '~/lib/utils/http_status';
import * as commonUtils from '~/lib/utils/common_utils';
-import createFlash from '~/flash';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
import { defaultTimeRange } from '~/vue_shared/constants';
import * as getters from '~/monitoring/stores/getters';
import { ENVIRONMENT_AVAILABLE_STATE } from '~/monitoring/constants';
@@ -30,6 +31,7 @@ import {
duplicateSystemDashboard,
updateVariablesAndFetchData,
fetchVariableMetricLabelValues,
+ fetchPanelPreview,
} from '~/monitoring/stores/actions';
import {
gqClient,
@@ -73,19 +75,7 @@ describe('Monitoring store actions', () => {
commit = jest.fn();
dispatch = jest.fn();
- jest.spyOn(commonUtils, 'backOff').mockImplementation(callback => {
- const q = new Promise((resolve, reject) => {
- const stop = arg => (arg instanceof Error ? reject(arg) : resolve(arg));
- const next = () => callback(next, stop);
- // Define a timeout based on a mock timer
- setTimeout(() => {
- callback(next, stop);
- });
- });
- // Run all resolved promises in chain
- jest.runOnlyPendingTimers();
- return q;
- });
+ jest.spyOn(commonUtils, 'backOff').mockImplementation(backoffMockImplementation);
});
afterEach(() => {
@@ -483,7 +473,6 @@ describe('Monitoring store actions', () => {
],
[],
() => {
- expect(mock.history.get).toHaveLength(1);
done();
},
).catch(done.fail);
@@ -569,46 +558,8 @@ describe('Monitoring store actions', () => {
});
});
- it('commits result, when waiting for results', done => {
- // Mock multiple attempts while the cache is filling up
- mock.onGet(prometheusEndpointPath).replyOnce(statusCodes.NO_CONTENT);
- mock.onGet(prometheusEndpointPath).replyOnce(statusCodes.NO_CONTENT);
- mock.onGet(prometheusEndpointPath).replyOnce(statusCodes.NO_CONTENT);
- mock.onGet(prometheusEndpointPath).reply(200, { data }); // 4th attempt
-
- testAction(
- fetchPrometheusMetric,
- { metric, defaultQueryParams },
- state,
- [
- {
- type: types.REQUEST_METRIC_RESULT,
- payload: {
- metricId: metric.metricId,
- },
- },
- {
- type: types.RECEIVE_METRIC_RESULT_SUCCESS,
- payload: {
- metricId: metric.metricId,
- data,
- },
- },
- ],
- [],
- () => {
- expect(mock.history.get).toHaveLength(4);
- done();
- },
- ).catch(done.fail);
- });
-
it('commits failure, when waiting for results and getting a server error', done => {
- // Mock multiple attempts while the cache is filling up and fails
- mock.onGet(prometheusEndpointPath).replyOnce(statusCodes.NO_CONTENT);
- mock.onGet(prometheusEndpointPath).replyOnce(statusCodes.NO_CONTENT);
- mock.onGet(prometheusEndpointPath).replyOnce(statusCodes.NO_CONTENT);
- mock.onGet(prometheusEndpointPath).reply(500); // 4th attempt
+ mock.onGet(prometheusEndpointPath).reply(500);
const error = new Error('Request failed with status code 500');
@@ -633,7 +584,6 @@ describe('Monitoring store actions', () => {
],
[],
).catch(e => {
- expect(mock.history.get).toHaveLength(4);
expect(e).toEqual(error);
done();
});
@@ -1205,4 +1155,69 @@ describe('Monitoring store actions', () => {
);
});
});
+
+ describe('fetchPanelPreview', () => {
+ const panelPreviewEndpoint = '/builder.json';
+ const mockYmlContent = 'mock yml content';
+
+ beforeEach(() => {
+ state.panelPreviewEndpoint = panelPreviewEndpoint;
+ });
+
+ it('should not commit or dispatch if payload is empty', () => {
+ testAction(fetchPanelPreview, '', state, [], []);
+ });
+
+ it('should store the panel and fetch metric results', () => {
+ const mockPanel = {
+ title: 'Go heap size',
+ type: 'area-chart',
+ };
+
+ mock
+ .onPost(panelPreviewEndpoint, { panel_yaml: mockYmlContent })
+ .reply(statusCodes.OK, mockPanel);
+
+ testAction(
+ fetchPanelPreview,
+ mockYmlContent,
+ state,
+ [
+ { type: types.SET_PANEL_PREVIEW_IS_SHOWN, payload: true },
+ { type: types.REQUEST_PANEL_PREVIEW, payload: mockYmlContent },
+ { type: types.RECEIVE_PANEL_PREVIEW_SUCCESS, payload: mockPanel },
+ ],
+ [{ type: 'fetchPanelPreviewMetrics' }],
+ );
+ });
+
+ it('should display a validation error when the backend cannot process the yml', () => {
+ const mockErrorMsg = 'Each "metric" must define one of :query or :query_range';
+
+ mock
+ .onPost(panelPreviewEndpoint, { panel_yaml: mockYmlContent })
+ .reply(statusCodes.UNPROCESSABLE_ENTITY, {
+ message: mockErrorMsg,
+ });
+
+ testAction(fetchPanelPreview, mockYmlContent, state, [
+ { type: types.SET_PANEL_PREVIEW_IS_SHOWN, payload: true },
+ { type: types.REQUEST_PANEL_PREVIEW, payload: mockYmlContent },
+ { type: types.RECEIVE_PANEL_PREVIEW_FAILURE, payload: mockErrorMsg },
+ ]);
+ });
+
+ it('should display a generic error when the backend fails', () => {
+ mock.onPost(panelPreviewEndpoint, { panel_yaml: mockYmlContent }).reply(500);
+
+ testAction(fetchPanelPreview, mockYmlContent, state, [
+ { type: types.SET_PANEL_PREVIEW_IS_SHOWN, payload: true },
+ { type: types.REQUEST_PANEL_PREVIEW, payload: mockYmlContent },
+ {
+ type: types.RECEIVE_PANEL_PREVIEW_FAILURE,
+ payload: 'Request failed with status code 500',
+ },
+ ]);
+ });
+ });
});
diff --git a/spec/frontend/monitoring/store/getters_spec.js b/spec/frontend/monitoring/store/getters_spec.js
index a69f5265ea7..509de8a4596 100644
--- a/spec/frontend/monitoring/store/getters_spec.js
+++ b/spec/frontend/monitoring/store/getters_spec.js
@@ -11,37 +11,36 @@ import {
storeVariables,
mockLinks,
} from '../mock_data';
-import {
- metricsDashboardPayload,
- metricResultStatus,
- metricResultPods,
- metricResultEmpty,
-} from '../fixture_data';
+import { metricsDashboardPayload } from '../fixture_data';
describe('Monitoring store Getters', () => {
+ let state;
+
+ const getMetric = ({ group = 0, panel = 0, metric = 0 } = {}) =>
+ state.dashboard.panelGroups[group].panels[panel].metrics[metric];
+
+ const setMetricSuccess = ({ group, panel, metric, result = metricsResult } = {}) => {
+ const { metricId } = getMetric({ group, panel, metric });
+ mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, {
+ metricId,
+ data: {
+ resultType: 'matrix',
+ result,
+ },
+ });
+ };
+
+ const setMetricFailure = ({ group, panel, metric } = {}) => {
+ const { metricId } = getMetric({ group, panel, metric });
+ mutations[types.RECEIVE_METRIC_RESULT_FAILURE](state, {
+ metricId,
+ });
+ };
+
describe('getMetricStates', () => {
let setupState;
- let state;
let getMetricStates;
- const setMetricSuccess = ({ result = metricsResult, group = 0, panel = 0, metric = 0 }) => {
- const { metricId } = state.dashboard.panelGroups[group].panels[panel].metrics[metric];
- mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, {
- metricId,
- data: {
- resultType: 'matrix',
- result,
- },
- });
- };
-
- const setMetricFailure = ({ group = 0, panel = 0, metric = 0 }) => {
- const { metricId } = state.dashboard.panelGroups[group].panels[panel].metrics[metric];
- mutations[types.RECEIVE_METRIC_RESULT_FAILURE](state, {
- metricId,
- });
- };
-
beforeEach(() => {
setupState = (initState = {}) => {
state = initState;
@@ -81,7 +80,7 @@ describe('Monitoring store Getters', () => {
it('on an empty metric with no result, returns NO_DATA', () => {
mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload);
- setMetricSuccess({ result: [], group: 2 });
+ setMetricSuccess({ group: 2, result: [] });
expect(getMetricStates()).toEqual([metricStates.NO_DATA]);
});
@@ -147,7 +146,6 @@ describe('Monitoring store Getters', () => {
describe('metricsWithData', () => {
let metricsWithData;
let setupState;
- let state;
beforeEach(() => {
setupState = (initState = {}) => {
@@ -191,35 +189,39 @@ describe('Monitoring store Getters', () => {
it('an empty metric, returns empty', () => {
mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload);
- mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, metricResultEmpty);
+ setMetricSuccess({ result: [] });
expect(metricsWithData()).toEqual([]);
});
it('a metric with results, it returns a metric', () => {
mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload);
- mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, metricResultStatus);
+ setMetricSuccess();
- expect(metricsWithData()).toEqual([metricResultStatus.metricId]);
+ expect(metricsWithData()).toEqual([getMetric().metricId]);
});
it('multiple metrics with results, it return multiple metrics', () => {
mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload);
- mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, metricResultStatus);
- mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, metricResultPods);
+ setMetricSuccess({ panel: 0 });
+ setMetricSuccess({ panel: 1 });
- expect(metricsWithData()).toEqual([metricResultStatus.metricId, metricResultPods.metricId]);
+ expect(metricsWithData()).toEqual([
+ getMetric({ panel: 0 }).metricId,
+ getMetric({ panel: 1 }).metricId,
+ ]);
});
it('multiple metrics with results, it returns metrics filtered by group', () => {
mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload);
- mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, metricResultStatus);
- mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](state, metricResultPods);
+
+ setMetricSuccess({ group: 1 });
+ setMetricSuccess({ group: 1, panel: 1 });
// First group has metrics
expect(metricsWithData(state.dashboard.panelGroups[1].key)).toEqual([
- metricResultStatus.metricId,
- metricResultPods.metricId,
+ getMetric({ group: 1 }).metricId,
+ getMetric({ group: 1, panel: 1 }).metricId,
]);
// Second group has no metrics
@@ -229,7 +231,6 @@ describe('Monitoring store Getters', () => {
});
describe('filteredEnvironments', () => {
- let state;
const setupState = (initState = {}) => {
state = {
...state,
@@ -284,7 +285,6 @@ describe('Monitoring store Getters', () => {
describe('metricsSavedToDb', () => {
let metricsSavedToDb;
- let state;
let mockData;
beforeEach(() => {
@@ -335,8 +335,6 @@ describe('Monitoring store Getters', () => {
});
describe('getCustomVariablesParams', () => {
- let state;
-
beforeEach(() => {
state = {
variables: {},
@@ -367,58 +365,65 @@ describe('Monitoring store Getters', () => {
describe('selectedDashboard', () => {
const { selectedDashboard } = getters;
- const localGetters = state => ({
- fullDashboardPath: getters.fullDashboardPath(state),
+ const localGetters = localState => ({
+ fullDashboardPath: getters.fullDashboardPath(localState),
});
it('returns a dashboard', () => {
- const state = {
+ const localState = {
allDashboards: dashboardGitResponse,
currentDashboard: dashboardGitResponse[0].path,
customDashboardBasePath,
};
- expect(selectedDashboard(state, localGetters(state))).toEqual(dashboardGitResponse[0]);
+ expect(selectedDashboard(localState, localGetters(localState))).toEqual(
+ dashboardGitResponse[0],
+ );
});
- it('returns a non-default dashboard', () => {
- const state = {
+ it('returns a dashboard different from the overview dashboard', () => {
+ const localState = {
allDashboards: dashboardGitResponse,
currentDashboard: dashboardGitResponse[1].path,
customDashboardBasePath,
};
- expect(selectedDashboard(state, localGetters(state))).toEqual(dashboardGitResponse[1]);
+ expect(selectedDashboard(localState, localGetters(localState))).toEqual(
+ dashboardGitResponse[1],
+ );
});
- it('returns a default dashboard when no dashboard is selected', () => {
- const state = {
+ it('returns the overview dashboard when no dashboard is selected', () => {
+ const localState = {
allDashboards: dashboardGitResponse,
currentDashboard: null,
customDashboardBasePath,
};
- expect(selectedDashboard(state, localGetters(state))).toEqual(dashboardGitResponse[0]);
+ expect(selectedDashboard(localState, localGetters(localState))).toEqual(
+ dashboardGitResponse[0],
+ );
});
- it('returns a default dashboard when dashboard cannot be found', () => {
- const state = {
+ it('returns the overview dashboard when dashboard cannot be found', () => {
+ const localState = {
allDashboards: dashboardGitResponse,
currentDashboard: 'wrong_path',
customDashboardBasePath,
};
- expect(selectedDashboard(state, localGetters(state))).toEqual(dashboardGitResponse[0]);
+ expect(selectedDashboard(localState, localGetters(localState))).toEqual(
+ dashboardGitResponse[0],
+ );
});
it('returns null when no dashboards are present', () => {
- const state = {
+ const localState = {
allDashboards: [],
currentDashboard: dashboardGitResponse[0].path,
customDashboardBasePath,
};
- expect(selectedDashboard(state, localGetters(state))).toEqual(null);
+ expect(selectedDashboard(localState, localGetters(localState))).toEqual(null);
});
});
describe('linksWithMetadata', () => {
- let state;
const setupState = (initState = {}) => {
state = {
...state,
diff --git a/spec/frontend/monitoring/store/mutations_spec.js b/spec/frontend/monitoring/store/mutations_spec.js
index 14b38d79aa2..8d1351fc909 100644
--- a/spec/frontend/monitoring/store/mutations_spec.js
+++ b/spec/frontend/monitoring/store/mutations_spec.js
@@ -4,8 +4,8 @@ import mutations from '~/monitoring/stores/mutations';
import * as types from '~/monitoring/stores/mutation_types';
import state from '~/monitoring/stores/state';
import { dashboardEmptyStates, metricStates } from '~/monitoring/constants';
-
import { deploymentData, dashboardGitResponse, storeTextVariables } from '../mock_data';
+import { prometheusMatrixMultiResult } from '../graph_data';
import { metricsDashboardPayload } from '../fixture_data';
describe('Monitoring mutations', () => {
@@ -259,27 +259,6 @@ describe('Monitoring mutations', () => {
describe('Individual panel/metric results', () => {
const metricId = 'NO_DB_response_metrics_nginx_ingress_throughput_status_code';
- const data = {
- resultType: 'matrix',
- result: [
- {
- metric: {
- __name__: 'up',
- job: 'prometheus',
- instance: 'localhost:9090',
- },
- values: [[1435781430.781, '1'], [1435781445.781, '1'], [1435781460.781, '1']],
- },
- {
- metric: {
- __name__: 'up',
- job: 'node',
- instance: 'localhost:9091',
- },
- values: [[1435781430.781, '0'], [1435781445.781, '0'], [1435781460.781, '1']],
- },
- ],
- };
const dashboard = metricsDashboardPayload;
const getMetric = () => stateCopy.dashboard.panelGroups[1].panels[0].metrics[0];
@@ -307,6 +286,8 @@ describe('Monitoring mutations', () => {
});
it('adds results to the store', () => {
+ const data = prometheusMatrixMultiResult();
+
expect(getMetric().result).toBe(null);
mutations[types.RECEIVE_METRIC_RESULT_SUCCESS](stateCopy, {
@@ -488,4 +469,128 @@ describe('Monitoring mutations', () => {
});
});
});
+
+ describe('REQUEST_PANEL_PREVIEW', () => {
+ it('saves yml content and resets other preview data', () => {
+ const mockYmlContent = 'mock yml content';
+ mutations[types.REQUEST_PANEL_PREVIEW](stateCopy, mockYmlContent);
+
+ expect(stateCopy.panelPreviewIsLoading).toBe(true);
+ expect(stateCopy.panelPreviewYml).toBe(mockYmlContent);
+ expect(stateCopy.panelPreviewGraphData).toBe(null);
+ expect(stateCopy.panelPreviewError).toBe(null);
+ });
+ });
+
+ describe('RECEIVE_PANEL_PREVIEW_SUCCESS', () => {
+ it('saves graph data', () => {
+ mutations[types.RECEIVE_PANEL_PREVIEW_SUCCESS](stateCopy, {
+ title: 'My Title',
+ type: 'area-chart',
+ });
+
+ expect(stateCopy.panelPreviewIsLoading).toBe(false);
+ expect(stateCopy.panelPreviewGraphData).toMatchObject({
+ title: 'My Title',
+ type: 'area-chart',
+ });
+ expect(stateCopy.panelPreviewError).toBe(null);
+ });
+ });
+
+ describe('RECEIVE_PANEL_PREVIEW_FAILURE', () => {
+ it('saves graph data', () => {
+ mutations[types.RECEIVE_PANEL_PREVIEW_FAILURE](stateCopy, 'Error!');
+
+ expect(stateCopy.panelPreviewIsLoading).toBe(false);
+ expect(stateCopy.panelPreviewGraphData).toBe(null);
+ expect(stateCopy.panelPreviewError).toBe('Error!');
+ });
+ });
+
+ describe('panel preview metric', () => {
+ const getPreviewMetricAt = i => stateCopy.panelPreviewGraphData.metrics[i];
+
+ beforeEach(() => {
+ stateCopy.panelPreviewGraphData = {
+ title: 'Preview panel title',
+ metrics: [
+ {
+ query: 'query',
+ },
+ ],
+ };
+ });
+
+ describe('REQUEST_PANEL_PREVIEW_METRIC_RESULT', () => {
+ it('sets the metric to loading for the first time', () => {
+ mutations[types.REQUEST_PANEL_PREVIEW_METRIC_RESULT](stateCopy, { index: 0 });
+
+ expect(getPreviewMetricAt(0).loading).toBe(true);
+ expect(getPreviewMetricAt(0).state).toBe(metricStates.LOADING);
+ });
+
+ it('sets the metric to loading and keeps the result', () => {
+ getPreviewMetricAt(0).result = [[0, 1]];
+ getPreviewMetricAt(0).state = metricStates.OK;
+
+ mutations[types.REQUEST_PANEL_PREVIEW_METRIC_RESULT](stateCopy, { index: 0 });
+
+ expect(getPreviewMetricAt(0)).toMatchObject({
+ loading: true,
+ result: [[0, 1]],
+ state: metricStates.OK,
+ });
+ });
+ });
+
+ describe('RECEIVE_PANEL_PREVIEW_METRIC_RESULT_SUCCESS', () => {
+ it('saves the result in the metric', () => {
+ const data = prometheusMatrixMultiResult();
+
+ mutations[types.RECEIVE_PANEL_PREVIEW_METRIC_RESULT_SUCCESS](stateCopy, {
+ index: 0,
+ data,
+ });
+
+ expect(getPreviewMetricAt(0)).toMatchObject({
+ loading: false,
+ state: metricStates.OK,
+ result: expect.any(Array),
+ });
+ expect(getPreviewMetricAt(0).result).toHaveLength(data.result.length);
+ });
+ });
+
+ describe('RECEIVE_PANEL_PREVIEW_METRIC_RESULT_FAILURE', () => {
+ it('stores an error in the metric', () => {
+ mutations[types.RECEIVE_PANEL_PREVIEW_METRIC_RESULT_FAILURE](stateCopy, {
+ index: 0,
+ });
+
+ expect(getPreviewMetricAt(0).loading).toBe(false);
+ expect(getPreviewMetricAt(0).state).toBe(metricStates.UNKNOWN_ERROR);
+ expect(getPreviewMetricAt(0).result).toBe(null);
+
+ expect(getPreviewMetricAt(0)).toMatchObject({
+ loading: false,
+ result: null,
+ state: metricStates.UNKNOWN_ERROR,
+ });
+ });
+
+ it('stores a timeout error in a metric', () => {
+ mutations[types.RECEIVE_PANEL_PREVIEW_METRIC_RESULT_FAILURE](stateCopy, {
+ index: 0,
+ error: { message: 'BACKOFF_TIMEOUT' },
+ });
+
+ expect(getPreviewMetricAt(0)).toMatchObject({
+ loading: false,
+ result: null,
+ state: metricStates.TIMEOUT,
+ });
+ });
+ });
+ });
});