text: 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);
        });
      });
    });
  });
  