import _ from 'lodash'; import { metricStates } from '~/monitoring/constants'; import * as getters from '~/monitoring/stores/getters'; import * as types from '~/monitoring/stores/mutation_types'; import mutations from '~/monitoring/stores/mutations'; import { metricsDashboardPayload } from '../fixture_data'; import { customDashboardBasePath, environmentData, metricsResult, dashboardGitResponse, storeVariables, mockLinks, } from '../mock_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 getMetricStates; beforeEach(() => { setupState = (initState = {}) => { state = initState; getMetricStates = getters.getMetricStates(state); }; }); it('has method-style access', () => { setupState(); expect(getMetricStates).toEqual(expect.any(Function)); }); it('when dashboard has no panel groups, returns empty', () => { setupState({ dashboard: { panelGroups: [], }, }); expect(getMetricStates()).toEqual([]); }); describe('when the dashboard is set', () => { let groups; beforeEach(() => { setupState({ dashboard: { panelGroups: [] }, }); mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload); groups = state.dashboard.panelGroups; }); it('no loaded metric returns empty', () => { expect(getMetricStates()).toEqual([]); }); it('on an empty metric with no result, returns NO_DATA', () => { mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload); setMetricSuccess({ group: 2, result: [] }); expect(getMetricStates()).toEqual([metricStates.NO_DATA]); }); it('on a metric with a result, returns OK', () => { mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload); setMetricSuccess({ group: 1 }); expect(getMetricStates()).toEqual([metricStates.OK]); }); it('on a metric with an error, returns an error', () => { mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload); setMetricFailure({}); expect(getMetricStates()).toEqual([metricStates.UNKNOWN_ERROR]); }); it('on multiple metrics with results, returns OK', () => { mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload); setMetricSuccess({ group: 1 }); setMetricSuccess({ group: 1, panel: 1 }); expect(getMetricStates()).toEqual([metricStates.OK]); // Filtered by groups expect(getMetricStates(state.dashboard.panelGroups[1].key)).toEqual([metricStates.OK]); expect(getMetricStates(state.dashboard.panelGroups[2].key)).toEqual([]); }); it('on multiple metrics errors', () => { mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload); setMetricFailure({}); setMetricFailure({ group: 1 }); // Entire dashboard fails expect(getMetricStates()).toEqual([metricStates.UNKNOWN_ERROR]); expect(getMetricStates(groups[0].key)).toEqual([metricStates.UNKNOWN_ERROR]); expect(getMetricStates(groups[1].key)).toEqual([metricStates.UNKNOWN_ERROR]); }); it('on multiple metrics with errors', () => { mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload); // An success in 1 group setMetricSuccess({ group: 1 }); // An error in 2 groups setMetricFailure({ group: 1, panel: 1 }); setMetricFailure({ group: 2, panel: 0 }); expect(getMetricStates()).toEqual([metricStates.OK, metricStates.UNKNOWN_ERROR]); expect(getMetricStates(groups[1].key)).toEqual([ metricStates.OK, metricStates.UNKNOWN_ERROR, ]); expect(getMetricStates(groups[2].key)).toEqual([metricStates.UNKNOWN_ERROR]); }); }); }); describe('metricsWithData', () => { let metricsWithData; let setupState; beforeEach(() => { setupState = (initState = {}) => { state = initState; metricsWithData = getters.metricsWithData(state); }; }); afterEach(() => { state = null; }); it('has method-style access', () => { setupState(); expect(metricsWithData).toEqual(expect.any(Function)); }); it('when dashboard has no panel groups, returns empty', () => { setupState({ dashboard: { panelGroups: [], }, }); expect(metricsWithData()).toEqual([]); }); describe('when the dashboard is set', () => { beforeEach(() => { setupState({ dashboard: { panelGroups: [] }, }); }); it('no loaded metric returns empty', () => { mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload); expect(metricsWithData()).toEqual([]); }); it('an empty metric, returns empty', () => { mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload); setMetricSuccess({ result: [] }); expect(metricsWithData()).toEqual([]); }); it('a metric with results, it returns a metric', () => { mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload); setMetricSuccess(); expect(metricsWithData()).toEqual([getMetric().metricId]); }); it('multiple metrics with results, it return multiple metrics', () => { mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, metricsDashboardPayload); setMetricSuccess({ panel: 0 }); setMetricSuccess({ panel: 1 }); 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); setMetricSuccess({ group: 1 }); setMetricSuccess({ group: 1, panel: 1 }); // First group has metrics expect(metricsWithData(state.dashboard.panelGroups[1].key)).toEqual([ getMetric({ group: 1 }).metricId, getMetric({ group: 1, panel: 1 }).metricId, ]); // Second group has no metrics expect(metricsWithData(state.dashboard.panelGroups[2].key)).toEqual([]); }); }); }); describe('filteredEnvironments', () => { const setupState = (initState = {}) => { state = { ...state, ...initState, }; }; beforeAll(() => { setupState({ environments: environmentData, }); }); afterAll(() => { state = null; }); [ { input: '', output: 17, }, { input: ' ', output: 17, }, { input: null, output: 17, }, { input: 'does-not-exist', output: 0, }, { input: 'noop-branch-', output: 15, }, { input: 'noop-branch-9', output: 1, }, ].forEach(({ input, output }) => { it(`filteredEnvironments returns ${output} items for ${input}`, () => { setupState({ environmentsSearchTerm: input, }); expect(getters.filteredEnvironments(state).length).toBe(output); }); }); }); describe('metricsSavedToDb', () => { let metricsSavedToDb; let mockData; beforeEach(() => { mockData = _.cloneDeep(metricsDashboardPayload); state = { dashboard: { panelGroups: [], }, }; }); it('return no metrics when dashboard is not persisted', () => { mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, mockData); metricsSavedToDb = getters.metricsSavedToDb(state); expect(metricsSavedToDb).toEqual([]); }); it('return a metric id when one metric is persisted', () => { const id = 99; const [metric] = mockData.panel_groups[0].panels[0].metrics; metric.metric_id = id; mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, mockData); metricsSavedToDb = getters.metricsSavedToDb(state); expect(metricsSavedToDb).toEqual([`${id}_${metric.id}`]); }); it('return a metric id when two metrics are persisted', () => { const id1 = 101; const id2 = 102; const [metric1] = mockData.panel_groups[0].panels[0].metrics; const [metric2] = mockData.panel_groups[0].panels[1].metrics; // database persisted 2 metrics metric1.metric_id = id1; metric2.metric_id = id2; mutations[types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, mockData); metricsSavedToDb = getters.metricsSavedToDb(state); expect(metricsSavedToDb).toEqual([`${id1}_${metric1.id}`, `${id2}_${metric2.id}`]); }); }); describe('getCustomVariablesParams', () => { beforeEach(() => { state = { variables: {}, }; }); it('transforms the variables object to an array in the [variable, variable_value] format for all variable types', () => { state.variables = storeVariables; const variablesArray = getters.getCustomVariablesParams(state); expect(variablesArray).toEqual({ 'variables[textSimple]': 'My default value', 'variables[textAdvanced]': 'A default value', 'variables[customSimple]': 'value1', 'variables[customAdvanced]': 'value2', 'variables[customAdvancedWithoutLabel]': 'value2', 'variables[customAdvancedWithoutOptText]': 'value2', }); }); it('transforms the variables object to an empty array when no keys are present', () => { state.variables = []; const variablesArray = getters.getCustomVariablesParams(state); expect(variablesArray).toEqual({}); }); }); describe('selectedDashboard', () => { const { selectedDashboard } = getters; const localGetters = (localState) => ({ fullDashboardPath: getters.fullDashboardPath(localState), }); it('returns a dashboard', () => { const localState = { allDashboards: dashboardGitResponse, currentDashboard: dashboardGitResponse[0].path, customDashboardBasePath, }; expect(selectedDashboard(localState, localGetters(localState))).toEqual( dashboardGitResponse[0], ); }); it('returns a dashboard different from the overview dashboard', () => { const localState = { allDashboards: dashboardGitResponse, currentDashboard: dashboardGitResponse[1].path, customDashboardBasePath, }; expect(selectedDashboard(localState, localGetters(localState))).toEqual( dashboardGitResponse[1], ); }); it('returns the overview dashboard when no dashboard is selected', () => { const localState = { allDashboards: dashboardGitResponse, currentDashboard: null, customDashboardBasePath, }; expect(selectedDashboard(localState, localGetters(localState))).toEqual( dashboardGitResponse[0], ); }); it('returns the overview dashboard when dashboard cannot be found', () => { const localState = { allDashboards: dashboardGitResponse, currentDashboard: 'wrong_path', customDashboardBasePath, }; expect(selectedDashboard(localState, localGetters(localState))).toEqual( dashboardGitResponse[0], ); }); it('returns null when no dashboards are present', () => { const localState = { allDashboards: [], currentDashboard: dashboardGitResponse[0].path, customDashboardBasePath, }; expect(selectedDashboard(localState, localGetters(localState))).toEqual(null); }); }); describe('linksWithMetadata', () => { const setupState = (initState = {}) => { state = { ...state, ...initState, }; }; beforeAll(() => { setupState({ links: mockLinks, }); }); afterAll(() => { state = null; }); it.each` timeRange | output ${{}} | ${''} ${{ start: '2020-01-01T00:00:00.000Z', end: '2020-01-31T23:59:00.000Z' }} | ${'start=2020-01-01T00%3A00%3A00.000Z&end=2020-01-31T23%3A59%3A00.000Z'} ${{ duration: { seconds: 86400 } }} | ${'duration_seconds=86400'} `('linksWithMetadata returns URLs with time range', ({ timeRange, output }) => { setupState({ timeRange }); const links = getters.linksWithMetadata(state); links.forEach(({ url }) => { expect(url).toMatch(output); }); }); }); });