diff options
Diffstat (limited to 'spec/frontend/monitoring/components/charts/stacked_column_spec.js')
-rw-r--r-- | spec/frontend/monitoring/components/charts/stacked_column_spec.js | 193 |
1 files changed, 170 insertions, 23 deletions
diff --git a/spec/frontend/monitoring/components/charts/stacked_column_spec.js b/spec/frontend/monitoring/components/charts/stacked_column_spec.js index abb89ac15ef..bb2fbc68eaa 100644 --- a/spec/frontend/monitoring/components/charts/stacked_column_spec.js +++ b/spec/frontend/monitoring/components/charts/stacked_column_spec.js @@ -1,45 +1,192 @@ -import { shallowMount } from '@vue/test-utils'; -import { GlStackedColumnChart } from '@gitlab/ui/dist/charts'; +import { shallowMount, mount } from '@vue/test-utils'; +import timezoneMock from 'timezone-mock'; +import { cloneDeep } from 'lodash'; +import { GlStackedColumnChart, GlChartLegend } from '@gitlab/ui/dist/charts'; import StackedColumnChart from '~/monitoring/components/charts/stacked_column.vue'; import { stackedColumnMockedData } from '../../mock_data'; jest.mock('~/lib/utils/icon_utils', () => ({ - getSvgIconPathContent: jest.fn().mockResolvedValue('mockSvgPathContent'), + getSvgIconPathContent: jest.fn().mockImplementation(icon => Promise.resolve(`${icon}-content`)), })); describe('Stacked column chart component', () => { let wrapper; - const glStackedColumnChart = () => wrapper.find(GlStackedColumnChart); - beforeEach(() => { - wrapper = shallowMount(StackedColumnChart, { + const findChart = () => wrapper.find(GlStackedColumnChart); + const findLegend = () => wrapper.find(GlChartLegend); + + const createWrapper = (props = {}, mountingMethod = shallowMount) => + mountingMethod(StackedColumnChart, { propsData: { graphData: stackedColumnMockedData, + ...props, + }, + stubs: { + GlPopover: true, }, + attachToDocument: true, + }); + + beforeEach(() => { + wrapper = createWrapper({}, mount); + }); + + describe('when graphData is present', () => { + beforeEach(() => { + createWrapper(); + return wrapper.vm.$nextTick(); + }); + + it('chart is rendered', () => { + expect(findChart().exists()).toBe(true); + }); + + it('data should match the graphData y value for each series', () => { + const data = findChart().props('data'); + + data.forEach((series, index) => { + const { values } = stackedColumnMockedData.metrics[index].result[0]; + expect(series).toEqual(values.map(value => value[1])); + }); + }); + + it('series names should be the same as the graphData metrics labels', () => { + const seriesNames = findChart().props('seriesNames'); + + expect(seriesNames).toHaveLength(stackedColumnMockedData.metrics.length); + seriesNames.forEach((name, index) => { + expect(stackedColumnMockedData.metrics[index].label).toBe(name); + }); + }); + + it('group by should be the same as the graphData first metric results', () => { + const groupBy = findChart().props('groupBy'); + + expect(groupBy).toEqual([ + '2020-01-30T12:00:00.000Z', + '2020-01-30T12:01:00.000Z', + '2020-01-30T12:02:00.000Z', + ]); + }); + + it('chart options should configure data zoom and axis label ', () => { + const chartOptions = findChart().props('option'); + const xAxisType = findChart().props('xAxisType'); + + expect(chartOptions).toMatchObject({ + dataZoom: [{ handleIcon: 'path://scroll-handle-content' }], + xAxis: { + axisLabel: { formatter: expect.any(Function) }, + }, + }); + + expect(xAxisType).toBe('category'); + }); + + it('chart options should configure category as x axis type', () => { + const chartOptions = findChart().props('option'); + const xAxisType = findChart().props('xAxisType'); + + expect(chartOptions).toMatchObject({ + xAxis: { + type: 'category', + }, + }); + expect(xAxisType).toBe('category'); + }); + + it('format date is correct', () => { + const { xAxis } = findChart().props('option'); + expect(xAxis.axisLabel.formatter('2020-01-30T12:01:00.000Z')).toBe('12:01 PM'); + }); + + describe('when in PT timezone', () => { + beforeAll(() => { + timezoneMock.register('US/Pacific'); + }); + + afterAll(() => { + timezoneMock.unregister(); + }); + + it('date is shown in local time', () => { + const { xAxis } = findChart().props('option'); + expect(xAxis.axisLabel.formatter('2020-01-30T12:01:00.000Z')).toBe('4:01 AM'); + }); + + it('date is shown in UTC', () => { + wrapper.setProps({ timezone: 'UTC' }); + + return wrapper.vm.$nextTick().then(() => { + const { xAxis } = findChart().props('option'); + expect(xAxis.axisLabel.formatter('2020-01-30T12:01:00.000Z')).toBe('12:01 PM'); + }); + }); }); }); - afterEach(() => { - wrapper.destroy(); + describe('when graphData has results missing', () => { + beforeEach(() => { + const graphData = cloneDeep(stackedColumnMockedData); + + graphData.metrics[0].result = null; + + createWrapper({ graphData }); + return wrapper.vm.$nextTick(); + }); + + it('chart is rendered', () => { + expect(findChart().exists()).toBe(true); + }); }); - describe('with graphData present', () => { - it('is a Vue instance', () => { - expect(glStackedColumnChart().exists()).toBe(true); + describe('legend', () => { + beforeEach(() => { + wrapper = createWrapper({}, mount); + }); + + it('allows user to override legend label texts using props', () => { + const legendRelatedProps = { + legendMinText: 'legendMinText', + legendMaxText: 'legendMaxText', + legendAverageText: 'legendAverageText', + legendCurrentText: 'legendCurrentText', + }; + wrapper.setProps({ + ...legendRelatedProps, + }); + + return wrapper.vm.$nextTick().then(() => { + expect(findChart().props()).toMatchObject(legendRelatedProps); + }); }); - it('should contain the same number of elements in the seriesNames computed prop as the graphData metrics prop', () => - wrapper.vm - .$nextTick() - .then(expect(wrapper.vm.seriesNames).toHaveLength(stackedColumnMockedData.metrics.length))); + it('should render a tabular legend layout by default', () => { + expect(findLegend().props('layout')).toBe('table'); + }); + + describe('when inline legend layout prop is set', () => { + beforeEach(() => { + wrapper.setProps({ + legendLayout: 'inline', + }); + }); + + it('should render an inline legend layout', () => { + expect(findLegend().props('layout')).toBe('inline'); + }); + }); + + describe('when table legend layout prop is set', () => { + beforeEach(() => { + wrapper.setProps({ + legendLayout: 'table', + }); + }); - it('should contain the same number of elements in the groupBy computed prop as the graphData result prop', () => - wrapper.vm - .$nextTick() - .then( - expect(wrapper.vm.groupBy).toHaveLength( - stackedColumnMockedData.metrics[0].result[0].values.length, - ), - )); + it('should render a tabular legend layout', () => { + expect(findLegend().props('layout')).toBe('table'); + }); + }); }); }); |