@blotch/dolan 22.2.2 → 22.2.4
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 +41 -11
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/add.test.js +162 -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 +228 -34
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.js +367 -10
- 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 +169 -40
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +392 -27
- 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/theme.js +1 -1
- package/dist/commands/theme.js.map +1 -1
- package/dist/commands/update.d.ts +11 -0
- package/dist/commands/update.js +174 -58
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/update.test.js +587 -33
- package/dist/commands/update.test.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/lockfile.d.ts +7 -0
- package/dist/lockfile.js +36 -0
- package/dist/lockfile.js.map +1 -1
- package/dist/lockfile.test.d.ts +1 -0
- package/dist/lockfile.test.js +25 -0
- package/dist/lockfile.test.js.map +1 -0
- package/dist/registry.d.ts +14 -0
- package/dist/registry.js +78 -24
- package/dist/registry.js.map +1 -1
- package/dist/registry.test.js +119 -38
- package/dist/registry.test.js.map +1 -1
- package/dist/test-utils.d.ts +5 -0
- package/dist/test-utils.js +6 -1
- package/dist/test-utils.js.map +1 -1
- package/dist/testing/fire-lynx-event.d.ts +14 -0
- package/dist/testing/fire-lynx-event.js +19 -0
- package/dist/testing/fire-lynx-event.js.map +1 -0
- package/dist/testing/fire-lynx-event.test.d.ts +1 -0
- package/dist/testing/fire-lynx-event.test.js +44 -0
- package/dist/testing/fire-lynx-event.test.js.map +1 -0
- package/dist/testing/lynx-main-thread.d.ts +22 -0
- package/dist/testing/lynx-main-thread.js +11 -0
- package/dist/testing/lynx-main-thread.js.map +1 -0
- package/dist/testing/lynx-main-thread.test.d.ts +1 -0
- package/dist/testing/lynx-main-thread.test.js +24 -0
- package/dist/testing/lynx-main-thread.test.js.map +1 -0
- package/dist/testing/set-input-signal.d.ts +14 -0
- package/dist/testing/set-input-signal.js +21 -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/accordion/accordion.test.ts +158 -144
- package/dist/ui/components/accordion/accordion.ts +19 -14
- package/dist/ui/components/action-sheet/action-sheet.test.ts +283 -151
- package/dist/ui/components/action-sheet/action-sheet.ts +77 -43
- package/dist/ui/components/alert/alert.test.ts +67 -19
- package/dist/ui/components/alert/alert.ts +14 -16
- package/dist/ui/components/alert-dialog/alert-dialog.test.ts +208 -94
- package/dist/ui/components/alert-dialog/alert-dialog.ts +75 -38
- package/dist/ui/components/area-chart/area-chart.test.ts +134 -119
- 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/avatar/avatar.test.ts +89 -45
- package/dist/ui/components/badge/badge.test.ts +57 -23
- package/dist/ui/components/badge/badge.ts +12 -14
- package/dist/ui/components/bar-chart/bar-chart.test.ts +172 -45
- 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 +386 -128
- package/dist/ui/components/bottom-sheet/bottom-sheet.ts +170 -53
- package/dist/ui/components/button/button.test.ts +611 -2
- package/dist/ui/components/button/button.ts +434 -49
- package/dist/ui/components/button/index.ts +2 -0
- package/dist/ui/components/button-group/button-group.test.ts +484 -2
- package/dist/ui/components/button-group/button-group.ts +380 -68
- package/dist/ui/components/button-group/index.ts +3 -0
- package/dist/ui/components/candlestick-chart/candlestick-chart.test.ts +183 -58
- 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/card/card.test.ts +82 -62
- 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 +335 -0
- package/dist/ui/components/chart/chart-presets.ts +278 -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 +210 -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.test.ts +1017 -0
- package/dist/ui/components/chart/chart.ts +934 -0
- package/dist/ui/components/chart/index.ts +24 -0
- package/dist/ui/components/checkbox/checkbox.test.ts +124 -42
- package/dist/ui/components/checkbox/checkbox.ts +23 -23
- package/dist/ui/components/collapsible/collapsible.test.ts +158 -81
- package/dist/ui/components/collapsible/collapsible.ts +19 -14
- package/dist/ui/components/context-menu/context-menu.test.ts +224 -0
- package/dist/ui/components/context-menu/context-menu.ts +110 -0
- package/dist/ui/components/context-menu/index.ts +1 -0
- package/dist/ui/components/dialog/dialog.test.ts +213 -108
- package/dist/ui/components/dialog/dialog.ts +72 -35
- package/dist/ui/components/dock/dock-scroll.test.ts +130 -0
- package/dist/ui/components/dock/dock-scroll.ts +133 -0
- package/dist/ui/components/dock/dock.test.ts +749 -0
- package/dist/ui/components/dock/dock.ts +960 -0
- package/dist/ui/components/dock/index.ts +2 -0
- package/dist/ui/components/empty-state/empty-state.test.ts +28 -39
- package/dist/ui/components/glass/concentric-radius.test.ts +13 -0
- package/dist/ui/components/glass/concentric-radius.ts +17 -0
- package/dist/ui/components/glass/glass-design.test.ts +78 -0
- package/dist/ui/components/glass/glass-design.ts +119 -0
- package/dist/ui/components/glass/glass.test.ts +338 -0
- package/dist/ui/components/glass/glass.ts +360 -0
- package/dist/ui/components/glass/index.ts +18 -0
- package/dist/ui/components/icon/icon-theme.test.ts +169 -0
- package/dist/ui/components/icon/icon-theme.ts +227 -0
- package/dist/ui/components/icon/icon.test.ts +85 -25
- package/dist/ui/components/icon/icon.ts +38 -21
- package/dist/ui/components/input/input.test.ts +178 -101
- package/dist/ui/components/input/input.ts +15 -12
- package/dist/ui/components/label/label.test.ts +11 -24
- package/dist/ui/components/line-chart/index.ts +2 -3
- package/dist/ui/components/line-chart/line-chart.test.ts +149 -56
- package/dist/ui/components/line-chart/line-chart.ts +83 -241
- package/dist/ui/components/list/list.test.ts +119 -21
- package/dist/ui/components/list/list.ts +21 -15
- package/dist/ui/components/menu/index.ts +25 -0
- package/dist/ui/components/menu/menu-placement.test.ts +153 -0
- package/dist/ui/components/menu/menu-placement.ts +159 -0
- package/dist/ui/components/menu/menu-popup.test.ts +632 -0
- package/dist/ui/components/menu/menu-popup.ts +544 -0
- package/dist/ui/components/menu/menu.test.ts +429 -0
- package/dist/ui/components/menu/menu.ts +415 -0
- package/dist/ui/components/nav-drawer/nav-drawer.test.ts +435 -191
- package/dist/ui/components/nav-drawer/nav-drawer.ts +127 -56
- package/dist/ui/components/pagination/pagination.test.ts +177 -65
- package/dist/ui/components/pagination/pagination.ts +55 -8
- package/dist/ui/components/progress/progress.test.ts +102 -46
- package/dist/ui/components/progress/progress.ts +52 -54
- package/dist/ui/components/radio-group/radio-group.test.ts +128 -83
- package/dist/ui/components/radio-group/radio-group.ts +24 -24
- package/dist/ui/components/scatter-chart/index.ts +2 -3
- package/dist/ui/components/scatter-chart/scatter-chart.test.ts +131 -26
- package/dist/ui/components/scatter-chart/scatter-chart.ts +104 -250
- package/dist/ui/components/scroll-area/scroll-area.test.ts +95 -24
- package/dist/ui/components/scroll-area/scroll-area.ts +8 -8
- package/dist/ui/components/select/select.test.ts +138 -78
- package/dist/ui/components/select/select.ts +17 -11
- package/dist/ui/components/separator/separator.test.ts +18 -17
- package/dist/ui/components/sheet/sheet.test.ts +64 -11
- package/dist/ui/components/sheet/sheet.ts +9 -1
- package/dist/ui/components/skeleton/skeleton.test.ts +24 -7
- package/dist/ui/components/skeleton/skeleton.ts +10 -16
- package/dist/ui/components/spinner/spinner.test.ts +67 -22
- package/dist/ui/components/spinner/spinner.ts +48 -41
- package/dist/ui/components/switch/switch.test.ts +116 -46
- package/dist/ui/components/switch/switch.ts +8 -13
- package/dist/ui/components/tab-bar/index.ts +1 -0
- package/dist/ui/components/tab-bar/tab-bar.test.ts +280 -0
- package/dist/ui/components/tab-bar/tab-bar.ts +230 -0
- package/dist/ui/components/tabs/tabs.test.ts +215 -157
- package/dist/ui/components/tabs/tabs.ts +110 -118
- package/dist/ui/components/textarea/textarea.test.ts +206 -100
- package/dist/ui/components/textarea/textarea.ts +14 -12
- package/dist/ui/components/toast/toast.test.ts +436 -315
- package/dist/ui/components/toast/toast.ts +62 -55
- package/dist/ui/components/toggle/toggle.test.ts +247 -140
- package/dist/ui/theme/chart-colors.test.ts +35 -0
- package/dist/ui/theme/dark.css +46 -2
- package/dist/ui/theme/default.css +63 -7
- package/dist/ui/theme/icon-colors.test.ts +35 -0
- package/dist/ui/theme/rgb-channels.test.ts +84 -0
- package/dist/ui/theme/tailwind-build.test.ts +114 -0
- package/dist/ui/theme/tailwind-css.test.ts +83 -0
- package/dist/ui/theme/tailwind-plugin.test.ts +42 -2
- package/dist/ui/theme/tailwind-plugin.ts +98 -25
- package/dist/ui/theme/tailwind.css +113 -0
- package/dist/ui/utils/animate.test.ts +13 -1
- package/dist/utils/analyze.d.ts +14 -0
- package/dist/utils/analyze.js +15 -0
- package/dist/utils/analyze.js.map +1 -1
- package/dist/utils/analyze.test.js +14 -1
- package/dist/utils/analyze.test.js.map +1 -1
- package/dist/utils/installed.d.ts +29 -0
- package/dist/utils/installed.js +43 -0
- package/dist/utils/installed.js.map +1 -0
- package/dist/utils/installed.test.d.ts +1 -0
- package/dist/utils/installed.test.js +57 -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 +21 -3
- package/dist/utils/resolve-paths.js.map +1 -1
- package/dist/utils/resolve-paths.test.js +38 -2
- package/dist/utils/resolve-paths.test.js.map +1 -1
- package/dist/utils/tailwind.d.ts +25 -0
- package/dist/utils/tailwind.js +51 -0
- package/dist/utils/tailwind.js.map +1 -0
- package/dist/utils/tailwind.test.d.ts +1 -0
- package/dist/utils/tailwind.test.js +71 -0
- package/dist/utils/tailwind.test.js.map +1 -0
- package/package.json +13 -1
- package/dist/ui/components/area-chart/area-chart-render.test.ts +0 -121
- package/dist/ui/components/bar-chart/bar-chart-render.test.ts +0 -174
- package/dist/ui/components/button/button-render.test.ts +0 -113
- package/dist/ui/components/button-group/button-group-render.test.ts +0 -146
- package/dist/ui/components/candlestick-chart/candlestick-chart-render.test.ts +0 -174
- 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
- package/dist/ui/components/line-chart/line-chart-render.test.ts +0 -121
- package/dist/ui/components/scatter-chart/scatter-chart-render.test.ts +0 -157
|
@@ -1,525 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
type ChartDomain,
|
|
4
|
-
linearScale,
|
|
5
|
-
invertLinear,
|
|
6
|
-
niceNum,
|
|
7
|
-
niceScale,
|
|
8
|
-
generateTicks,
|
|
9
|
-
generateAlignedTicks,
|
|
10
|
-
isValueOutsideDomain,
|
|
11
|
-
gridlineOffset,
|
|
12
|
-
sampleSmoothLine,
|
|
13
|
-
clampWindow,
|
|
14
|
-
panWindow,
|
|
15
|
-
zoomWindow,
|
|
16
|
-
} from './cartesian-chart';
|
|
17
|
-
|
|
18
|
-
describe('linearScale', () => {
|
|
19
|
-
it('interpolates a value across the range', () => {
|
|
20
|
-
const scale = linearScale([0, 10], [0, 100]);
|
|
21
|
-
expect(scale(0)).toBe(0);
|
|
22
|
-
expect(scale(5)).toBe(50);
|
|
23
|
-
expect(scale(10)).toBe(100);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('supports a descending range (flipped y-axis)', () => {
|
|
27
|
-
const scale = linearScale([0, 100], [180, 0]);
|
|
28
|
-
expect(scale(0)).toBe(180);
|
|
29
|
-
expect(scale(50)).toBe(90);
|
|
30
|
-
expect(scale(100)).toBe(0);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('collapses a zero-width domain to the range midpoint', () => {
|
|
34
|
-
const scale = linearScale([5, 5], [0, 200]);
|
|
35
|
-
expect(scale(5)).toBe(100);
|
|
36
|
-
expect(scale(999)).toBe(100);
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe('niceNum', () => {
|
|
41
|
-
it('rounds a range up to a nice number', () => {
|
|
42
|
-
expect(niceNum(97, false)).toBe(100);
|
|
43
|
-
expect(niceNum(85, false)).toBe(100);
|
|
44
|
-
expect(niceNum(10, false)).toBe(10);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('snaps a step to the nearest nice number', () => {
|
|
48
|
-
expect(niceNum(25, true)).toBe(20);
|
|
49
|
-
expect(niceNum(20, true)).toBe(20);
|
|
50
|
-
expect(niceNum(2, true)).toBe(2);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('rounds down small-fraction values to 1 (round=true) and 1 (round=false)', () => {
|
|
54
|
-
// fraction < 1.5 branch under round=true.
|
|
55
|
-
expect(niceNum(11, true)).toBe(10);
|
|
56
|
-
// fraction <= 1 branch under round=false.
|
|
57
|
-
expect(niceNum(9, false)).toBe(10);
|
|
58
|
-
expect(niceNum(1, false)).toBe(1);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('rounds fractions 3–7 to 5 and larger to 10 (round=true)', () => {
|
|
62
|
-
// fraction=4.5 → nice 5.
|
|
63
|
-
expect(niceNum(45, true)).toBe(50);
|
|
64
|
-
// fraction=8 → nice 10.
|
|
65
|
-
expect(niceNum(80, true)).toBe(100);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('handles round=false fraction branches 2, 5, and 10', () => {
|
|
69
|
-
// fraction <= 2 → nice 2 (round=false).
|
|
70
|
-
expect(niceNum(15, false)).toBe(20);
|
|
71
|
-
// fraction <= 5 → nice 5 (round=false).
|
|
72
|
-
expect(niceNum(45, false)).toBe(50);
|
|
73
|
-
// fraction > 5 → nice 10 (round=false).
|
|
74
|
-
expect(niceNum(60, false)).toBe(100);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('returns 0 for non-positive input', () => {
|
|
78
|
-
expect(niceNum(0, true)).toBe(0);
|
|
79
|
-
expect(niceNum(-5, false)).toBe(0);
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
describe('niceScale', () => {
|
|
84
|
-
it('produces a rounded domain that contains the data', () => {
|
|
85
|
-
const { domain } = niceScale(3, 88, 5);
|
|
86
|
-
expect(domain[0]).toBeLessThanOrEqual(3);
|
|
87
|
-
expect(domain[1]).toBeGreaterThanOrEqual(88);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('generates ticks that span the domain endpoints', () => {
|
|
91
|
-
const { domain, ticks, step } = niceScale(0, 100, 5);
|
|
92
|
-
expect(step).toBeGreaterThan(0);
|
|
93
|
-
expect(ticks[0]).toBe(domain[0]);
|
|
94
|
-
expect(ticks[ticks.length - 1]).toBe(domain[1]);
|
|
95
|
-
for (const tick of ticks) {
|
|
96
|
-
expect(tick).toBeGreaterThanOrEqual(domain[0]);
|
|
97
|
-
expect(tick).toBeLessThanOrEqual(domain[1]);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('pads flat data around the single value', () => {
|
|
102
|
-
const { domain } = niceScale(5, 5, 5);
|
|
103
|
-
expect(domain[0]).toBeLessThan(5);
|
|
104
|
-
expect(domain[1]).toBeGreaterThan(5);
|
|
105
|
-
expect(Number.isFinite(domain[0])).toBe(true);
|
|
106
|
-
expect(Number.isFinite(domain[1])).toBe(true);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('pads flat data around zero with an absolute-pad fallback', () => {
|
|
110
|
-
// base === 0 branch: pad defaults to 1.
|
|
111
|
-
const { domain } = niceScale(0, 0, 5);
|
|
112
|
-
expect(domain[0]).toBeLessThan(0);
|
|
113
|
-
expect(domain[1]).toBeGreaterThan(0);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('handles non-finite inputs by falling back to a padded zero-based domain', () => {
|
|
117
|
-
// !Number.isFinite(lo0) branch.
|
|
118
|
-
const { domain } = niceScale(Number.NaN, 10, 5);
|
|
119
|
-
expect(Number.isFinite(domain[0])).toBe(true);
|
|
120
|
-
expect(Number.isFinite(domain[1])).toBe(true);
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
describe('generateTicks', () => {
|
|
125
|
-
it('evenly divides a domain into count ticks', () => {
|
|
126
|
-
expect(generateTicks([0, 10], 5)).toEqual([0, 2.5, 5, 7.5, 10]);
|
|
127
|
-
expect(generateTicks([0, 100], 3)).toEqual([0, 50, 100]);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('returns a single tick when count is 1', () => {
|
|
131
|
-
expect(generateTicks([0, 10], 1)).toEqual([0]);
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
// Regression guard for the "grid stays still while panning" bug. The report:
|
|
136
|
-
// zoomed-in pan moves the plotted content but the gridlines/tick marks stay
|
|
137
|
-
// put — only the axis numbers update. Root cause: the old zoomable-tick
|
|
138
|
-
// generator (generateTicks) divided the CURRENT window into a fixed fraction
|
|
139
|
-
// per tick, so every tick always lands at the same `i/(count-1)` pixel no
|
|
140
|
-
// matter where the window is. generateAlignedTicks fixes this by anchoring
|
|
141
|
-
// each tick to a fixed multiple of a step in DATA space instead.
|
|
142
|
-
describe('generateAlignedTicks', () => {
|
|
143
|
-
it('returns a fixed count of targetCount + 2 regardless of the window', () => {
|
|
144
|
-
expect(generateAlignedTicks([0, 100], 5)).toHaveLength(7);
|
|
145
|
-
expect(generateAlignedTicks([37, 57], 5)).toHaveLength(7);
|
|
146
|
-
expect(generateAlignedTicks([1000, 1050], 5)).toHaveLength(7);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('anchors ticks to fixed data-space multiples of a nice step — panning shifts WHICH multiples are visible, not the multiples themselves', () => {
|
|
150
|
-
// Two windows of the same span (20) as if panned right by 6 data units —
|
|
151
|
-
// a real drag never changes the window's span, only its position.
|
|
152
|
-
const before = generateAlignedTicks([40, 60], 5);
|
|
153
|
-
const after = generateAlignedTicks([46, 66], 5);
|
|
154
|
-
const step = 5; // niceNum(20 / 4, true)
|
|
155
|
-
for (const t of [...before, ...after]) {
|
|
156
|
-
expect(t % step).toBeCloseTo(0, 6);
|
|
157
|
-
}
|
|
158
|
-
// Ticks still inside the post-pan window must appear UNCHANGED in both
|
|
159
|
-
// arrays — proof the grid is anchored to fixed data values, not
|
|
160
|
-
// recomputed as a fraction of the (shifted) window.
|
|
161
|
-
const stillVisible = before.filter((t) => t >= 46 && t <= 60);
|
|
162
|
-
expect(stillVisible.length).toBeGreaterThan(0);
|
|
163
|
-
for (const t of stillVisible) {
|
|
164
|
-
expect(after).toContain(t);
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it('projects an anchored tick to a shifted pixel after a pan (the actual visual fix)', () => {
|
|
169
|
-
const rangePx = 200;
|
|
170
|
-
const project = (value: number, window: ChartDomain) =>
|
|
171
|
-
linearScale(window, [0, rangePx])(value);
|
|
172
|
-
|
|
173
|
-
const before: ChartDomain = [40, 60];
|
|
174
|
-
const after: ChartDomain = [46, 66]; // panned right by 6 data units
|
|
175
|
-
const common = generateAlignedTicks(before, 5).filter((t) =>
|
|
176
|
-
generateAlignedTicks(after, 5).includes(t),
|
|
177
|
-
);
|
|
178
|
-
expect(common.length).toBeGreaterThan(0);
|
|
179
|
-
for (const t of common) {
|
|
180
|
-
const pxBefore = project(t, before);
|
|
181
|
-
const pxAfter = project(t, after);
|
|
182
|
-
// The old (buggy) generateTicks-based ticks always re-projected to the
|
|
183
|
-
// exact same pixel here; an anchored tick must NOT.
|
|
184
|
-
expect(pxAfter).not.toBeCloseTo(pxBefore, 3);
|
|
185
|
-
// Panning the window +6 data units shifts every fixed value left by
|
|
186
|
-
// 6/20 of the range.
|
|
187
|
-
expect(pxBefore - pxAfter).toBeCloseTo((6 / 20) * rangePx, 6);
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
it('falls back to a step of 1 for a zero-width window instead of dividing by zero', () => {
|
|
192
|
-
expect(() => generateAlignedTicks([5, 5], 5)).not.toThrow();
|
|
193
|
-
expect(generateAlignedTicks([5, 5], 5).every(Number.isFinite)).toBe(true);
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
// Regression guard for the "top axis number cut in half" bug. The zoomable
|
|
198
|
-
// tick generator emits buffer ticks just past each edge of the window; their
|
|
199
|
-
// labels must be hidden, but a legitimate edge label (value exactly on the
|
|
200
|
-
// domain bound) must NOT be — hiding it, or clipping it at the container box,
|
|
201
|
-
// is what sliced the top "100" in half at 1:1.
|
|
202
|
-
describe('isValueOutsideDomain', () => {
|
|
203
|
-
it('treats a value exactly on either bound as inside (edge labels stay visible)', () => {
|
|
204
|
-
expect(isValueOutsideDomain(0, [0, 100])).toBe(false);
|
|
205
|
-
expect(isValueOutsideDomain(100, [0, 100])).toBe(false);
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('flags buffer ticks beyond either edge as outside', () => {
|
|
209
|
-
// generateAlignedTicks([0,100], 5) yields e.g. -20 and would extend past
|
|
210
|
-
// 100 — those must hide; the in-range multiples must not.
|
|
211
|
-
expect(isValueOutsideDomain(-20, [0, 100])).toBe(true);
|
|
212
|
-
expect(isValueOutsideDomain(120, [0, 100])).toBe(true);
|
|
213
|
-
expect(isValueOutsideDomain(40, [0, 100])).toBe(false);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('does not exclude an on-bound tick lost to float drift', () => {
|
|
217
|
-
// A window bound that arrived via pan/zoom arithmetic can land a hair off
|
|
218
|
-
// the tick value; the relative epsilon must keep it visible.
|
|
219
|
-
expect(isValueOutsideDomain(100, [0, 99.99999999])).toBe(false);
|
|
220
|
-
expect(isValueOutsideDomain(0, [0.00000001, 100])).toBe(false);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it('scales epsilon with the span (a genuinely-outside tick still hides on a large domain)', () => {
|
|
224
|
-
expect(isValueOutsideDomain(1_000_050, [0, 1_000_000])).toBe(true);
|
|
225
|
-
expect(isValueOutsideDomain(1_000_000, [0, 1_000_000])).toBe(false);
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// Regression guard for the "y-axis 0 gridline isn't visible" bug. The plot needs
|
|
230
|
-
// `overflow: hidden` to clip panned marks, but a 1px gridline whose value sits on
|
|
231
|
-
// the plot's far edge projects to exactly `extent` — one row/column past the box —
|
|
232
|
-
// so the clip eats it. gridlineOffset nudges an in-window edge line back inside;
|
|
233
|
-
// out-of-window buffer ticks stay put so they clip away instead of piling up.
|
|
234
|
-
describe('gridlineOffset', () => {
|
|
235
|
-
it('nudges an in-window far-edge line inward so overflow:hidden cannot clip it', () => {
|
|
236
|
-
// y = domain min projects to `extent` (bottom of a flipped y-scale); a 1px
|
|
237
|
-
// line there is fully outside, so it clamps to extent - thickness.
|
|
238
|
-
expect(gridlineOffset(0, 200, [0, 100], 200)).toBe(199);
|
|
239
|
-
// The near edge (top / left = 0) is already inside and is left untouched.
|
|
240
|
-
expect(gridlineOffset(100, 0, [0, 100], 200)).toBe(0);
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('leaves an interior line exactly where it projects', () => {
|
|
244
|
-
expect(gridlineOffset(50, 100, [0, 100], 200)).toBe(100);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('does not clamp an out-of-window buffer tick (it must clip away, not pile on the edge)', () => {
|
|
248
|
-
// generateAlignedTicks emits ticks just past each edge while panning. Below
|
|
249
|
-
// the window it projects past `extent`; above it projects negative. Both are
|
|
250
|
-
// returned as-is so the plot clip hides them rather than dragging them onto
|
|
251
|
-
// the visible edge as a spurious doubled line.
|
|
252
|
-
expect(gridlineOffset(-20, 260, [0, 100], 200)).toBe(260);
|
|
253
|
-
expect(gridlineOffset(120, -60, [0, 100], 200)).toBe(-60);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
it('honors a custom gridline thickness', () => {
|
|
257
|
-
expect(gridlineOffset(0, 200, [0, 100], 200, 2)).toBe(198);
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
describe('sampleSmoothLine', () => {
|
|
262
|
-
it('returns fewer-than-three points unchanged (no curve possible)', () => {
|
|
263
|
-
expect(sampleSmoothLine([])).toEqual([]);
|
|
264
|
-
expect(sampleSmoothLine([{ x: 1, y: 2 }])).toEqual([{ x: 1, y: 2 }]);
|
|
265
|
-
expect(
|
|
266
|
-
sampleSmoothLine([
|
|
267
|
-
{ x: 0, y: 0 },
|
|
268
|
-
{ x: 10, y: 5 },
|
|
269
|
-
]),
|
|
270
|
-
).toEqual([
|
|
271
|
-
{ x: 0, y: 0 },
|
|
272
|
-
{ x: 10, y: 5 },
|
|
273
|
-
]);
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
it('passes exactly through every original data point', () => {
|
|
277
|
-
const points = [
|
|
278
|
-
{ x: 0, y: 0 },
|
|
279
|
-
{ x: 1, y: 8 },
|
|
280
|
-
{ x: 2, y: 3 },
|
|
281
|
-
{ x: 3, y: 10 },
|
|
282
|
-
];
|
|
283
|
-
const curve = sampleSmoothLine(points, 8);
|
|
284
|
-
for (const p of points) {
|
|
285
|
-
const hit = curve.find((c) => Math.abs(c.x - p.x) < 1e-9);
|
|
286
|
-
expect(hit).toBeDefined();
|
|
287
|
-
expect(hit?.y).toBeCloseTo(p.y);
|
|
288
|
-
}
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
it('keeps a straight line straight (collinear points do not bow)', () => {
|
|
292
|
-
// y = 2x sampled at the curve's x values must stay on the line.
|
|
293
|
-
const curve = sampleSmoothLine(
|
|
294
|
-
[
|
|
295
|
-
{ x: 0, y: 0 },
|
|
296
|
-
{ x: 5, y: 10 },
|
|
297
|
-
{ x: 10, y: 20 },
|
|
298
|
-
],
|
|
299
|
-
6,
|
|
300
|
-
);
|
|
301
|
-
for (const c of curve) {
|
|
302
|
-
expect(c.y).toBeCloseTo(c.x * 2);
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
it('never overshoots the data range (monotone: no bulge past a peak)', () => {
|
|
307
|
-
const points = [
|
|
308
|
-
{ x: 0, y: 0 },
|
|
309
|
-
{ x: 1, y: 10 },
|
|
310
|
-
{ x: 2, y: 10 },
|
|
311
|
-
{ x: 3, y: 0 },
|
|
312
|
-
];
|
|
313
|
-
const curve = sampleSmoothLine(points, 16);
|
|
314
|
-
const ys = curve.map((c) => c.y);
|
|
315
|
-
// The plateau at 10 is the max and 0 the min — a monotone cubic must stay
|
|
316
|
-
// inside them (Catmull-Rom would overshoot above 10 approaching the plateau).
|
|
317
|
-
expect(Math.max(...ys)).toBeLessThanOrEqual(10 + 1e-9);
|
|
318
|
-
expect(Math.min(...ys)).toBeGreaterThanOrEqual(0 - 1e-9);
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
it('emits a denser, x-ascending point set', () => {
|
|
322
|
-
const curve = sampleSmoothLine(
|
|
323
|
-
[
|
|
324
|
-
{ x: 0, y: 0 },
|
|
325
|
-
{ x: 1, y: 5 },
|
|
326
|
-
{ x: 2, y: 2 },
|
|
327
|
-
],
|
|
328
|
-
10,
|
|
329
|
-
);
|
|
330
|
-
// 2 segments × 10 samples + 1 closing point.
|
|
331
|
-
expect(curve).toHaveLength(21);
|
|
332
|
-
for (let i = 1; i < curve.length; i++) {
|
|
333
|
-
expect(curve[i].x).toBeGreaterThanOrEqual(curve[i - 1].x);
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
it('applies the Fritsch-Carlson tangent constraint on steep slopes (monotone clamp)', () => {
|
|
338
|
-
// Data with a steep rise then steep drop triggers the `magnitude > 9`
|
|
339
|
-
// tangent-clamp branch inside sampleSmoothLine.
|
|
340
|
-
const points = [
|
|
341
|
-
{ x: 0, y: 0 },
|
|
342
|
-
{ x: 1, y: 0.01 },
|
|
343
|
-
{ x: 2, y: 100 },
|
|
344
|
-
{ x: 3, y: 0.01 },
|
|
345
|
-
{ x: 4, y: 0 },
|
|
346
|
-
];
|
|
347
|
-
const curve = sampleSmoothLine(points, 12);
|
|
348
|
-
expect(curve.length).toBeGreaterThan(0);
|
|
349
|
-
// No sample exceeds the actual data range — the clamp did its job.
|
|
350
|
-
for (const c of curve) {
|
|
351
|
-
expect(c.y).toBeLessThanOrEqual(100 + 1e-9);
|
|
352
|
-
expect(c.y).toBeGreaterThanOrEqual(0 - 1e-9);
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
it('treats a duplicate-x pair (zero horizontal gap) as a flat secant', () => {
|
|
357
|
-
// Covers the `dx === 0 ? 0 : ...` branch. Two consecutive points share an x.
|
|
358
|
-
const curve = sampleSmoothLine(
|
|
359
|
-
[
|
|
360
|
-
{ x: 0, y: 0 },
|
|
361
|
-
{ x: 5, y: 3 },
|
|
362
|
-
{ x: 5, y: 8 },
|
|
363
|
-
{ x: 10, y: 10 },
|
|
364
|
-
],
|
|
365
|
-
6,
|
|
366
|
-
);
|
|
367
|
-
expect(curve.length).toBeGreaterThan(0);
|
|
368
|
-
for (const c of curve) expect(Number.isFinite(c.y)).toBe(true);
|
|
369
|
-
});
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
describe('invertLinear', () => {
|
|
373
|
-
it('is the inverse of linearScale', () => {
|
|
374
|
-
const domain = [0, 10] as const;
|
|
375
|
-
const range = [0, 100] as const;
|
|
376
|
-
const scale = linearScale(domain, range);
|
|
377
|
-
for (const v of [0, 2.5, 5, 7.5, 10]) {
|
|
378
|
-
expect(invertLinear(domain, range, scale(v))).toBeCloseTo(v);
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
it('inverts a descending (flipped y) range', () => {
|
|
383
|
-
// linearScale([0,100],[180,0])(50) === 90 → invert back to 50.
|
|
384
|
-
expect(invertLinear([0, 100], [180, 0], 90)).toBeCloseTo(50);
|
|
385
|
-
expect(invertLinear([0, 100], [180, 0], 180)).toBeCloseTo(0);
|
|
386
|
-
expect(invertLinear([0, 100], [180, 0], 0)).toBeCloseTo(100);
|
|
387
|
-
});
|
|
388
|
-
|
|
389
|
-
it('collapses a zero-width range to the domain lower bound', () => {
|
|
390
|
-
expect(invertLinear([2, 8], [50, 50], 999)).toBe(2);
|
|
391
|
-
});
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
describe('clampWindow', () => {
|
|
395
|
-
it('leaves a window already inside the base untouched', () => {
|
|
396
|
-
expect(clampWindow([0, 10], [2, 6])).toEqual([2, 6]);
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
it('slides a window back inside the base, preserving its span', () => {
|
|
400
|
-
expect(clampWindow([0, 10], [8, 14])).toEqual([4, 10]);
|
|
401
|
-
expect(clampWindow([0, 10], [-3, 2])).toEqual([0, 5]);
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
it('caps a window wider than the base to the whole base', () => {
|
|
405
|
-
expect(clampWindow([0, 10], [-5, 20])).toEqual([0, 10]);
|
|
406
|
-
});
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
describe('panWindow', () => {
|
|
410
|
-
it('shifts the window by a data delta', () => {
|
|
411
|
-
expect(panWindow([0, 10], [2, 6], 1)).toEqual([3, 7]);
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
it('stops (does not resize) at either edge', () => {
|
|
415
|
-
// Preserves the span of 4, clamped against the right and left edges.
|
|
416
|
-
expect(panWindow([0, 10], [2, 6], 10)).toEqual([6, 10]);
|
|
417
|
-
expect(panWindow([0, 10], [2, 6], -10)).toEqual([0, 4]);
|
|
418
|
-
});
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
// Regression guard for the pan interaction. The bug: on iOS AND Android the
|
|
422
|
-
// native pan handler gates onStart/onEnd behind onBegin having fired, so a pan
|
|
423
|
-
// that registers only onStart/onUpdate/onEnd never snapshots the start window and
|
|
424
|
-
// #onPan re-reads the CURRENT window every frame — making the pan compound instead
|
|
425
|
-
// of tracking the finger 1:1. The fix registers onBegin to anchor the window once
|
|
426
|
-
// at gesture start. These tests lock the geometry that anchoring must produce, and
|
|
427
|
-
// pin down the compounding failure mode so it can't silently return.
|
|
428
|
-
describe('pan tracks the finger 1:1 (window anchored at gesture start)', () => {
|
|
429
|
-
/**
|
|
430
|
-
* Projects a data x into plot pixels through a given visible window, matching how
|
|
431
|
-
* xScale maps the effective domain across the plot range.
|
|
432
|
-
*/
|
|
433
|
-
const projectX = (
|
|
434
|
-
dataX: number,
|
|
435
|
-
window: readonly [number, number],
|
|
436
|
-
rangePx: number,
|
|
437
|
-
) => ((dataX - window[0]) / (window[1] - window[0])) * rangePx;
|
|
438
|
-
|
|
439
|
-
it('moves projected content exactly translationX pixels for any cumulative delta', () => {
|
|
440
|
-
const base: ChartDomain = [0, 100];
|
|
441
|
-
const start: ChartDomain = [40, 60]; // zoomed 5× (span 20 of a 100 domain)
|
|
442
|
-
const rangePx = 200;
|
|
443
|
-
const dataPerPx = (start[1] - start[0]) / rangePx; // 0.1 data units / px
|
|
444
|
-
|
|
445
|
-
const pointX = 45; // any data point inside the window
|
|
446
|
-
const startPx = projectX(pointX, start, rangePx);
|
|
447
|
-
|
|
448
|
-
// A steady drag is reported as a CUMULATIVE translation (0 → growing). Each
|
|
449
|
-
// frame maps it against the FIXED start window (what onBegin snapshots).
|
|
450
|
-
for (const translationX of [5, 12, 40, -18, -35]) {
|
|
451
|
-
const window = panWindow(base, start, -translationX * dataPerPx);
|
|
452
|
-
const nowPx = projectX(pointX, window, rangePx);
|
|
453
|
-
// 1:1: the point moved on screen by exactly the finger's travel.
|
|
454
|
-
expect(nowPx - startPx).toBeCloseTo(translationX, 6);
|
|
455
|
-
}
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
it('compounds (the bug) when the window is re-read every frame instead of anchored', () => {
|
|
459
|
-
const base: ChartDomain = [0, 100];
|
|
460
|
-
const rangePx = 200;
|
|
461
|
-
const dataPerPx = 20 / rangePx; // 0.1
|
|
462
|
-
|
|
463
|
-
// Correct path: fixed start window, cumulative translation. A 10 px/frame drag
|
|
464
|
-
// over 3 frames (cumulative 10, 20, 30) shifts the window left by 30·0.1 = 3.
|
|
465
|
-
const start: ChartDomain = [40, 60];
|
|
466
|
-
const anchored = panWindow(base, start, -30 * dataPerPx);
|
|
467
|
-
expect(anchored[0]).toBeCloseTo(37, 6);
|
|
468
|
-
|
|
469
|
-
// Buggy path: use the CURRENT window as the base each frame (because the start
|
|
470
|
-
// was never snapshotted). The same drag drives the window much further left —
|
|
471
|
-
// the shift accumulates super-linearly.
|
|
472
|
-
let window: ChartDomain = [40, 60];
|
|
473
|
-
for (const cumulative of [10, 20, 30]) {
|
|
474
|
-
window = panWindow(base, window, -cumulative * dataPerPx);
|
|
475
|
-
}
|
|
476
|
-
expect(window[0]).toBeLessThan(37);
|
|
477
|
-
// Concretely: 40 → 39 → 37 → 34, i.e. 2× the correct shift after 3 frames.
|
|
478
|
-
expect(window[0]).toBeCloseTo(34, 6);
|
|
479
|
-
});
|
|
480
|
-
});
|
|
481
|
-
|
|
482
|
-
describe('zoomWindow', () => {
|
|
483
|
-
it('zooms in around the focal value, keeping it fixed', () => {
|
|
484
|
-
// 2× zoom on the center halves the span and stays centered.
|
|
485
|
-
expect(zoomWindow([0, 10], [0, 10], 2, 5, 8)).toEqual([2.5, 7.5]);
|
|
486
|
-
// Focal at the left edge keeps that edge pinned.
|
|
487
|
-
expect(zoomWindow([0, 10], [0, 10], 2, 0, 8)).toEqual([0, 5]);
|
|
488
|
-
});
|
|
489
|
-
|
|
490
|
-
it('clamps zoom-in to maxZoom (min span = baseSpan / maxZoom)', () => {
|
|
491
|
-
const [lo, hi] = zoomWindow([0, 10], [0, 10], 100, 5, 8);
|
|
492
|
-
expect(hi - lo).toBeCloseTo(10 / 8); // 1.25, not 0.1
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
it('never zooms out past the full base domain', () => {
|
|
496
|
-
expect(zoomWindow([0, 10], [2.5, 7.5], 0.1, 5, 8)).toEqual([0, 10]);
|
|
497
|
-
});
|
|
498
|
-
|
|
499
|
-
it('honors minZoom as an upper bound on the visible span', () => {
|
|
500
|
-
// minZoom 2 → the window can never be wider than baseSpan / 2 = 5.
|
|
501
|
-
const [lo, hi] = zoomWindow([0, 10], [3, 4], 0.01, 3.5, 8, 2);
|
|
502
|
-
expect(hi - lo).toBeCloseTo(5);
|
|
503
|
-
});
|
|
504
|
-
|
|
505
|
-
it('falls back to factor=1 when the caller passes 0 (defensive divide-by-zero guard)', () => {
|
|
506
|
-
// Covers the `factor || 1` branch.
|
|
507
|
-
const window = zoomWindow([0, 10], [0, 10], 0, 5, 8);
|
|
508
|
-
// With factor=0 → treated as 1, the span stays.
|
|
509
|
-
expect(window[1] - window[0]).toBeCloseTo(10);
|
|
510
|
-
});
|
|
511
|
-
|
|
512
|
-
it('centers a zero-span current window at the focal (fallback fraction 0.5)', () => {
|
|
513
|
-
// Covers the `span === 0 ? 0.5 : ...` branch.
|
|
514
|
-
const window = zoomWindow([0, 10], [5, 5], 1, 5, 8);
|
|
515
|
-
expect(window[0]).toBeLessThanOrEqual(5);
|
|
516
|
-
expect(window[1]).toBeGreaterThanOrEqual(5);
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
it('falls back to baseSpan when maxZoom or minZoom are non-positive', () => {
|
|
520
|
-
// Covers `maxZoom > 0` and `minZoom > 0` false branches.
|
|
521
|
-
expect(() => zoomWindow([0, 10], [0, 10], 1, 5, 0, 1)).not.toThrow();
|
|
522
|
-
expect(() => zoomWindow([0, 10], [0, 10], 1, 5, 8, 0)).not.toThrow();
|
|
523
|
-
expect(() => zoomWindow([0, 10], [0, 10], 1, 5, -1, -1)).not.toThrow();
|
|
524
|
-
});
|
|
525
|
-
});
|