2020-05-05 21:59:32 +02:00
|
|
|
/*
|
|
|
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
2021-02-04 03:12:39 +01:00
|
|
|
* or more contributor license agreements. Licensed under the Elastic License
|
|
|
|
* 2.0; you may not use this file except in compliance with the Elastic License
|
|
|
|
* 2.0.
|
2020-05-05 21:59:32 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
import React from 'react';
|
2020-11-04 11:27:52 +01:00
|
|
|
import {
|
2021-02-11 09:18:48 +01:00
|
|
|
Partition,
|
|
|
|
SeriesIdentifier,
|
|
|
|
Settings,
|
2020-11-04 11:27:52 +01:00
|
|
|
NodeColorAccessor,
|
|
|
|
ShapeTreeNode,
|
2021-02-11 09:18:48 +01:00
|
|
|
HierarchyOfArrays,
|
|
|
|
} from '@elastic/charts';
|
2020-05-05 21:59:32 +02:00
|
|
|
import { shallow } from 'enzyme';
|
|
|
|
import { LensMultiTable } from '../types';
|
|
|
|
import { PieComponent } from './render_function';
|
|
|
|
import { PieExpressionArgs } from './types';
|
2020-05-13 14:49:50 +02:00
|
|
|
import { EmptyPlaceholder } from '../shared_components';
|
2020-07-02 16:02:30 +02:00
|
|
|
import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks';
|
2020-09-15 11:24:02 +02:00
|
|
|
import { LensIconChartDonut } from '../assets/chart_donut';
|
2020-07-02 16:02:30 +02:00
|
|
|
|
|
|
|
const chartsThemeService = chartPluginMock.createSetupContract().theme;
|
2020-05-05 21:59:32 +02:00
|
|
|
|
|
|
|
describe('PieVisualization component', () => {
|
|
|
|
let getFormatSpy: jest.Mock;
|
|
|
|
let convertSpy: jest.Mock;
|
|
|
|
|
|
|
|
beforeEach(() => {
|
2020-05-22 09:08:58 +02:00
|
|
|
convertSpy = jest.fn((x) => x);
|
2020-05-05 21:59:32 +02:00
|
|
|
getFormatSpy = jest.fn();
|
|
|
|
getFormatSpy.mockReturnValue({ convert: convertSpy });
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('legend options', () => {
|
|
|
|
const data: LensMultiTable = {
|
|
|
|
type: 'lens_multitable',
|
|
|
|
tables: {
|
|
|
|
first: {
|
2020-10-16 18:46:51 +02:00
|
|
|
type: 'datatable',
|
2020-05-05 21:59:32 +02:00
|
|
|
columns: [
|
2020-10-16 18:46:51 +02:00
|
|
|
{ id: 'a', name: 'a', meta: { type: 'number' } },
|
|
|
|
{ id: 'b', name: 'b', meta: { type: 'number' } },
|
|
|
|
{ id: 'c', name: 'c', meta: { type: 'string' } },
|
2020-05-05 21:59:32 +02:00
|
|
|
],
|
|
|
|
rows: [
|
|
|
|
{ a: 6, b: 2, c: 'I', d: 'Row 1' },
|
|
|
|
{ a: 1, b: 5, c: 'J', d: 'Row 2' },
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const args: PieExpressionArgs = {
|
|
|
|
shape: 'pie',
|
|
|
|
groups: ['a', 'b'],
|
|
|
|
metric: 'c',
|
|
|
|
numberDisplay: 'hidden',
|
|
|
|
categoryDisplay: 'default',
|
|
|
|
legendDisplay: 'default',
|
|
|
|
nestedLegend: false,
|
|
|
|
percentDecimals: 3,
|
|
|
|
hideLabels: false,
|
2020-11-04 11:27:52 +01:00
|
|
|
palette: { name: 'mock', type: 'palette' },
|
2020-05-05 21:59:32 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
function getDefaultArgs() {
|
|
|
|
return {
|
|
|
|
data,
|
|
|
|
formatFactory: getFormatSpy,
|
2020-05-15 12:01:27 +02:00
|
|
|
onClickValue: jest.fn(),
|
2020-07-02 16:02:30 +02:00
|
|
|
chartsThemeService,
|
2020-11-04 11:27:52 +01:00
|
|
|
paletteService: chartPluginMock.createPaletteRegistry(),
|
2020-11-24 18:42:02 +01:00
|
|
|
renderMode: 'display' as const,
|
2020-12-22 17:35:27 +01:00
|
|
|
syncColors: false,
|
2020-05-05 21:59:32 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-07-22 12:14:59 +02:00
|
|
|
test('it shows legend on correct side', () => {
|
|
|
|
const component = shallow(
|
|
|
|
<PieComponent args={{ ...args, legendPosition: 'top' }} {...getDefaultArgs()} />
|
|
|
|
);
|
|
|
|
expect(component.find(Settings).prop('legendPosition')).toEqual('top');
|
|
|
|
});
|
|
|
|
|
2020-05-05 21:59:32 +02:00
|
|
|
test('it shows legend for 2 groups using default legendDisplay', () => {
|
|
|
|
const component = shallow(<PieComponent args={args} {...getDefaultArgs()} />);
|
|
|
|
expect(component.find(Settings).prop('showLegend')).toEqual(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('it hides legend for 1 group using default legendDisplay', () => {
|
|
|
|
const component = shallow(
|
|
|
|
<PieComponent args={{ ...args, groups: ['a'] }} {...getDefaultArgs()} />
|
|
|
|
);
|
|
|
|
expect(component.find(Settings).prop('showLegend')).toEqual(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('it hides legend that would show otherwise in preview mode', () => {
|
|
|
|
const component = shallow(
|
|
|
|
<PieComponent args={{ ...args, hideLabels: true }} {...getDefaultArgs()} />
|
|
|
|
);
|
|
|
|
expect(component.find(Settings).prop('showLegend')).toEqual(false);
|
|
|
|
});
|
|
|
|
|
2020-11-04 11:27:52 +01:00
|
|
|
test('it calls the color function with the right series layers', () => {
|
|
|
|
const defaultArgs = getDefaultArgs();
|
|
|
|
const component = shallow(
|
|
|
|
<PieComponent
|
|
|
|
args={args}
|
|
|
|
{...defaultArgs}
|
|
|
|
data={{
|
|
|
|
...data,
|
|
|
|
tables: {
|
|
|
|
first: {
|
|
|
|
...data.tables.first,
|
|
|
|
rows: [
|
|
|
|
{ a: 'empty', b: 'first', c: 1, d: 'Row 1' },
|
|
|
|
{ a: 'css', b: 'first', c: 1, d: 'Row 1' },
|
|
|
|
{ a: 'css', b: 'second', c: 1, d: 'Row 1' },
|
|
|
|
{ a: 'css', b: 'third', c: 1, d: 'Row 1' },
|
|
|
|
{ a: 'gz', b: 'first', c: 1, d: 'Row 1' },
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
|
|
|
|
(component.find(Partition).prop('layers')![1].shape!.fillColor as NodeColorAccessor)(
|
|
|
|
({
|
|
|
|
dataName: 'third',
|
|
|
|
depth: 2,
|
|
|
|
parent: {
|
|
|
|
children: [
|
|
|
|
['first', {}],
|
|
|
|
['second', {}],
|
|
|
|
['third', {}],
|
|
|
|
],
|
|
|
|
depth: 1,
|
|
|
|
value: 200,
|
|
|
|
dataName: 'css',
|
|
|
|
parent: {
|
|
|
|
children: [
|
|
|
|
['empty', {}],
|
|
|
|
['css', {}],
|
|
|
|
['gz', {}],
|
|
|
|
],
|
|
|
|
depth: 0,
|
|
|
|
sortIndex: 0,
|
|
|
|
value: 500,
|
|
|
|
},
|
|
|
|
sortIndex: 1,
|
|
|
|
},
|
|
|
|
value: 41,
|
|
|
|
sortIndex: 2,
|
|
|
|
} as unknown) as ShapeTreeNode,
|
|
|
|
0,
|
|
|
|
[] as HierarchyOfArrays
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(defaultArgs.paletteService.get('mock').getColor).toHaveBeenCalledWith(
|
|
|
|
[
|
|
|
|
{
|
|
|
|
name: 'css',
|
|
|
|
rankAtDepth: 1,
|
|
|
|
totalSeriesAtDepth: 3,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'third',
|
|
|
|
rankAtDepth: 2,
|
|
|
|
totalSeriesAtDepth: 3,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
{
|
|
|
|
maxDepth: 2,
|
|
|
|
totalSeries: 5,
|
2020-12-22 17:35:27 +01:00
|
|
|
syncColors: false,
|
2020-11-04 11:27:52 +01:00
|
|
|
behindText: true,
|
|
|
|
},
|
|
|
|
undefined
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2020-05-05 21:59:32 +02:00
|
|
|
test('it hides legend with 2 groups for treemap', () => {
|
|
|
|
const component = shallow(
|
|
|
|
<PieComponent args={{ ...args, shape: 'treemap' }} {...getDefaultArgs()} />
|
|
|
|
);
|
|
|
|
expect(component.find(Settings).prop('showLegend')).toEqual(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('it shows treemap legend only when forced on', () => {
|
|
|
|
const component = shallow(
|
|
|
|
<PieComponent
|
|
|
|
args={{ ...args, legendDisplay: 'show', shape: 'treemap' }}
|
|
|
|
{...getDefaultArgs()}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
expect(component.find(Settings).prop('showLegend')).toEqual(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('it defaults to 1-level legend depth', () => {
|
|
|
|
const component = shallow(<PieComponent args={args} {...getDefaultArgs()} />);
|
|
|
|
expect(component.find(Settings).prop('legendMaxDepth')).toEqual(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('it shows nested legend only when forced on', () => {
|
|
|
|
const component = shallow(
|
|
|
|
<PieComponent args={{ ...args, nestedLegend: true }} {...getDefaultArgs()} />
|
|
|
|
);
|
|
|
|
expect(component.find(Settings).prop('legendMaxDepth')).toBeUndefined();
|
|
|
|
});
|
2020-05-13 14:49:50 +02:00
|
|
|
|
2020-05-15 12:01:27 +02:00
|
|
|
test('it calls filter callback with the given context', () => {
|
|
|
|
const defaultArgs = getDefaultArgs();
|
|
|
|
const component = shallow(<PieComponent args={{ ...args }} {...defaultArgs} />);
|
2020-05-22 09:08:58 +02:00
|
|
|
component.find(Settings).first().prop('onElementClick')!([
|
2021-02-11 09:18:48 +01:00
|
|
|
[
|
|
|
|
[{ groupByRollup: 6, value: 6, depth: 1, path: [], sortIndex: 1 }],
|
|
|
|
{} as SeriesIdentifier,
|
|
|
|
],
|
2020-05-22 09:08:58 +02:00
|
|
|
]);
|
2020-05-15 12:01:27 +02:00
|
|
|
|
|
|
|
expect(defaultArgs.onClickValue.mock.calls[0][0]).toMatchInlineSnapshot(`
|
|
|
|
Object {
|
|
|
|
"data": Array [
|
|
|
|
Object {
|
|
|
|
"column": 0,
|
|
|
|
"row": 0,
|
|
|
|
"table": Object {
|
|
|
|
"columns": Array [
|
|
|
|
Object {
|
|
|
|
"id": "a",
|
2020-10-16 18:46:51 +02:00
|
|
|
"meta": Object {
|
|
|
|
"type": "number",
|
|
|
|
},
|
2020-05-15 12:01:27 +02:00
|
|
|
"name": "a",
|
|
|
|
},
|
|
|
|
Object {
|
|
|
|
"id": "b",
|
2020-10-16 18:46:51 +02:00
|
|
|
"meta": Object {
|
|
|
|
"type": "number",
|
|
|
|
},
|
2020-05-15 12:01:27 +02:00
|
|
|
"name": "b",
|
|
|
|
},
|
|
|
|
Object {
|
|
|
|
"id": "c",
|
2020-10-16 18:46:51 +02:00
|
|
|
"meta": Object {
|
|
|
|
"type": "string",
|
|
|
|
},
|
2020-05-15 12:01:27 +02:00
|
|
|
"name": "c",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
"rows": Array [
|
|
|
|
Object {
|
|
|
|
"a": 6,
|
|
|
|
"b": 2,
|
|
|
|
"c": "I",
|
|
|
|
"d": "Row 1",
|
|
|
|
},
|
|
|
|
Object {
|
|
|
|
"a": 1,
|
|
|
|
"b": 5,
|
|
|
|
"c": "J",
|
|
|
|
"d": "Row 2",
|
|
|
|
},
|
|
|
|
],
|
2020-10-16 18:46:51 +02:00
|
|
|
"type": "datatable",
|
2020-05-15 12:01:27 +02:00
|
|
|
},
|
|
|
|
"value": 6,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
}
|
|
|
|
`);
|
|
|
|
});
|
|
|
|
|
2020-11-24 18:42:02 +01:00
|
|
|
test('does not set click listener on noInteractivity render mode', () => {
|
|
|
|
const defaultArgs = getDefaultArgs();
|
|
|
|
const component = shallow(
|
|
|
|
<PieComponent args={{ ...args }} {...defaultArgs} renderMode="noInteractivity" />
|
|
|
|
);
|
|
|
|
expect(component.find(Settings).first().prop('onElementClick')).toBeUndefined();
|
|
|
|
});
|
|
|
|
|
2020-05-13 14:49:50 +02:00
|
|
|
test('it shows emptyPlaceholder for undefined grouped data', () => {
|
|
|
|
const defaultData = getDefaultArgs().data;
|
|
|
|
const emptyData: LensMultiTable = {
|
|
|
|
...defaultData,
|
|
|
|
tables: {
|
|
|
|
first: {
|
|
|
|
...defaultData.tables.first,
|
|
|
|
rows: [
|
|
|
|
{ a: undefined, b: undefined, c: 'I', d: 'Row 1' },
|
|
|
|
{ a: undefined, b: undefined, c: 'J', d: 'Row 2' },
|
|
|
|
],
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const component = shallow(
|
|
|
|
<PieComponent args={args} {...getDefaultArgs()} data={emptyData} />
|
|
|
|
);
|
2020-09-15 11:24:02 +02:00
|
|
|
expect(component.find(EmptyPlaceholder).prop('icon')).toEqual(LensIconChartDonut);
|
2020-05-13 14:49:50 +02:00
|
|
|
});
|
2020-05-05 21:59:32 +02:00
|
|
|
});
|
|
|
|
});
|