@blotch/dolan 22.2.2 → 22.2.3
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/dist/commands/add.d.ts +6 -2
- package/dist/commands/add.js +32 -10
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/add.test.js +129 -9
- package/dist/commands/add.test.js.map +1 -1
- package/dist/commands/diff.d.ts +2 -1
- package/dist/commands/diff.js +38 -25
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/diff.test.js +72 -11
- package/dist/commands/diff.test.js.map +1 -1
- package/dist/commands/doctor.js +41 -27
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.js +93 -9
- package/dist/commands/doctor.test.js.map +1 -1
- package/dist/commands/eject.js +7 -0
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/eject.test.js +39 -0
- package/dist/commands/eject.test.js.map +1 -1
- package/dist/commands/info.js +3 -2
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.d.ts +37 -1
- package/dist/commands/init.js +149 -40
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +285 -26
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/install-packages.d.ts +6 -0
- package/dist/commands/install-packages.js +20 -0
- package/dist/commands/install-packages.js.map +1 -0
- package/dist/commands/install-packages.test.d.ts +1 -0
- package/dist/commands/install-packages.test.js +55 -0
- package/dist/commands/install-packages.test.js.map +1 -0
- package/dist/commands/list.js +21 -14
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/list.test.js +62 -5
- package/dist/commands/list.test.js.map +1 -1
- package/dist/commands/outdated.js +11 -10
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/outdated.test.js +20 -5
- package/dist/commands/outdated.test.js.map +1 -1
- package/dist/commands/remove.d.ts +4 -0
- package/dist/commands/remove.js +17 -4
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/remove.test.js +53 -2
- package/dist/commands/remove.test.js.map +1 -1
- package/dist/commands/update.d.ts +6 -0
- package/dist/commands/update.js +59 -24
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/update.test.js +273 -31
- package/dist/commands/update.test.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/registry.d.ts +8 -0
- package/dist/registry.js +32 -24
- package/dist/registry.js.map +1 -1
- package/dist/registry.test.js +76 -37
- package/dist/registry.test.js.map +1 -1
- package/dist/testing/set-input-signal.d.ts +13 -0
- package/dist/testing/set-input-signal.js +20 -0
- package/dist/testing/set-input-signal.js.map +1 -0
- package/dist/testing/set-input-signal.test.d.ts +1 -0
- package/dist/testing/set-input-signal.test.js +20 -0
- package/dist/testing/set-input-signal.test.js.map +1 -0
- package/dist/ui/components/action-sheet/action-sheet.test.ts +48 -1
- package/dist/ui/components/action-sheet/action-sheet.ts +37 -9
- package/dist/ui/components/alert-dialog/alert-dialog.test.ts +49 -2
- package/dist/ui/components/alert-dialog/alert-dialog.ts +43 -12
- package/dist/ui/components/area-chart/area-chart-render.test.ts +52 -110
- package/dist/ui/components/area-chart/area-chart.test.ts +58 -123
- package/dist/ui/components/area-chart/area-chart.ts +100 -315
- package/dist/ui/components/area-chart/index.ts +2 -3
- package/dist/ui/components/bar-chart/bar-chart-render.test.ts +47 -163
- package/dist/ui/components/bar-chart/bar-chart.test.ts +83 -37
- package/dist/ui/components/bar-chart/bar-chart.ts +140 -294
- package/dist/ui/components/bar-chart/index.ts +3 -3
- package/dist/ui/components/bottom-sheet/bottom-sheet.test.ts +191 -9
- package/dist/ui/components/bottom-sheet/bottom-sheet.ts +136 -20
- package/dist/ui/components/button/button-render.test.ts +19 -0
- package/dist/ui/components/button/button.ts +18 -2
- package/dist/ui/components/candlestick-chart/candlestick-chart-render.test.ts +48 -163
- package/dist/ui/components/candlestick-chart/candlestick-chart.test.ts +106 -62
- package/dist/ui/components/candlestick-chart/candlestick-chart.ts +150 -323
- package/dist/ui/components/candlestick-chart/index.ts +3 -4
- package/dist/ui/components/chart/chart-focus.test.ts +132 -0
- package/dist/ui/components/chart/chart-focus.ts +115 -0
- package/dist/ui/components/chart/chart-presets.test.ts +139 -0
- package/dist/ui/components/chart/chart-presets.ts +271 -0
- package/dist/ui/components/chart/chart-render.test.ts +730 -0
- package/dist/ui/components/chart/chart-scene.test.ts +589 -0
- package/dist/ui/components/chart/chart-scene.ts +483 -0
- package/dist/ui/components/chart/chart-theme.test.ts +85 -0
- package/dist/ui/components/chart/chart-theme.ts +198 -0
- package/dist/ui/components/chart/chart-zoom.test.ts +159 -0
- package/dist/ui/components/chart/chart-zoom.ts +162 -0
- package/dist/ui/components/chart/chart.ts +921 -0
- package/dist/ui/components/chart/index.ts +24 -0
- package/dist/ui/components/dialog/dialog.test.ts +49 -2
- package/dist/ui/components/dialog/dialog.ts +43 -12
- package/dist/ui/components/icon/icon-theme.test.ts +133 -0
- package/dist/ui/components/icon/icon-theme.ts +204 -0
- package/dist/ui/components/icon/icon.test.ts +51 -2
- package/dist/ui/components/icon/icon.ts +38 -21
- package/dist/ui/components/line-chart/index.ts +2 -3
- package/dist/ui/components/line-chart/line-chart-render.test.ts +69 -107
- package/dist/ui/components/line-chart/line-chart.test.ts +63 -45
- package/dist/ui/components/line-chart/line-chart.ts +83 -241
- package/dist/ui/components/list/list.test.ts +69 -2
- package/dist/ui/components/list/list.ts +21 -15
- package/dist/ui/components/nav-drawer/nav-drawer.test.ts +80 -1
- package/dist/ui/components/nav-drawer/nav-drawer.ts +66 -11
- package/dist/ui/components/pagination/pagination.test.ts +62 -0
- package/dist/ui/components/pagination/pagination.ts +55 -8
- package/dist/ui/components/scatter-chart/index.ts +2 -3
- package/dist/ui/components/scatter-chart/scatter-chart-render.test.ts +51 -144
- package/dist/ui/components/scatter-chart/scatter-chart.test.ts +57 -25
- package/dist/ui/components/scatter-chart/scatter-chart.ts +104 -250
- package/dist/ui/components/scroll-area/scroll-area.test.ts +37 -2
- package/dist/ui/components/scroll-area/scroll-area.ts +8 -8
- package/dist/ui/components/spinner/spinner.test.ts +27 -0
- package/dist/ui/components/spinner/spinner.ts +33 -23
- package/dist/ui/components/toast/toast.test.ts +37 -0
- package/dist/ui/components/toast/toast.ts +20 -4
- package/dist/ui/theme/chart-colors.test.ts +30 -0
- package/dist/ui/theme/dark.css +8 -0
- package/dist/ui/theme/default.css +8 -0
- package/dist/ui/theme/icon-colors.test.ts +30 -0
- package/dist/ui/theme/tailwind-plugin.ts +10 -1
- package/dist/utils/installed.d.ts +17 -0
- package/dist/utils/installed.js +27 -0
- package/dist/utils/installed.js.map +1 -0
- package/dist/utils/installed.test.d.ts +1 -0
- package/dist/utils/installed.test.js +41 -0
- package/dist/utils/installed.test.js.map +1 -0
- package/dist/utils/interactive.d.ts +9 -0
- package/dist/utils/interactive.js +10 -0
- package/dist/utils/interactive.js.map +1 -0
- package/dist/utils/interactive.test.d.ts +1 -0
- package/dist/utils/interactive.test.js +24 -0
- package/dist/utils/interactive.test.js.map +1 -0
- package/dist/utils/packages.d.ts +36 -0
- package/dist/utils/packages.js +70 -0
- package/dist/utils/packages.js.map +1 -0
- package/dist/utils/packages.test.d.ts +1 -0
- package/dist/utils/packages.test.js +89 -0
- package/dist/utils/packages.test.js.map +1 -0
- package/dist/utils/resolve-paths.d.ts +17 -1
- package/dist/utils/resolve-paths.js +23 -3
- package/dist/utils/resolve-paths.js.map +1 -1
- package/dist/utils/resolve-paths.test.js +34 -2
- package/dist/utils/resolve-paths.test.js.map +1 -1
- package/package.json +5 -1
- package/dist/ui/components/cartesian-chart/cartesian-chart-render.test.ts +0 -188
- package/dist/ui/components/cartesian-chart/cartesian-chart.test.ts +0 -525
- package/dist/ui/components/cartesian-chart/cartesian-chart.ts +0 -1140
- package/dist/ui/components/cartesian-chart/index.ts +0 -18
|
@@ -1,174 +1,59 @@
|
|
|
1
|
-
import { render
|
|
1
|
+
import { render } from '@blotch/angular-lynx-testing-library';
|
|
2
|
+
import { createChartRuntime } from '@tanstack/charts/runtime';
|
|
3
|
+
import type {
|
|
4
|
+
ChartDefinition,
|
|
5
|
+
ChartPoint,
|
|
6
|
+
SceneNode,
|
|
7
|
+
} from '@tanstack/charts/types';
|
|
2
8
|
import { describe, expect, it, vi } from 'vitest';
|
|
3
9
|
import { setInputSignal } from '../../../test-utils/set-input-signal';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
import { UiCandlestickChart } from './candlestick-chart';
|
|
11
|
+
|
|
12
|
+
const data = [
|
|
13
|
+
{ x: 0, open: 100, high: 104, low: 98, close: 102 },
|
|
14
|
+
{ x: 1, open: 102, high: 103, low: 97, close: 99 },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const render2 = (definition: ChartDefinition<any, any, any>) => {
|
|
18
|
+
const scene = createChartRuntime().render(definition, {
|
|
19
|
+
width: 300,
|
|
20
|
+
height: 200,
|
|
21
|
+
});
|
|
22
|
+
const found: SceneNode[] = [];
|
|
23
|
+
const walk = (nodes: readonly SceneNode[]) => {
|
|
24
|
+
for (const node of nodes) {
|
|
25
|
+
if (node.kind === 'group') {
|
|
26
|
+
if (!node.focus) walk(node.children);
|
|
27
|
+
} else if (node.kind !== 'label') found.push(node);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
walk(scene.nodes);
|
|
31
|
+
return { scene, found };
|
|
32
|
+
};
|
|
18
33
|
|
|
19
34
|
describe('UiCandlestickChart', () => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
it('derives the y-axis from the lowest low and highest high', async () => {
|
|
26
|
-
const { componentRef } = await render(UiCandlestickChart);
|
|
27
|
-
const inst = componentRef.instance as UiCandlestickChart;
|
|
28
|
-
setInputSignal(inst.data, [
|
|
29
|
-
period(0, 10, 15, 5, 12),
|
|
30
|
-
period(1, 12, 20, 8, 18),
|
|
31
|
-
period(2, 18, 22, 14, 16),
|
|
32
|
-
]);
|
|
33
|
-
await waitForUpdate();
|
|
34
|
-
const cast = inst as unknown as {
|
|
35
|
-
xAxis: () => { domain: readonly [number, number] };
|
|
36
|
-
yAxis: () => { domain: readonly [number, number] };
|
|
37
|
-
effectivePadding: () => { left?: number; right?: number };
|
|
38
|
-
};
|
|
39
|
-
expect(cast.xAxis().domain[0]).toBeLessThanOrEqual(0);
|
|
40
|
-
expect(cast.xAxis().domain[1]).toBeGreaterThanOrEqual(2);
|
|
41
|
-
expect(cast.yAxis().domain[0]).toBeLessThanOrEqual(5);
|
|
42
|
-
expect(cast.yAxis().domain[1]).toBeGreaterThanOrEqual(22);
|
|
43
|
-
// 3 candles → half = 0.5 / 2 = 0.25
|
|
44
|
-
expect(cast.effectivePadding().left).toBeCloseTo(0.25);
|
|
45
|
-
expect(cast.effectivePadding().right).toBeCloseTo(0.25);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('honors explicit xMin / xMax / yMin / yMax overrides', async () => {
|
|
49
|
-
const { componentRef } = await render(UiCandlestickChart);
|
|
50
|
-
const inst = componentRef.instance as UiCandlestickChart;
|
|
51
|
-
setInputSignal(inst.data, [period(0, 10, 15, 5, 12)]);
|
|
52
|
-
setInputSignal(inst.xMin, -5);
|
|
53
|
-
setInputSignal(inst.xMax, 20);
|
|
54
|
-
setInputSignal(inst.yMin, 0);
|
|
55
|
-
setInputSignal(inst.yMax, 100);
|
|
56
|
-
await waitForUpdate();
|
|
57
|
-
const cast = inst as unknown as {
|
|
58
|
-
xAxis: () => { domain: readonly [number, number] };
|
|
59
|
-
yAxis: () => { domain: readonly [number, number] };
|
|
60
|
-
};
|
|
61
|
-
expect(cast.xAxis().domain[0]).toBeLessThanOrEqual(-5);
|
|
62
|
-
expect(cast.xAxis().domain[1]).toBeGreaterThanOrEqual(20);
|
|
63
|
-
expect(cast.yAxis().domain[0]).toBeLessThanOrEqual(0);
|
|
64
|
-
expect(cast.yAxis().domain[1]).toBeGreaterThanOrEqual(100);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('single-datum series drops the half-candle padding', async () => {
|
|
68
|
-
const { componentRef } = await render(UiCandlestickChart);
|
|
69
|
-
const inst = componentRef.instance as UiCandlestickChart;
|
|
70
|
-
setInputSignal(inst.data, [period(0, 10, 15, 5, 12)]);
|
|
71
|
-
await waitForUpdate();
|
|
72
|
-
const cast = inst as unknown as {
|
|
73
|
-
effectivePadding: () => { left?: number; right?: number };
|
|
74
|
-
};
|
|
75
|
-
expect(cast.effectivePadding().left).toBe(0);
|
|
76
|
-
expect(cast.effectivePadding().right).toBe(0);
|
|
77
|
-
});
|
|
35
|
+
type Internals = {
|
|
36
|
+
definition: () => ChartDefinition<any, any, any>;
|
|
37
|
+
onSelect(point: ChartPoint | null): void;
|
|
38
|
+
};
|
|
78
39
|
|
|
79
|
-
it('
|
|
40
|
+
it('builds its definition from its inputs', async () => {
|
|
80
41
|
const { componentRef } = await render(UiCandlestickChart);
|
|
81
|
-
const
|
|
82
|
-
setInputSignal(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
]);
|
|
86
|
-
setInputSignal(inst.padding, { right: 0.05 });
|
|
87
|
-
await waitForUpdate();
|
|
88
|
-
const cast = inst as unknown as {
|
|
89
|
-
effectivePadding: () => { left?: number; right?: number };
|
|
90
|
-
};
|
|
91
|
-
expect(cast.effectivePadding().right).toBeCloseTo(0.05);
|
|
92
|
-
expect(cast.effectivePadding().left).toBeCloseTo(0.5);
|
|
42
|
+
const chart = componentRef.instance as UiCandlestickChart;
|
|
43
|
+
setInputSignal(chart.data, data);
|
|
44
|
+
setInputSignal(chart.upColor, 'blue');
|
|
45
|
+
const { found } = render2((chart as unknown as Internals).definition());
|
|
46
|
+
expect(found.filter((n) => n.kind === 'rect')[0]!.style?.fill).toBe('blue');
|
|
93
47
|
});
|
|
94
48
|
|
|
95
|
-
it('
|
|
49
|
+
it('emits the tapped datum', async () => {
|
|
96
50
|
const { componentRef } = await render(UiCandlestickChart);
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const renderSeries = async () => {
|
|
105
|
-
const parentResult = await render(UiCartesianChart);
|
|
106
|
-
const parent = parentResult.componentRef.instance as UiCartesianChart;
|
|
107
|
-
setInputSignal(parent.xDomain, [0, 10]);
|
|
108
|
-
setInputSignal(parent.yDomain, [0, 100]);
|
|
109
|
-
await waitForUpdate();
|
|
110
|
-
const seriesResult = await render(UiCandlestickSeries, {
|
|
111
|
-
providers: [{ provide: UiCartesianChart, useValue: parent }],
|
|
112
|
-
});
|
|
113
|
-
const series = seriesResult.componentRef.instance as UiCandlestickSeries;
|
|
114
|
-
setInputSignal(series.data, [
|
|
115
|
-
// up candle (close >= open)
|
|
116
|
-
period(0, 10, 20, 5, 15),
|
|
117
|
-
// down candle (close < open)
|
|
118
|
-
period(5, 60, 70, 50, 55),
|
|
119
|
-
// doji (close === open)
|
|
120
|
-
period(10, 40, 50, 30, 40),
|
|
121
|
-
]);
|
|
122
|
-
await waitForUpdate();
|
|
123
|
-
return { parent, series };
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
it('renders a wick + body for each period, tinted by direction', async () => {
|
|
127
|
-
const { series } = await renderSeries();
|
|
128
|
-
const cast = series as unknown as {
|
|
129
|
-
candles: () => {
|
|
130
|
-
wickStyle: string;
|
|
131
|
-
bodyStyle: string;
|
|
132
|
-
point: CandlestickPoint;
|
|
133
|
-
}[];
|
|
134
|
-
};
|
|
135
|
-
const candles = cast.candles();
|
|
136
|
-
expect(candles.length).toBe(3);
|
|
137
|
-
// First: up candle → uses upColor (green rgba)
|
|
138
|
-
expect(candles[0].bodyStyle).toContain('rgba(34, 197, 94, 1)');
|
|
139
|
-
// Second: down candle → uses downColor (red rgba)
|
|
140
|
-
expect(candles[1].bodyStyle).toContain('rgba(239, 68, 68, 1)');
|
|
141
|
-
// Third: doji (open === close) is `up: true` (>= comparison)
|
|
142
|
-
expect(candles[2].bodyStyle).toContain('rgba(34, 197, 94, 1)');
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('emits candleTap with the source point when a body is tapped', async () => {
|
|
146
|
-
const { series } = await renderSeries();
|
|
147
|
-
const cb = vi.fn();
|
|
148
|
-
series.candleTap.subscribe(cb);
|
|
149
|
-
const p = period(1, 2, 3, 1, 2);
|
|
150
|
-
(
|
|
151
|
-
series as unknown as { onCandleTap: (point: CandlestickPoint) => void }
|
|
152
|
-
).onCandleTap(p);
|
|
153
|
-
expect(cb).toHaveBeenCalledWith(p);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('single-datum series uses the fallback body width', async () => {
|
|
157
|
-
const parentResult = await render(UiCartesianChart);
|
|
158
|
-
const parent = parentResult.componentRef.instance as UiCartesianChart;
|
|
159
|
-
setInputSignal(parent.xDomain, [0, 10]);
|
|
160
|
-
setInputSignal(parent.yDomain, [0, 100]);
|
|
161
|
-
await waitForUpdate();
|
|
162
|
-
const seriesResult = await render(UiCandlestickSeries, {
|
|
163
|
-
providers: [{ provide: UiCartesianChart, useValue: parent }],
|
|
164
|
-
});
|
|
165
|
-
const series = seriesResult.componentRef.instance as UiCandlestickSeries;
|
|
166
|
-
setInputSignal(series.data, [period(5, 10, 15, 5, 12)]);
|
|
167
|
-
await waitForUpdate();
|
|
168
|
-
const cast = series as unknown as {
|
|
169
|
-
candles: () => { bodyStyle: string }[];
|
|
170
|
-
};
|
|
171
|
-
// fallback body width = 8px
|
|
172
|
-
expect(cast.candles()[0].bodyStyle).toContain('width: 8.00px');
|
|
51
|
+
const chart = componentRef.instance as UiCandlestickChart;
|
|
52
|
+
const tapped = vi.fn();
|
|
53
|
+
chart.candleTap.subscribe(tapped);
|
|
54
|
+
const internals = chart as unknown as Internals;
|
|
55
|
+
internals.onSelect({ datum: data[0] } as ChartPoint);
|
|
56
|
+
internals.onSelect(null);
|
|
57
|
+
expect(tapped.mock.calls).toEqual([[data[0]]]);
|
|
173
58
|
});
|
|
174
59
|
});
|
|
@@ -1,74 +1,118 @@
|
|
|
1
|
+
import { createChartRuntime } from '@tanstack/charts/runtime';
|
|
2
|
+
import { createChartTooltipContent } from '@tanstack/charts/tooltip/model';
|
|
3
|
+
import type {
|
|
4
|
+
ChartDefinition,
|
|
5
|
+
ChartTooltipOptions,
|
|
6
|
+
SceneNode,
|
|
7
|
+
} from '@tanstack/charts/types';
|
|
1
8
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import {
|
|
9
|
+
import { candlestickChartDefinition } from './candlestick-chart';
|
|
3
10
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
cx: 50,
|
|
9
|
-
highY: 10, // high price → top of plot
|
|
10
|
-
lowY: 90, // low price → bottom of plot
|
|
11
|
-
openY: 70,
|
|
12
|
-
closeY: 30,
|
|
13
|
-
up: true,
|
|
14
|
-
};
|
|
11
|
+
const data = [
|
|
12
|
+
{ x: 0, open: 100, high: 104, low: 98, close: 102 },
|
|
13
|
+
{ x: 1, open: 102, high: 103, low: 97, close: 99 },
|
|
14
|
+
];
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
expect(shape.wick.height).toBe(80); // |lowY - highY|
|
|
21
|
-
expect(shape.wick.width).toBe(1); // default wickWidth
|
|
22
|
-
// Centered: left = cx - wickWidth/2.
|
|
23
|
-
expect(shape.wick.left).toBe(50 - 0.5);
|
|
16
|
+
const render2 = (definition: ChartDefinition<any, any, any>) => {
|
|
17
|
+
const scene = createChartRuntime().render(definition, {
|
|
18
|
+
width: 300,
|
|
19
|
+
height: 200,
|
|
24
20
|
});
|
|
21
|
+
const found: SceneNode[] = [];
|
|
22
|
+
const walk = (nodes: readonly SceneNode[]) => {
|
|
23
|
+
for (const node of nodes) {
|
|
24
|
+
if (node.kind === 'group') {
|
|
25
|
+
if (!node.focus) walk(node.children);
|
|
26
|
+
} else if (node.kind !== 'label') found.push(node);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
walk(scene.nodes);
|
|
30
|
+
return { scene, found };
|
|
31
|
+
};
|
|
25
32
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
expect(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
describe('candlestickChartDefinition', () => {
|
|
34
|
+
it('draws a wick and a body per candle, colored by direction', () => {
|
|
35
|
+
const { scene, found } = render2(candlestickChartDefinition({ data }));
|
|
36
|
+
const bodies = found.filter((n) => n.kind === 'rect');
|
|
37
|
+
expect(bodies.map((body) => body.style?.fill)).toEqual([
|
|
38
|
+
'rgba(34, 197, 94, 1)',
|
|
39
|
+
'rgba(239, 68, 68, 1)',
|
|
40
|
+
]);
|
|
41
|
+
// The y axis spans the lows and highs.
|
|
42
|
+
expect(scene.scales['y']!.domain[0]).toBeLessThanOrEqual(97);
|
|
43
|
+
expect(scene.scales['y']!.domain[1]).toBeGreaterThanOrEqual(104);
|
|
44
|
+
expect(found.some((n) => n.kind === 'rule' || n.kind === 'polyline')).toBe(
|
|
45
|
+
true,
|
|
46
|
+
);
|
|
33
47
|
});
|
|
34
48
|
|
|
35
|
-
it('
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
it('lists all four prices in the tooltip', () => {
|
|
50
|
+
const definition = candlestickChartDefinition({
|
|
51
|
+
data,
|
|
52
|
+
upColor: 'green',
|
|
53
|
+
downColor: 'red',
|
|
54
|
+
});
|
|
55
|
+
const { scene } = render2(definition);
|
|
56
|
+
const point = scene.points.find((p) => (p.datum as { x: number }).x === 1)!;
|
|
57
|
+
const content = createChartTooltipContent(
|
|
58
|
+
[point],
|
|
59
|
+
scene,
|
|
60
|
+
false,
|
|
61
|
+
definition.tooltip as unknown as ChartTooltipOptions,
|
|
62
|
+
point,
|
|
63
|
+
);
|
|
64
|
+
expect(content).toEqual({
|
|
65
|
+
title: '1',
|
|
66
|
+
color: 'red',
|
|
67
|
+
rows: [
|
|
68
|
+
{ label: 'Open', value: '102' },
|
|
69
|
+
{ label: 'High', value: '103' },
|
|
70
|
+
{ label: 'Low', value: '97' },
|
|
71
|
+
{ label: 'Close', value: '99' },
|
|
72
|
+
],
|
|
73
|
+
});
|
|
74
|
+
const custom = (
|
|
75
|
+
definition.tooltip as unknown as Required<ChartTooltipOptions>
|
|
76
|
+
).content;
|
|
77
|
+
const context = {
|
|
78
|
+
pinned: false,
|
|
79
|
+
xLabel: 'x',
|
|
80
|
+
yLabel: 'y',
|
|
81
|
+
formatX: (v: unknown) => `x${v}`,
|
|
82
|
+
formatY: (v: unknown) => `y${v}`,
|
|
44
83
|
};
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
expect(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
expect(shape.wick.left).toBe(50 - 1.5);
|
|
84
|
+
expect(custom([], context)).toEqual({ title: undefined, rows: [] });
|
|
85
|
+
// Points of other marks (say, a moving average added on top) get x/y rows.
|
|
86
|
+
expect(
|
|
87
|
+
custom(
|
|
88
|
+
[{ datum: { x: 1, y: 2 }, xValue: 1, yValue: 2 } as never],
|
|
89
|
+
context,
|
|
90
|
+
),
|
|
91
|
+
).toEqual({ title: 'x1', rows: [{ label: 'y', value: 'y2' }] });
|
|
92
|
+
expect(
|
|
93
|
+
custom([{ datum: null, xValue: 3, yValue: 4 } as never], context),
|
|
94
|
+
).toMatchObject({
|
|
95
|
+
title: 'x3',
|
|
96
|
+
});
|
|
97
|
+
const up = scene.points.find((p) => (p.datum as { x: number }).x === 0)!;
|
|
98
|
+
expect(
|
|
99
|
+
createChartTooltipContent(
|
|
100
|
+
[up],
|
|
101
|
+
scene,
|
|
102
|
+
false,
|
|
103
|
+
definition.tooltip as unknown as ChartTooltipOptions,
|
|
104
|
+
up,
|
|
105
|
+
),
|
|
106
|
+
).toMatchObject({ color: 'green' });
|
|
69
107
|
});
|
|
70
108
|
|
|
71
|
-
it('
|
|
72
|
-
|
|
109
|
+
it('can drop the tooltip, and clamps the body ratio', () => {
|
|
110
|
+
const definition = candlestickChartDefinition({
|
|
111
|
+
data,
|
|
112
|
+
tooltip: false,
|
|
113
|
+
bodyWidthRatio: 5,
|
|
114
|
+
});
|
|
115
|
+
expect(definition.tooltip).toBe(false);
|
|
116
|
+
expect(render2(definition).found.length).toBeGreaterThan(0);
|
|
73
117
|
});
|
|
74
118
|
});
|