text: import merge from 'lodash/merge';
  import Breakpoints from '../breakpoints';
  import { columnOptions } from '../constants';
  import { hexToRgba } from '../utils';
  import {
    getDataZoomConfig,
    getThresholdConfig,
    mergeSeriesToOptions,
    parseAnnotations,
    generateBarSeries,
    generateLineSeries,
  } from './config';
  import {
    mockDefaultDataZoomConfig,
    mockDefaultChartOptions,
    mockDefaultStackedBarData,
    mockDefaultLineData,
  } from './mock_data';
  import { colorFromDefaultPalette } from './theme';
  
  describe('chart config helpers', () => {
    describe('getThresholdConfig', () => {
      const makeThreshold = (threshold, operator) => [
        {
          threshold,
          operator,
        },
      ];
  
      it('returns empty object for no thresholds', () => {
        expect(getThresholdConfig([])).toEqual({});
      });
  
      it('draws area below line for < threshold', () => {
        const threshold = 3;
        const thresholds = makeThreshold(threshold, '<');
        const expectedLineData = [{ yAxis: threshold }];
        const expectedAreaData = [[{ yAxis: Number.NEGATIVE_INFINITY }, { yAxis: threshold }]];
  
        const { markLine, markArea } = getThresholdConfig(thresholds);
  
        expect(markLine.data).toEqual(expectedLineData);
        expect(markArea.data).toEqual(expectedAreaData);
      });
  
      it('draws line only for = threshold', () => {
        const threshold = 7;
        const thresholds = makeThreshold(threshold, '=');
        const expectedLineData = [{ yAxis: threshold }];
        const expectedAreaData = [];
  
        const { markLine, markArea } = getThresholdConfig(thresholds);
  
        expect(markLine.data).toEqual(expectedLineData);
        expect(markArea.data).toEqual(expectedAreaData);
      });
  
      it('draws area above line for > threshold', () => {
        const threshold = 9000;
        const thresholds = makeThreshold(threshold, '>');
        const expectedLineData = [{ yAxis: threshold }];
        const expectedAreaData = [[{ yAxis: threshold }, { yAxis: Infinity }]];
  
        const { markLine, markArea } = getThresholdConfig(thresholds);
  
        expect(markLine.data).toEqual(expectedLineData);
        expect(markArea.data).toEqual(expectedAreaData);
      });
    });
  
    describe('parseAnnotations', () => {
      const makeAnnotation = ({ min, max }) => [
        {
          min,
          max,
        },
      ];
  
      it('returns empty object for no annotations', () => {
        expect(parseAnnotations([])).toEqual({
          areas: [],
          lines: [],
          points: [],
        });
      });
  
      it('draws an annotation range between two fixed points', () => {
        const annotation = makeAnnotation({
          min: 10,
          max: 40,
        });
        const expectedLineData = [];
        const expectedAreaData = [[{ xAxis: 10 }, { xAxis: 40 }]];
  
        const { lines, areas } = parseAnnotations(annotation);
  
        expect(lines).toEqual(expectedLineData);
        expect(areas).toEqual(expectedAreaData);
      });
  
      it('draws an annotation range with infinity upper bound', () => {
        const annotation = makeAnnotation({
          min: 10,
          max: Infinity,
        });
        const expectedLineData = [];
        const expectedAreaData = [[{ xAxis: 10 }, { xAxis: Infinity }]];
  
        const { lines, areas } = parseAnnotations(annotation);
  
        expect(lines).toEqual(expectedLineData);
        expect(areas).toEqual(expectedAreaData);
      });
  
      it('draws an annotation range with infinity lower bound', () => {
        const annotation = makeAnnotation({
          min: Number.NEGATIVE_INFINITY,
          max: 10,
        });
        const expectedLineData = [];
        const expectedAreaData = [[{ xAxis: -Infinity }, { xAxis: 10 }]];
  
        const { lines, areas } = parseAnnotations(annotation);
  
        expect(lines).toEqual(expectedLineData);
        expect(areas).toEqual(expectedAreaData);
      });
  
      it('draws an annotation range without upper bound', () => {
        const annotation = makeAnnotation({
          min: 10,
        });
        const expectedLineData = [];
        const expectedAreaData = [[{ xAxis: 10 }, { xAxis: undefined }]];
  
        const { lines, areas } = parseAnnotations(annotation);
  
        expect(lines).toEqual(expectedLineData);
        expect(areas).toEqual(expectedAreaData);
      });
  
      it('draws an annotation range without lower bound', () => {
        const annotation = makeAnnotation({
          max: 10,
        });
        const expectedLineData = [];
        const expectedAreaData = [[{ xAxis: undefined }, { xAxis: 10 }]];
  
        const { lines, areas } = parseAnnotations(annotation);
  
        expect(lines).toEqual(expectedLineData);
        expect(areas).toEqual(expectedAreaData);
      });
  
      it('draws an annotation line', () => {
        const annotation = makeAnnotation({
          min: 10,
          max: 10,
        });
        const expectedLineData = [{ xAxis: 10 }];
        const expectedAreaData = [];
  
        const { lines, areas } = parseAnnotations(annotation);
  
        expect(lines).toEqual(expectedLineData);
        expect(areas).toEqual(expectedAreaData);
      });
  
      it('draws multiple annotation lines', () => {
        const annotation1 = makeAnnotation({
          min: 10,
          max: 10,
        });
        const annotation2 = makeAnnotation({
          min: 30,
          max: 30,
        });
        const expectedLineData = [{ xAxis: 10 }, { xAxis: 30 }];
        const expectedAreaData = [];
  
        const { lines, areas } = parseAnnotations([...annotation1, ...annotation2]);
  
        expect(lines).toEqual(expectedLineData);
        expect(areas).toEqual(expectedAreaData);
      });
    });
  
    describe('getDataZoomConfig', () => {
      describe('on large viewports (lg, xl)', () => {
        it('creates a basic dataZoomConfig with inside scrolling being disabled', () => {
          const actual = getDataZoomConfig();
          const expected = mockDefaultDataZoomConfig;
  
          expect(actual).toEqual(expected);
        });
      });
  
      describe('on small viewports', () => {
        it('creates a basic dataZoomConfig with inside scrolling being enabled', () => {
          jest.spyOn(Breakpoints, 'getBreakpointSize').mockImplementationOnce(() => 'sm');
          const actual = getDataZoomConfig();
          const dataZoomWithInsideEnabled = [
            {
              bottom: 22,
              filterMode: 'none',
              minSpan: 0.01,
              type: 'slider',
            },
            {
              type: 'inside',
              filterMode: 'none',
              minSpan: 0.01,
              disabled: false,
            },
          ];
          const expected = merge(mockDefaultDataZoomConfig, {
            dataZoom: dataZoomWithInsideEnabled,
          });
  
          expect(actual).toEqual(expected);
        });
      });
  
      it('allows the filterMode to be set', () => {
        const actual = getDataZoomConfig({ filterMode: 'filter' });
        // After https://gitlab.com/gitlab-org/gitlab-ui/issues/240
        // all default dataZoom configs will have slider & inside.
        // inside is specifically to enable touch zoom for mobile devices
        const dataZoomWithFilter = [
          {
            type: 'slider',
            filterMode: 'filter',
            minSpan: null,
          },
          {
            type: 'inside',
            filterMode: 'filter',
            minSpan: null,
            disabled: true,
          },
        ];
        const expected = merge(mockDefaultDataZoomConfig, {
          dataZoom: dataZoomWithFilter,
        });
  
        expect(actual).toEqual(expected);
      });
    });
  
    describe('mergeSeriesToOptions', () => {
      const series = {
        areaStyle: {
          opacity: 0.2,
          color: '#1f78d1',
        },
        showSymbol: false,
        lineStyle: {
          color: '#1f78d1',
        },
        itemStyle: {
          color: '#1f78d1',
        },
        symbol: 'circle',
        type: 'line',
        width: 2,
        name: 'Values',
        data: [
          [0, 5],
          [4, 3],
          [8, 10],
        ],
      };
  
      it('create chart options with invalid series props', () => {
        const chartOptionsOutput = {
          ...mockDefaultChartOptions,
          series: [],
        };
        expect(mergeSeriesToOptions(mockDefaultChartOptions)).toEqual(chartOptionsOutput);
        expect(mergeSeriesToOptions(mockDefaultChartOptions, [])).toEqual(chartOptionsOutput);
      });
  
      it('creates chart options with single series object passed as data prop', () => {
        // data for chart can also be passed as a data prop which is transformed to series
        const chartOptions = mergeSeriesToOptions({
          ...mockDefaultChartOptions,
          series,
        });
  
        expect(chartOptions.series).toBeInstanceOf(Array);
        expect(chartOptions.series.length).toBe(1);
      });
  
      it('creates chart options with single series array passed as data prop', () => {
        const chartOptions = mergeSeriesToOptions({
          ...mockDefaultChartOptions,
          series: [series],
        });
  
        expect(chartOptions.series).toBeInstanceOf(Array);
        expect(chartOptions.series.length).toBe(1);
      });
  
      it('creates chart options with multiple series array passed as data prop', () => {
        const chartOptions = mergeSeriesToOptions({
          ...mockDefaultChartOptions,
          series: [series, series],
        });
  
        expect(chartOptions.series).toBeInstanceOf(Array);
        expect(chartOptions.series.length).toBe(2);
      });
  
      it('creates chart options with single series object passed as series prop', () => {
        const chartOptions = mergeSeriesToOptions(mockDefaultChartOptions, series);
  
        expect(chartOptions.series).toBeInstanceOf(Array);
        expect(chartOptions.series.length).toBe(1);
      });
  
      it('creates chart options with single series array passed as series prop', () => {
        const chartOptions = mergeSeriesToOptions(mockDefaultChartOptions, [series]);
  
        expect(chartOptions.series).toBeInstanceOf(Array);
        expect(chartOptions.series.length).toBe(1);
      });
  
      it('creates chart options with multiple series array passed as series prop', () => {
        const chartOptions = mergeSeriesToOptions(mockDefaultChartOptions, [series, series]);
  
        expect(chartOptions.series).toBeInstanceOf(Array);
        expect(chartOptions.series.length).toBe(2);
      });
    });
  
    describe('generateBarSeries', () => {
      const defaultBarColors = {
        itemStyle: { color: hexToRgba(colorFromDefaultPalette(1), 0.2) },
        emphasis: { itemStyle: { color: hexToRgba(colorFromDefaultPalette(1), 0.4) } },
      };
      const barDefaultParams = {
        name: 'Bar chart',
        color: colorFromDefaultPalette(0),
        stack: columnOptions.stacked,
      };
  
      it.each`
        param           | value                         | result
        ${'name'}       | ${'Cool new bar chart'}       | ${{ name: 'Cool new bar chart' }}
        ${'color'}      | ${colorFromDefaultPalette(1)} | ${defaultBarColors}
        ${'data'}       | ${mockDefaultStackedBarData}  | ${{ data: mockDefaultStackedBarData }}
        ${'stack'}      | ${columnOptions.tiled}        | ${{ stack: columnOptions.tiled }}
        ${'yAxisIndex'} | ${3}                          | ${{ yAxisIndex: 3 }}
      `('with $param set will contain $result', ({ param, value, result }) => {
        expect(
          generateBarSeries({
            ...barDefaultParams,
            [param]: value,
          })
        ).toMatchObject(result);
      });
    });
    describe('generateLineSeries', () => {
      const defaultLineColors = {
        itemStyle: { color: colorFromDefaultPalette(1) },
        lineStyle: { color: colorFromDefaultPalette(1) },
      };
      const lineDefaultParams = { name: 'Line chart', color: colorFromDefaultPalette(0) };
  
      it.each`
        param           | value                         | result
        ${'name'}       | ${'Cool new line chart'}      | ${{ name: 'Cool new line chart' }}
        ${'color'}      | ${colorFromDefaultPalette(1)} | ${defaultLineColors}
        ${'data'}       | ${mockDefaultLineData}        | ${{ data: mockDefaultLineData }}
        ${'yAxisIndex'} | ${2}                          | ${{ yAxisIndex: 2 }}
      `('with $param set will contain $result', ({ param, value, result }) => {
        expect(
          generateLineSeries({
            ...lineDefaultParams,
            [param]: value,
          })
        ).toMatchObject(result);
      });
    });
  });
  