@pie-lib/charting 5.15.6 → 5.15.7-next.1618
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +1 -581
- package/CHANGELOG.md +206 -38
- package/NEXT.CHANGELOG.json +1 -0
- package/lib/actions-button.js +175 -0
- package/lib/actions-button.js.map +1 -0
- package/lib/axes.js +154 -104
- package/lib/axes.js.map +1 -1
- package/lib/bars/common/bars.js +105 -19
- package/lib/bars/common/bars.js.map +1 -1
- package/lib/bars/common/correct-check-icon.js +55 -0
- package/lib/bars/common/correct-check-icon.js.map +1 -0
- package/lib/chart-type.js +4 -4
- package/lib/chart-type.js.map +1 -1
- package/lib/chart.js +96 -65
- package/lib/chart.js.map +1 -1
- package/lib/common/correctness-indicators.js +99 -0
- package/lib/common/correctness-indicators.js.map +1 -0
- package/lib/common/drag-handle.js +47 -13
- package/lib/common/drag-handle.js.map +1 -1
- package/lib/common/drag-icon.js +7 -24
- package/lib/common/drag-icon.js.map +1 -1
- package/lib/grid.js +47 -10
- package/lib/grid.js.map +1 -1
- package/lib/index.js +8 -0
- package/lib/index.js.map +1 -1
- package/lib/key-legend.js +111 -0
- package/lib/key-legend.js.map +1 -0
- package/lib/line/common/drag-handle.js +40 -18
- package/lib/line/common/drag-handle.js.map +1 -1
- package/lib/line/common/line.js +7 -8
- package/lib/line/common/line.js.map +1 -1
- package/lib/line/line-cross.js +76 -9
- package/lib/line/line-cross.js.map +1 -1
- package/lib/line/line-dot.js +58 -5
- package/lib/line/line-dot.js.map +1 -1
- package/lib/mark-label.js +40 -15
- package/lib/mark-label.js.map +1 -1
- package/lib/plot/common/plot.js +129 -16
- package/lib/plot/common/plot.js.map +1 -1
- package/lib/plot/dot.js +17 -4
- package/lib/plot/dot.js.map +1 -1
- package/lib/plot/line.js +19 -6
- package/lib/plot/line.js.map +1 -1
- package/lib/tool-menu.js +0 -4
- package/lib/tool-menu.js.map +1 -1
- package/package.json +6 -8
- package/src/__tests__/__snapshots__/axes.test.jsx.snap +569 -0
- package/src/__tests__/__snapshots__/chart-type.test.jsx.snap +14 -0
- package/src/__tests__/__snapshots__/chart.test.jsx.snap +595 -0
- package/src/__tests__/__snapshots__/grid.test.jsx.snap +72 -0
- package/src/__tests__/__snapshots__/mark-label.test.jsx.snap +73 -0
- package/src/__tests__/axes.test.jsx +141 -0
- package/src/__tests__/chart-setup.test.jsx +47 -0
- package/src/__tests__/chart-type.test.jsx +29 -0
- package/src/__tests__/chart.test.jsx +95 -0
- package/src/__tests__/grid.test.jsx +25 -0
- package/src/__tests__/mark-label.test.jsx +31 -0
- package/src/__tests__/utils.js +30 -0
- package/src/__tests__/utils.test.js +100 -0
- package/src/actions-button.jsx +110 -0
- package/src/axes.jsx +98 -54
- package/src/bars/__tests__/__snapshots__/bar.test.jsx.snap +43 -0
- package/src/bars/__tests__/__snapshots__/histogram.test.jsx.snap +45 -0
- package/src/bars/__tests__/bar.test.jsx +37 -0
- package/src/bars/__tests__/histogram.test.jsx +38 -0
- package/src/bars/__tests__/utils.js +30 -0
- package/src/bars/common/__tests__/__snapshots__/bars.test.jsx.snap +110 -0
- package/src/bars/common/__tests__/bars.test.jsx +69 -0
- package/src/bars/common/__tests__/utils.js +30 -0
- package/src/bars/common/bars.jsx +101 -14
- package/src/bars/common/correct-check-icon.jsx +20 -0
- package/src/chart-type.js +7 -3
- package/src/chart.jsx +53 -29
- package/src/common/__tests__/__snapshots__/drag-handle.test.jsx.snap +48 -0
- package/src/common/__tests__/drag-handle.test.jsx +88 -0
- package/src/common/__tests__/utils.js +30 -0
- package/src/common/correctness-indicators.jsx +55 -0
- package/src/common/drag-handle.jsx +48 -26
- package/src/common/drag-icon.jsx +6 -21
- package/src/grid.jsx +37 -12
- package/src/index.js +2 -1
- package/src/key-legend.jsx +75 -0
- package/src/line/__tests__/__snapshots__/line-cross.test.jsx.snap +45 -0
- package/src/line/__tests__/__snapshots__/line-dot.test.jsx.snap +45 -0
- package/src/line/__tests__/line-cross.test.jsx +38 -0
- package/src/line/__tests__/line-dot.test.jsx +38 -0
- package/src/line/__tests__/utils.js +30 -0
- package/src/line/common/__tests__/__snapshots__/drag-handle.test.jsx.snap +49 -0
- package/src/line/common/__tests__/__snapshots__/line.test.jsx.snap +143 -0
- package/src/line/common/__tests__/drag-handle.test.jsx +88 -0
- package/src/line/common/__tests__/line.test.jsx +82 -0
- package/src/line/common/__tests__/utils.js +30 -0
- package/src/line/common/drag-handle.jsx +38 -16
- package/src/line/common/line.jsx +4 -6
- package/src/line/line-cross.js +56 -4
- package/src/line/line-dot.js +74 -10
- package/src/mark-label.jsx +83 -51
- package/src/plot/__tests__/__snapshots__/dot.test.jsx.snap +45 -0
- package/src/plot/__tests__/__snapshots__/line.test.jsx.snap +45 -0
- package/src/plot/__tests__/dot.test.jsx +38 -0
- package/src/plot/__tests__/line.test.jsx +38 -0
- package/src/plot/__tests__/utils.js +30 -0
- package/src/plot/common/__tests__/__snapshots__/plot.test.jsx.snap +97 -0
- package/src/plot/common/__tests__/plot.test.jsx +70 -0
- package/src/plot/common/__tests__/utils.js +30 -0
- package/src/plot/common/plot.jsx +127 -10
- package/src/plot/dot.js +19 -3
- package/src/plot/line.js +18 -4
- package/src/tool-menu.jsx +0 -4
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`MarkLabel snapshot renders 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<AutosizeInput
|
|
6
|
+
injectStyles={true}
|
|
7
|
+
inputClassName=""
|
|
8
|
+
inputRef={[Function]}
|
|
9
|
+
inputStyle={
|
|
10
|
+
Object {
|
|
11
|
+
"background": "transparent",
|
|
12
|
+
"boxSizing": "border-box",
|
|
13
|
+
"minWidth": undefined,
|
|
14
|
+
"paddingLeft": 0,
|
|
15
|
+
"paddingRight": 0,
|
|
16
|
+
"textAlign": "center",
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
minWidth={1}
|
|
20
|
+
onBlur={[Function]}
|
|
21
|
+
onChange={[Function]}
|
|
22
|
+
style={
|
|
23
|
+
Object {
|
|
24
|
+
"left": 0,
|
|
25
|
+
"marginTop": "0",
|
|
26
|
+
"minWidth": undefined,
|
|
27
|
+
"pointerEvents": "auto",
|
|
28
|
+
"position": "fixed",
|
|
29
|
+
"top": 0,
|
|
30
|
+
"transform": "rotate(undefineddeg)",
|
|
31
|
+
"transformOrigin": "left",
|
|
32
|
+
"visibility": "unset",
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/>
|
|
36
|
+
</div>
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
exports[`MarkLabel snapshot renders 2`] = `
|
|
40
|
+
<div>
|
|
41
|
+
<AutosizeInput
|
|
42
|
+
injectStyles={true}
|
|
43
|
+
inputClassName=""
|
|
44
|
+
inputRef={[Function]}
|
|
45
|
+
inputStyle={
|
|
46
|
+
Object {
|
|
47
|
+
"background": "transparent",
|
|
48
|
+
"boxSizing": "border-box",
|
|
49
|
+
"minWidth": undefined,
|
|
50
|
+
"paddingLeft": 0,
|
|
51
|
+
"paddingRight": 0,
|
|
52
|
+
"textAlign": "center",
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
minWidth={1}
|
|
56
|
+
onBlur={[Function]}
|
|
57
|
+
onChange={[Function]}
|
|
58
|
+
style={
|
|
59
|
+
Object {
|
|
60
|
+
"left": 0,
|
|
61
|
+
"marginTop": "0",
|
|
62
|
+
"minWidth": undefined,
|
|
63
|
+
"pointerEvents": "auto",
|
|
64
|
+
"position": "fixed",
|
|
65
|
+
"top": 0,
|
|
66
|
+
"transform": "rotate(undefineddeg)",
|
|
67
|
+
"transformOrigin": "left",
|
|
68
|
+
"visibility": "unset",
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/>
|
|
72
|
+
</div>
|
|
73
|
+
`;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { shallow } from 'enzyme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import ChartAxes, { TickComponent, RawChartAxes } from '../axes';
|
|
4
|
+
import { graphProps } from './utils';
|
|
5
|
+
|
|
6
|
+
describe('ChartAxes', () => {
|
|
7
|
+
const wrapper = (extras) => {
|
|
8
|
+
const defaults = {
|
|
9
|
+
classes: {},
|
|
10
|
+
className: 'className',
|
|
11
|
+
graphProps: graphProps(),
|
|
12
|
+
xBand: {
|
|
13
|
+
bandwidth: () => {},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
const props = { ...defaults, ...extras };
|
|
17
|
+
return shallow(<ChartAxes {...props} />);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
describe('snapshot', () => {
|
|
21
|
+
it('renders', () => expect(wrapper()).toMatchSnapshot());
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('RawChartAxes', () => {
|
|
26
|
+
const wrapper = (extras) => {
|
|
27
|
+
const defaults = {
|
|
28
|
+
classes: {},
|
|
29
|
+
className: 'className',
|
|
30
|
+
graphProps: graphProps(),
|
|
31
|
+
xBand: {
|
|
32
|
+
bandwidth: () => {},
|
|
33
|
+
rangeRound: () => {},
|
|
34
|
+
},
|
|
35
|
+
categories: [],
|
|
36
|
+
};
|
|
37
|
+
const props = { ...defaults, ...extras };
|
|
38
|
+
return shallow(<RawChartAxes {...props} />);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
describe('snapshot', () => {
|
|
42
|
+
it('renders', () => expect(wrapper()).toMatchSnapshot());
|
|
43
|
+
|
|
44
|
+
it('renders if graphProps is not defined', () => expect(wrapper({ graphProps: undefined })).toMatchSnapshot());
|
|
45
|
+
|
|
46
|
+
it('renders if categories are not defined', () => expect(wrapper({ categories: undefined })).toMatchSnapshot());
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('splitText method', () => {
|
|
51
|
+
const wrapper = (extras) => {
|
|
52
|
+
const xBand = jest.fn();
|
|
53
|
+
xBand.bandwidth = jest.fn();
|
|
54
|
+
|
|
55
|
+
const defaults = {
|
|
56
|
+
graphProps: graphProps(),
|
|
57
|
+
xBand,
|
|
58
|
+
};
|
|
59
|
+
const props = { ...defaults, ...extras };
|
|
60
|
+
return shallow(<TickComponent {...props} />);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
it('splits a string into chunks of up to the specified length', () => {
|
|
64
|
+
const w = wrapper();
|
|
65
|
+
const input = 'This is a test string for splitText function';
|
|
66
|
+
const output = w.instance().splitText(input, 20);
|
|
67
|
+
expect(output).toEqual(['This is a test', 'string for splitText', 'function']);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('returns an array with a single string when the input is less than the specified length', () => {
|
|
71
|
+
const w = wrapper();
|
|
72
|
+
const input = 'Short text';
|
|
73
|
+
const output = w.instance().splitText(input, 20);
|
|
74
|
+
expect(output).toEqual(['Short text']);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('splits a string into chunks of exact length when no spaces are present', () => {
|
|
78
|
+
const w = wrapper();
|
|
79
|
+
const input = 'ThisisateststringforsplitTextfunction';
|
|
80
|
+
const output = w.instance().splitText(input, 10);
|
|
81
|
+
expect(output).toEqual(['Thisisates', 'tstringfor', 'splitTextf', 'unction']);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('returns an empty array when the input is an empty string', () => {
|
|
85
|
+
const w = wrapper();
|
|
86
|
+
const input = '';
|
|
87
|
+
const output = w.instance().splitText(input, 20);
|
|
88
|
+
expect(output).toEqual([]);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('returns an empty array when the input is null', () => {
|
|
92
|
+
const w = wrapper();
|
|
93
|
+
const input = null;
|
|
94
|
+
const output = w.instance().splitText(input, 20);
|
|
95
|
+
expect(output).toEqual([]);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('TickComponent', () => {
|
|
100
|
+
const wrapper = (extras) => {
|
|
101
|
+
const xBand = jest.fn();
|
|
102
|
+
xBand.bandwidth = jest.fn();
|
|
103
|
+
|
|
104
|
+
const defaults = {
|
|
105
|
+
graphProps: graphProps(),
|
|
106
|
+
xBand,
|
|
107
|
+
};
|
|
108
|
+
const props = { ...defaults, ...extras };
|
|
109
|
+
return shallow(<TickComponent {...props} />);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
describe('snapshot', () => {
|
|
113
|
+
it('renders', () => expect(wrapper()).toMatchSnapshot());
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe('snapshot1', () => {
|
|
117
|
+
it('renders', () =>
|
|
118
|
+
expect(
|
|
119
|
+
wrapper({
|
|
120
|
+
formattedValue: '0-test',
|
|
121
|
+
categories: [{ value: 1, label: 'test' }],
|
|
122
|
+
}),
|
|
123
|
+
).toMatchSnapshot());
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('logic', () => {
|
|
127
|
+
const onChange = jest.fn();
|
|
128
|
+
const onChangeCategory = jest.fn();
|
|
129
|
+
const w = wrapper({
|
|
130
|
+
formattedValue: '0-test',
|
|
131
|
+
categories: [{ value: 1, label: 'test' }],
|
|
132
|
+
onChange,
|
|
133
|
+
onChangeCategory,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('calls onChangeCategory', () => {
|
|
137
|
+
w.instance().changeCategory(0, 'new label');
|
|
138
|
+
expect(onChangeCategory).toHaveBeenCalledWith(0, { value: 1, label: 'new label' });
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { resetValues } from '../chart-setup';
|
|
2
|
+
|
|
3
|
+
describe('resetValues', () => {
|
|
4
|
+
let data;
|
|
5
|
+
let range;
|
|
6
|
+
let model;
|
|
7
|
+
let onChange;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
range = { min: 0, max: 10, step: 1 };
|
|
11
|
+
data = [
|
|
12
|
+
{ value: 2 },
|
|
13
|
+
{ value: 11 },
|
|
14
|
+
{ value: 5.5 },
|
|
15
|
+
{ value: 2.0000000001 }, // A float close to an integer
|
|
16
|
+
{ value: 2.9999999999 }, // Another float close to an integer
|
|
17
|
+
];
|
|
18
|
+
model = { someField: 'someValue', data };
|
|
19
|
+
onChange = jest.fn();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should reset values greater than range.max to zero', () => {
|
|
23
|
+
resetValues(data, true, range, onChange, model);
|
|
24
|
+
expect(data[1].value).toBe(0);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should reset values that are not multiples of range.step to zero', () => {
|
|
28
|
+
resetValues(data, true, range, onChange, model);
|
|
29
|
+
expect(data[2].value).toBe(0);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should not reset values that are within range and multiples of range.step', () => {
|
|
33
|
+
resetValues(data, true, range, onChange, model);
|
|
34
|
+
expect(data[0].value).toBe(2);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should not reset floating point values that are close to multiples of range.step', () => {
|
|
38
|
+
resetValues(data, true, range, onChange, model);
|
|
39
|
+
expect(data[3].value).toBe(2.0000000001); // remains unchanged
|
|
40
|
+
expect(data[4].value).toBe(2.9999999999); // remains unchanged
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should not call onChange when updateModel is false', () => {
|
|
44
|
+
resetValues(data, false, range, onChange, model);
|
|
45
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { shallow } from 'enzyme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import ChartType from '../chart-type';
|
|
4
|
+
|
|
5
|
+
describe('ChartType', () => {
|
|
6
|
+
let wrapper;
|
|
7
|
+
let props;
|
|
8
|
+
const onChange = jest.fn();
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
props = {
|
|
12
|
+
classes: {},
|
|
13
|
+
value: 'bar',
|
|
14
|
+
onChange,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
wrapper = (newProps) => {
|
|
18
|
+
const configureProps = { ...props, newProps };
|
|
19
|
+
|
|
20
|
+
return shallow(<ChartType {...configureProps} />);
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('renders', () => {
|
|
25
|
+
it('snapshot', () => {
|
|
26
|
+
expect(wrapper()).toMatchSnapshot();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { shallow } from 'enzyme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Chart } from '../chart';
|
|
4
|
+
import { graphProps } from './utils';
|
|
5
|
+
|
|
6
|
+
describe('ChartAxes', () => {
|
|
7
|
+
let onDataChange = jest.fn();
|
|
8
|
+
const wrapper = (extras) => {
|
|
9
|
+
const defaults = {
|
|
10
|
+
classes: {},
|
|
11
|
+
onDataChange,
|
|
12
|
+
className: 'className',
|
|
13
|
+
graphProps: graphProps(),
|
|
14
|
+
xBand: () => {
|
|
15
|
+
return {
|
|
16
|
+
bandwidth: () => {},
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
charts: [
|
|
20
|
+
{
|
|
21
|
+
type: 'bar',
|
|
22
|
+
Component: () => <div />,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
chartType: 'bar',
|
|
26
|
+
domain: {},
|
|
27
|
+
range: {
|
|
28
|
+
min: 0,
|
|
29
|
+
max: 10,
|
|
30
|
+
},
|
|
31
|
+
size: {
|
|
32
|
+
width: 100,
|
|
33
|
+
height: 100,
|
|
34
|
+
},
|
|
35
|
+
data: [],
|
|
36
|
+
};
|
|
37
|
+
const props = { ...defaults, ...extras };
|
|
38
|
+
return shallow(<Chart {...props} />);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
describe('snapshot', () => {
|
|
42
|
+
it('renders', () => {
|
|
43
|
+
jest.spyOn(Chart.prototype, 'generateMaskId').mockReturnValue('chart-2645');
|
|
44
|
+
let w = wrapper();
|
|
45
|
+
expect(w).toMatchSnapshot();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('renders if size is not defined', () => {
|
|
49
|
+
jest.spyOn(Chart.prototype, 'generateMaskId').mockReturnValue('chart-1553');
|
|
50
|
+
let w = wrapper({ size: undefined });
|
|
51
|
+
expect(w).toMatchSnapshot();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('renders without chartType property', () => {
|
|
55
|
+
jest.spyOn(Chart.prototype, 'generateMaskId').mockReturnValue('chart-4286');
|
|
56
|
+
let w = wrapper({ chartType: null });
|
|
57
|
+
expect(w).toMatchSnapshot();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('renders without chartType and charts properties', () =>
|
|
61
|
+
expect(wrapper({ chartType: null, charts: null })).toMatchSnapshot());
|
|
62
|
+
|
|
63
|
+
it('renders without chartType property and empty charts property', () =>
|
|
64
|
+
expect(wrapper({ chartType: null, charts: [] })).toMatchSnapshot());
|
|
65
|
+
|
|
66
|
+
it('renders with chartType property and empty charts property', () =>
|
|
67
|
+
expect(wrapper({ charts: [] })).toMatchSnapshot());
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('logic', () => {
|
|
71
|
+
it('changeData', () => {
|
|
72
|
+
let w = wrapper();
|
|
73
|
+
|
|
74
|
+
w.instance().changeData();
|
|
75
|
+
|
|
76
|
+
expect(onDataChange).toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('getChart', () => {
|
|
80
|
+
const w = wrapper();
|
|
81
|
+
|
|
82
|
+
const chart = w.instance().getChart();
|
|
83
|
+
|
|
84
|
+
expect(chart.type).toEqual('bar');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('deleteCategory', () => {
|
|
88
|
+
const w = wrapper();
|
|
89
|
+
|
|
90
|
+
w.instance().deleteCategory(0);
|
|
91
|
+
|
|
92
|
+
expect(onDataChange).toHaveBeenCalled();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { shallow } from 'enzyme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Grid } from '../grid';
|
|
4
|
+
import { graphProps } from './utils';
|
|
5
|
+
|
|
6
|
+
describe('Grid', () => {
|
|
7
|
+
let w;
|
|
8
|
+
const wrapper = (extras) => {
|
|
9
|
+
const defaults = {
|
|
10
|
+
classes: {},
|
|
11
|
+
className: 'className',
|
|
12
|
+
graphProps: graphProps(),
|
|
13
|
+
xBand: {
|
|
14
|
+
bandwidth: () => {},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
const props = { ...defaults, ...extras };
|
|
18
|
+
return shallow(<Grid {...props} />);
|
|
19
|
+
};
|
|
20
|
+
describe('snapshot', () => {
|
|
21
|
+
it('renders', () => expect(wrapper()).toMatchSnapshot());
|
|
22
|
+
|
|
23
|
+
it('renders if graphProps is not defined', () => expect(wrapper({ graphProps: undefined })).toMatchSnapshot());
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { shallow } from 'enzyme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { MarkLabel } from '../mark-label';
|
|
4
|
+
import { graphProps as getGraphProps } from './utils';
|
|
5
|
+
|
|
6
|
+
describe('MarkLabel', () => {
|
|
7
|
+
let w;
|
|
8
|
+
let onChange = jest.fn();
|
|
9
|
+
const wrapper = (extras) => {
|
|
10
|
+
const defaults = {
|
|
11
|
+
classes: {},
|
|
12
|
+
defineChart: false,
|
|
13
|
+
className: 'className',
|
|
14
|
+
onChange,
|
|
15
|
+
mark: { x: 1, y: 1 },
|
|
16
|
+
graphProps: getGraphProps(0, 10, 0, 10),
|
|
17
|
+
};
|
|
18
|
+
const props = { ...defaults, ...extras };
|
|
19
|
+
return shallow(<MarkLabel {...props} />);
|
|
20
|
+
};
|
|
21
|
+
describe('snapshot', () => {
|
|
22
|
+
it('renders', () => {
|
|
23
|
+
w = wrapper();
|
|
24
|
+
expect(w).toMatchSnapshot();
|
|
25
|
+
});
|
|
26
|
+
it('renders', () => {
|
|
27
|
+
w = wrapper({ mark: { x: 10, y: 10 } });
|
|
28
|
+
expect(w).toMatchSnapshot();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const scaleMock = () => {
|
|
2
|
+
const fn = jest.fn((n) => n);
|
|
3
|
+
fn.invert = jest.fn((n) => n);
|
|
4
|
+
return fn;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const graphProps = (dmin = 0, dmax = 1, rmin = 0, rmax = 1) => ({
|
|
8
|
+
scale: {
|
|
9
|
+
x: scaleMock(),
|
|
10
|
+
y: scaleMock(),
|
|
11
|
+
},
|
|
12
|
+
snap: {
|
|
13
|
+
x: jest.fn((n) => n),
|
|
14
|
+
y: jest.fn((n) => n),
|
|
15
|
+
},
|
|
16
|
+
domain: {
|
|
17
|
+
min: dmin,
|
|
18
|
+
max: dmax,
|
|
19
|
+
step: 1,
|
|
20
|
+
},
|
|
21
|
+
range: {
|
|
22
|
+
min: rmin,
|
|
23
|
+
max: rmax,
|
|
24
|
+
step: 1,
|
|
25
|
+
},
|
|
26
|
+
size: {
|
|
27
|
+
width: 400,
|
|
28
|
+
height: 400,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as utils from '../utils';
|
|
2
|
+
|
|
3
|
+
const xy = (x, y) => ({ x, y });
|
|
4
|
+
|
|
5
|
+
describe('utils', () => {
|
|
6
|
+
describe('getTickValues', () => {
|
|
7
|
+
const assertGetTickValues = (range, points) => {
|
|
8
|
+
it(`converts ${range} -> ${points}`, () => {
|
|
9
|
+
const result = utils.getTickValues(range);
|
|
10
|
+
expect(result).toEqual(points);
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
assertGetTickValues({ min: 0, max: 5, step: 1 }, [0, 1, 2, 3, 4, 5]);
|
|
15
|
+
assertGetTickValues({ min: 0, max: 5, step: 0.5 }, [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5]);
|
|
16
|
+
assertGetTickValues({ min: 0.4, max: 2, step: 0.3 }, [0.4, 0.7, 1, 1.3, 1.6, 1.9]);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('getDomainAndRangeByChartType', () => {
|
|
20
|
+
const assertGetDomainAndRangeByChartType = (domain, range, chartType, correctValues) => {
|
|
21
|
+
it('returns correct values for domain and range', () => {
|
|
22
|
+
const result = utils.getDomainAndRangeByChartType(domain, range, chartType);
|
|
23
|
+
expect(result).toEqual(correctValues);
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
assertGetDomainAndRangeByChartType({ min: -1, max: 4 }, { min: 1, max: 2, step: 1 }, 'line', {
|
|
28
|
+
domain: { min: 0, max: 1, step: 1, labelStep: 1 },
|
|
29
|
+
range: { min: 1, max: 2, step: 1, labelStep: 1 },
|
|
30
|
+
});
|
|
31
|
+
assertGetDomainAndRangeByChartType({ min: -1, max: 4 }, { min: 0.1, max: 2, labelStep: 0.1 }, 'line', {
|
|
32
|
+
domain: { min: 0, max: 1, step: 1, labelStep: 1 },
|
|
33
|
+
range: { min: 0.1, max: 2, step: 0.1, labelStep: 0.1 },
|
|
34
|
+
});
|
|
35
|
+
assertGetDomainAndRangeByChartType({ min: -1, max: 4 }, { min: 0.2, max: 2.4, step: 0.1 }, 'dotPlot', {
|
|
36
|
+
domain: { min: 0, max: 1, step: 1, labelStep: 1 },
|
|
37
|
+
range: { min: 0, max: 2, step: 1, labelStep: 0.1 },
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('getGridLinesAndAxisByChartType', () => {
|
|
42
|
+
const assertGetGridLinesAndAxisByChartType = (range, chartType, gridLines) => {
|
|
43
|
+
it('returns proper grid values', () => {
|
|
44
|
+
const result = utils.getGridLinesAndAxisByChartType(range, chartType);
|
|
45
|
+
expect(result).toEqual(gridLines);
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
assertGetGridLinesAndAxisByChartType({ min: 0, max: 1, step: 1 }, 'lineDot', {
|
|
50
|
+
verticalLines: undefined,
|
|
51
|
+
horizontalLines: [0, 1],
|
|
52
|
+
leftAxis: true,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
assertGetGridLinesAndAxisByChartType({ min: 0, max: 1, step: 1 }, 'lineCross', {
|
|
56
|
+
verticalLines: undefined,
|
|
57
|
+
horizontalLines: [0, 1],
|
|
58
|
+
leftAxis: true,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
assertGetGridLinesAndAxisByChartType({ min: 0, max: 1, step: 1 }, 'bar', {
|
|
62
|
+
verticalLines: [],
|
|
63
|
+
horizontalLines: [0, 1],
|
|
64
|
+
leftAxis: true,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
assertGetGridLinesAndAxisByChartType({ min: 0, max: 1, step: 1 }, 'dotPlot', {
|
|
68
|
+
verticalLines: [],
|
|
69
|
+
horizontalLines: [],
|
|
70
|
+
leftAxis: false,
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('getTopPadding', () => {
|
|
75
|
+
const assertGetTopPadding = (barWidth, topPadding) => {
|
|
76
|
+
it('returns proper top padding', () => {
|
|
77
|
+
const result = utils.getTopPadding(barWidth);
|
|
78
|
+
expect(result).toEqual(topPadding);
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
assertGetTopPadding(20, 50);
|
|
83
|
+
assertGetTopPadding(35, 30);
|
|
84
|
+
assertGetTopPadding(55, 15);
|
|
85
|
+
assertGetTopPadding(65, 0);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('getRotateAngle', () => {
|
|
89
|
+
const assertGetRotateAngle = ({ fontSize, height }, rotateAngle) => {
|
|
90
|
+
it('returns proper rotate angle', () => {
|
|
91
|
+
const result = utils.getRotateAngle(fontSize, height);
|
|
92
|
+
expect(result).toEqual(rotateAngle);
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
assertGetRotateAngle({ fontSize: 14, height: 14 }, 0);
|
|
97
|
+
assertGetRotateAngle({ fontSize: 14, height: 28 }, 25);
|
|
98
|
+
assertGetRotateAngle({ fontSize: 14, height: 42 }, 25);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { withStyles } from '@material-ui/core/styles';
|
|
4
|
+
import Button from '@material-ui/core/Button';
|
|
5
|
+
import Popover from '@material-ui/core/Popover';
|
|
6
|
+
import Paper from '@material-ui/core/Paper';
|
|
7
|
+
|
|
8
|
+
import { color } from '@pie-lib/render-ui';
|
|
9
|
+
import Translator from '@pie-lib/translator';
|
|
10
|
+
|
|
11
|
+
const { translator } = Translator;
|
|
12
|
+
|
|
13
|
+
export class ActionsButton extends React.Component {
|
|
14
|
+
constructor(props) {
|
|
15
|
+
super(props);
|
|
16
|
+
this.state = {
|
|
17
|
+
actionsAnchorEl: null,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static propTypes = {
|
|
22
|
+
classes: PropTypes.object.isRequired,
|
|
23
|
+
addCategory: PropTypes.func.isRequired,
|
|
24
|
+
deleteCategory: PropTypes.func.isRequired,
|
|
25
|
+
language: PropTypes.string,
|
|
26
|
+
categories: PropTypes.array,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
handleActionsClick = (event) => {
|
|
30
|
+
this.setState({ actionsAnchorEl: event.currentTarget });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
handleActionsClose = () => {
|
|
34
|
+
this.setState({ actionsAnchorEl: null });
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
handleAddCategory = () => {
|
|
38
|
+
const { addCategory } = this.props;
|
|
39
|
+
addCategory();
|
|
40
|
+
this.handleActionsClose();
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
handleDeleteCategory = (index) => {
|
|
44
|
+
const { deleteCategory } = this.props;
|
|
45
|
+
deleteCategory(index);
|
|
46
|
+
this.handleActionsClose();
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
render() {
|
|
50
|
+
const { classes, categories, language } = this.props;
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div className={classes.actions}>
|
|
54
|
+
<div role="button" tabIndex={0} className={classes.trigger} onClick={this.handleActionsClick}>
|
|
55
|
+
Actions
|
|
56
|
+
</div>
|
|
57
|
+
<Popover
|
|
58
|
+
open={Boolean(this.state.actionsAnchorEl)}
|
|
59
|
+
anchorEl={this.state.actionsAnchorEl}
|
|
60
|
+
onClose={this.handleActionsClose}
|
|
61
|
+
anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
|
|
62
|
+
transformOrigin={{ vertical: 'top', horizontal: 'left' }}
|
|
63
|
+
>
|
|
64
|
+
<Paper className={classes.actionsPaper}>
|
|
65
|
+
<Button onClick={() => this.handleAddCategory()}>
|
|
66
|
+
+ {translator.t('charting.add', { lng: language })}
|
|
67
|
+
</Button>
|
|
68
|
+
{categories.length > 0 &&
|
|
69
|
+
categories.map(
|
|
70
|
+
(category, index) =>
|
|
71
|
+
category.deletable &&
|
|
72
|
+
!category.correctness && (
|
|
73
|
+
<Button key={index} onClick={() => this.handleDeleteCategory(index)}>
|
|
74
|
+
{`${translator.t('charting.delete', { lng: language })} <${category.label ||
|
|
75
|
+
translator.t('charting.newLabel', { lng: language })}>`}
|
|
76
|
+
</Button>
|
|
77
|
+
),
|
|
78
|
+
)}
|
|
79
|
+
</Paper>
|
|
80
|
+
</Popover>
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const styles = (theme) => ({
|
|
87
|
+
actions: {
|
|
88
|
+
alignSelf: 'flex-end',
|
|
89
|
+
},
|
|
90
|
+
trigger: {
|
|
91
|
+
cursor: 'pointer',
|
|
92
|
+
fontSize: theme.typography.fontSize,
|
|
93
|
+
color: color.tertiary(),
|
|
94
|
+
padding: theme.spacing.unit,
|
|
95
|
+
},
|
|
96
|
+
actionsPaper: {
|
|
97
|
+
padding: theme.spacing.unit,
|
|
98
|
+
display: 'flex',
|
|
99
|
+
flexDirection: 'column',
|
|
100
|
+
gap: theme.spacing.unit,
|
|
101
|
+
'& button': {
|
|
102
|
+
textTransform: 'none',
|
|
103
|
+
fontSize: theme.typography.fontSize,
|
|
104
|
+
color: color.text(),
|
|
105
|
+
justifyContent: 'flex-start',
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
export default withStyles(styles)(ActionsButton);
|