@363045841yyt/klinechart-core 0.7.3 → 0.7.5
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/README.md +201 -201
- package/README.zh-CN.md +201 -201
- package/dist/controllers/index.d.ts +1 -0
- package/dist/controllers/index.d.ts.map +1 -1
- package/dist/controllers/index.js +1 -0
- package/dist/controllers/index.js.map +1 -1
- package/dist/engine/chart.d.ts +11 -19
- package/dist/engine/chart.d.ts.map +1 -1
- package/dist/engine/chart.js +92 -109
- package/dist/engine/chart.js.map +1 -1
- package/dist/engine/renderers/Indicator/indicatorData.d.ts +1 -0
- package/dist/engine/renderers/Indicator/indicatorData.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/indicatorData.js +1 -1
- package/dist/engine/renderers/Indicator/indicatorData.js.map +1 -1
- package/dist/engine/renderers/webgl/candleSurface.js +47 -47
- package/dist/engine/subPaneManager.d.ts +4 -0
- package/dist/engine/subPaneManager.d.ts.map +1 -1
- package/dist/engine/subPaneManager.js +13 -0
- package/dist/engine/subPaneManager.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -2
- package/dist/version.js.map +1 -1
- package/package.json +129 -122
- package/src/__tests__/signal.test.ts +124 -124
- package/src/config/chartSettings.ts +66 -66
- package/src/controllers/__tests__/drawing.test.ts +214 -214
- package/src/controllers/__tests__/indicatorSelector.test.ts +481 -481
- package/src/controllers/__tests__/toolbar.test.ts +225 -225
- package/src/controllers/createChartController.ts +665 -665
- package/src/controllers/createDrawingController.ts +96 -96
- package/src/controllers/createIndicatorSelectorController.ts +307 -307
- package/src/controllers/createToolbarController.ts +146 -146
- package/src/controllers/index.ts +20 -19
- package/src/controllers/types.ts +284 -284
- package/src/engine/__tests__/chart.dpr.test.ts +401 -401
- package/src/engine/__tests__/paneRenderer.resize.test.ts +92 -92
- package/src/engine/chart-store.ts +121 -121
- package/src/engine/chart.d.ts +617 -617
- package/src/engine/chart.ts +2803 -2815
- package/src/engine/controller/__tests__/interaction.dpr.test.ts +259 -259
- package/src/engine/controller/interaction.ts +722 -722
- package/src/engine/controller/markerInteraction.ts +130 -130
- package/src/engine/controller/pinchTracker.ts +82 -82
- package/src/engine/controller/tooltipPosition.ts +48 -48
- package/src/engine/draw/__tests__/pixelAlign.spec.ts +176 -176
- package/src/engine/draw/pixelAlign.ts +259 -259
- package/src/engine/drawing/index.ts +655 -655
- package/src/engine/drawing/interaction.ts +842 -842
- package/src/engine/drawing/plugin.ts +343 -343
- package/src/engine/indicators/__tests__/__fixtures__/golden/atr.json +38 -38
- package/src/engine/indicators/__tests__/__fixtures__/golden/dema.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/hma.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/index.ts +55 -55
- package/src/engine/indicators/__tests__/__fixtures__/golden/kama.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/tema.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/wma.json +40 -40
- package/src/engine/indicators/__tests__/__fixtures__/synthetic.ts +65 -65
- package/src/engine/indicators/__tests__/_propertyAssertions.ts +76 -76
- package/src/engine/indicators/__tests__/atr.test.ts +153 -153
- package/src/engine/indicators/__tests__/calculators.test.ts +614 -614
- package/src/engine/indicators/__tests__/cmf-mfi.test.ts +100 -100
- package/src/engine/indicators/__tests__/dema.test.ts +73 -73
- package/src/engine/indicators/__tests__/donchian.test.ts +70 -70
- package/src/engine/indicators/__tests__/hma.test.ts +73 -73
- package/src/engine/indicators/__tests__/ichimoku.test.ts +105 -105
- package/src/engine/indicators/__tests__/kama.test.ts +80 -80
- package/src/engine/indicators/__tests__/keltner.test.ts +65 -65
- package/src/engine/indicators/__tests__/pivot-fib.test.ts +110 -110
- package/src/engine/indicators/__tests__/roc.test.ts +68 -68
- package/src/engine/indicators/__tests__/sar.test.ts +86 -86
- package/src/engine/indicators/__tests__/scheduler.test.ts +831 -831
- package/src/engine/indicators/__tests__/soa.test.ts +533 -533
- package/src/engine/indicators/__tests__/structure.test.ts +110 -110
- package/src/engine/indicators/__tests__/supertrend.test.ts +65 -65
- package/src/engine/indicators/__tests__/tema.test.ts +68 -68
- package/src/engine/indicators/__tests__/trix.test.ts +70 -70
- package/src/engine/indicators/__tests__/volatility.test.ts +117 -117
- package/src/engine/indicators/__tests__/volume.test.ts +115 -115
- package/src/engine/indicators/__tests__/volumeProfile.test.ts +74 -74
- package/src/engine/indicators/__tests__/vwap.test.ts +69 -69
- package/src/engine/indicators/__tests__/wma.test.ts +112 -112
- package/src/engine/indicators/__tests__/zones.test.ts +95 -95
- package/src/engine/indicators/atrState.ts +27 -27
- package/src/engine/indicators/bollState.ts +51 -51
- package/src/engine/indicators/calculators.ts +2593 -2593
- package/src/engine/indicators/cciState.ts +25 -25
- package/src/engine/indicators/chaikinVolState.ts +32 -32
- package/src/engine/indicators/cmfState.ts +27 -27
- package/src/engine/indicators/demaState.ts +27 -27
- package/src/engine/indicators/donchianState.ts +43 -43
- package/src/engine/indicators/eneState.ts +43 -43
- package/src/engine/indicators/expmaState.ts +43 -43
- package/src/engine/indicators/fastkState.ts +25 -25
- package/src/engine/indicators/fibState.ts +41 -41
- package/src/engine/indicators/hmaState.ts +27 -27
- package/src/engine/indicators/hvState.ts +28 -28
- package/src/engine/indicators/ichimokuState.ts +70 -70
- package/src/engine/indicators/indicator.worker.ts +169 -169
- package/src/engine/indicators/indicatorDefinitionRegistry.ts +62 -62
- package/src/engine/indicators/indicatorMetadata.ts +110 -110
- package/src/engine/indicators/indicatorRegistry.ts +106 -106
- package/src/engine/indicators/indicatorRuntime.ts +1548 -1548
- package/src/engine/indicators/kamaState.ts +34 -34
- package/src/engine/indicators/keltnerState.ts +49 -49
- package/src/engine/indicators/kstState.ts +42 -42
- package/src/engine/indicators/maState.ts +36 -36
- package/src/engine/indicators/macdState.ts +76 -76
- package/src/engine/indicators/mfiState.ts +27 -27
- package/src/engine/indicators/momState.ts +25 -25
- package/src/engine/indicators/obvState.ts +25 -25
- package/src/engine/indicators/parkinsonState.ts +28 -28
- package/src/engine/indicators/pivotState.ts +51 -51
- package/src/engine/indicators/pvtState.ts +25 -25
- package/src/engine/indicators/rocState.ts +27 -27
- package/src/engine/indicators/rsiState.ts +65 -65
- package/src/engine/indicators/sarState.ts +41 -41
- package/src/engine/indicators/scheduler.ts +1205 -1205
- package/src/engine/indicators/soa.ts +352 -352
- package/src/engine/indicators/stateComposer.ts +1262 -1262
- package/src/engine/indicators/stochState.ts +26 -26
- package/src/engine/indicators/structureState.ts +69 -69
- package/src/engine/indicators/supertrendState.ts +37 -37
- package/src/engine/indicators/temaState.ts +27 -27
- package/src/engine/indicators/trixState.ts +35 -35
- package/src/engine/indicators/vmaState.ts +27 -27
- package/src/engine/indicators/volumeProfileState.ts +63 -63
- package/src/engine/indicators/vwapState.ts +29 -29
- package/src/engine/indicators/wmaState.ts +27 -27
- package/src/engine/indicators/wmsrState.ts +25 -25
- package/src/engine/indicators/workerProtocol.ts +613 -613
- package/src/engine/indicators/zonesState.ts +47 -47
- package/src/engine/layout/pane.ts +161 -161
- package/src/engine/marker/registry.ts +265 -265
- package/src/engine/paneRenderer.ts +169 -169
- package/src/engine/renderers/Indicator/atr.ts +237 -237
- package/src/engine/renderers/Indicator/boll.ts +317 -317
- package/src/engine/renderers/Indicator/cci.ts +275 -275
- package/src/engine/renderers/Indicator/chaikinVol.ts +138 -138
- package/src/engine/renderers/Indicator/cmf.ts +137 -137
- package/src/engine/renderers/Indicator/dema.ts +136 -136
- package/src/engine/renderers/Indicator/donchian.ts +137 -137
- package/src/engine/renderers/Indicator/ene.ts +271 -271
- package/src/engine/renderers/Indicator/expma.ts +197 -197
- package/src/engine/renderers/Indicator/fastk.ts +316 -316
- package/src/engine/renderers/Indicator/fib.ts +141 -141
- package/src/engine/renderers/Indicator/hma.ts +136 -136
- package/src/engine/renderers/Indicator/hv.ts +124 -124
- package/src/engine/renderers/Indicator/ichimoku.ts +181 -181
- package/src/engine/renderers/Indicator/index.ts +241 -241
- package/src/engine/renderers/Indicator/indicatorData.ts +650 -650
- package/src/engine/renderers/Indicator/kama.ts +136 -136
- package/src/engine/renderers/Indicator/keltner.ts +137 -137
- package/src/engine/renderers/Indicator/kst.ts +302 -302
- package/src/engine/renderers/Indicator/ma.ts +200 -200
- package/src/engine/renderers/Indicator/macd.ts +477 -477
- package/src/engine/renderers/Indicator/macdLegend.ts +141 -141
- package/src/engine/renderers/Indicator/mainIndicatorLegend.ts +272 -272
- package/src/engine/renderers/Indicator/mfi.ts +142 -142
- package/src/engine/renderers/Indicator/mom.ts +311 -311
- package/src/engine/renderers/Indicator/obv.ts +123 -123
- package/src/engine/renderers/Indicator/parkinson.ts +124 -124
- package/src/engine/renderers/Indicator/pivot.ts +131 -131
- package/src/engine/renderers/Indicator/pvt.ts +123 -123
- package/src/engine/renderers/Indicator/roc.ts +143 -143
- package/src/engine/renderers/Indicator/rsi.ts +390 -390
- package/src/engine/renderers/Indicator/sar.ts +113 -113
- package/src/engine/renderers/Indicator/scale/atr_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/cci_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/fastk_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/indicator_scale.ts +204 -204
- package/src/engine/renderers/Indicator/scale/kst_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/macd_scale.ts +22 -22
- package/src/engine/renderers/Indicator/scale/mom_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/rsi_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/stoch_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/volume_scale.ts +26 -26
- package/src/engine/renderers/Indicator/scale/wmsr_scale.ts +19 -19
- package/src/engine/renderers/Indicator/stoch.ts +359 -359
- package/src/engine/renderers/Indicator/structure.ts +126 -126
- package/src/engine/renderers/Indicator/subPaneConfig.ts +265 -265
- package/src/engine/renderers/Indicator/supertrend.ts +115 -115
- package/src/engine/renderers/Indicator/tema.ts +136 -136
- package/src/engine/renderers/Indicator/trix.ts +158 -158
- package/src/engine/renderers/Indicator/vma.ts +124 -124
- package/src/engine/renderers/Indicator/volumeProfile.ts +125 -125
- package/src/engine/renderers/Indicator/vwap.ts +123 -123
- package/src/engine/renderers/Indicator/wma.ts +136 -136
- package/src/engine/renderers/Indicator/wmsr.ts +328 -328
- package/src/engine/renderers/Indicator/zones.ts +104 -104
- package/src/engine/renderers/__tests__/boll.renderer.test.ts +314 -314
- package/src/engine/renderers/__tests__/ene.renderer.test.ts +305 -305
- package/src/engine/renderers/__tests__/expma.renderer.test.ts +279 -279
- package/src/engine/renderers/__tests__/ma.renderer.test.ts +426 -426
- package/src/engine/renderers/__tests__/mainIndicatorLegend.renderer.test.ts +502 -502
- package/src/engine/renderers/__tests__/yAxis.renderer.test.ts +173 -173
- package/src/engine/renderers/candle.ts +459 -459
- package/src/engine/renderers/crosshair.ts +69 -69
- package/src/engine/renderers/customMarkers.ts +162 -162
- package/src/engine/renderers/extremaMarkers.ts +246 -246
- package/src/engine/renderers/gridLines.ts +90 -90
- package/src/engine/renderers/lastPrice.ts +97 -97
- package/src/engine/renderers/paneTitle.ts +136 -136
- package/src/engine/renderers/subVolume.ts +236 -236
- package/src/engine/renderers/timeAxis.ts +121 -121
- package/src/engine/renderers/webgl/candleSurface.ts +955 -955
- package/src/engine/renderers/webgl/sharedWebGLSurface.ts +146 -146
- package/src/engine/renderers/yAxis.ts +105 -105
- package/src/engine/scale/__tests__/logFormula.spec.ts +148 -148
- package/src/engine/scale/logFormula.ts +130 -130
- package/src/engine/scale/price.ts +39 -39
- package/src/engine/scale/priceScale.ts +264 -264
- package/src/engine/subPaneManager.ts +442 -427
- package/src/engine/theme/colors.ts +642 -642
- package/src/engine/theme/fonts.ts +20 -20
- package/src/engine/utils/klineConfig.ts +49 -49
- package/src/engine/utils/tickCount.ts +11 -11
- package/src/engine/utils/tickPosition.ts +214 -214
- package/src/engine/utils/zoom.ts +83 -83
- package/src/engine/viewport/viewport.ts +67 -67
- package/src/index.ts +3 -3
- package/src/plugin/ConfigManager.ts +93 -93
- package/src/plugin/EventBus.ts +77 -77
- package/src/plugin/HookSystem.ts +106 -106
- package/src/plugin/PluginHost.ts +243 -243
- package/src/plugin/PluginRegistry.ts +92 -92
- package/src/plugin/StateStore.ts +73 -73
- package/src/plugin/index.ts +19 -19
- package/src/plugin/rendererPluginManager.ts +368 -368
- package/src/plugin/stateKeys.ts +8 -8
- package/src/plugin/types.ts +526 -526
- package/src/reactivity/index.ts +2 -2
- package/src/reactivity/signal.ts +119 -119
- package/src/semantic/controller.ts +251 -251
- package/src/semantic/drawShape.ts +260 -260
- package/src/semantic/index.ts +28 -28
- package/src/semantic/schema.json +256 -256
- package/src/semantic/types.ts +251 -251
- package/src/semantic/validator.ts +349 -349
- package/src/types/kLine.ts +13 -13
- package/src/types/price.ts +56 -56
- package/src/types/volumePrice.ts +33 -33
- package/src/utils/dateFormat.ts +208 -208
- package/src/utils/kLineDraw/axis.ts +562 -562
- package/src/utils/priceToY.ts +34 -34
- package/src/utils/volumePrice.ts +202 -202
- package/src/version.ts +1 -1
|
@@ -1,314 +1,314 @@
|
|
|
1
|
-
// @ts-nocheck - Test file with intentional type relaxations for mocking
|
|
2
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
3
|
-
import { createBOLLRendererPlugin } from '../Indicator/boll'
|
|
4
|
-
import { BOLL_STATE_KEY, type BOLLRenderState } from '@/core/indicators/bollState'
|
|
5
|
-
import { BOLL_COLORS } from '@/core/theme/colors'
|
|
6
|
-
import type { PluginHost, RenderContext, RendererPluginWithHost } from '@/plugin'
|
|
7
|
-
import type { KLineData } from '@/types/price'
|
|
8
|
-
import type { Pane } from '@/core/layout/pane'
|
|
9
|
-
|
|
10
|
-
// Type helper for tests
|
|
11
|
-
interface TestableBOLLRenderer extends RendererPluginWithHost {
|
|
12
|
-
draw: (context: RenderContext) => void
|
|
13
|
-
getConfig: () => Record<string, unknown>
|
|
14
|
-
setConfig: (config: Record<string, unknown>) => void
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function createMockCanvasContext(): CanvasRenderingContext2D {
|
|
18
|
-
return {
|
|
19
|
-
save: vi.fn(),
|
|
20
|
-
restore: vi.fn(),
|
|
21
|
-
translate: vi.fn(),
|
|
22
|
-
beginPath: vi.fn(),
|
|
23
|
-
moveTo: vi.fn(),
|
|
24
|
-
lineTo: vi.fn(),
|
|
25
|
-
stroke: vi.fn(),
|
|
26
|
-
fill: vi.fn(),
|
|
27
|
-
closePath: vi.fn(),
|
|
28
|
-
strokeStyle: '',
|
|
29
|
-
fillStyle: '',
|
|
30
|
-
lineWidth: 0,
|
|
31
|
-
lineJoin: '',
|
|
32
|
-
lineCap: '',
|
|
33
|
-
} as unknown as CanvasRenderingContext2D
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function createMockPluginHost(state?: BOLLRenderState): PluginHost {
|
|
37
|
-
return {
|
|
38
|
-
setSharedState: vi.fn(),
|
|
39
|
-
getSharedState: vi.fn(<T>(key: string): T | undefined => {
|
|
40
|
-
if (key === BOLL_STATE_KEY) {
|
|
41
|
-
return state as T
|
|
42
|
-
}
|
|
43
|
-
return undefined
|
|
44
|
-
}),
|
|
45
|
-
clearByOwner: vi.fn(),
|
|
46
|
-
registerService: vi.fn(),
|
|
47
|
-
getService: vi.fn(<T>(name: string) => {
|
|
48
|
-
if (name === 'indicatorScheduler') {
|
|
49
|
-
return {
|
|
50
|
-
getIndicatorMetadata: (indicatorName: string) => {
|
|
51
|
-
if (indicatorName === 'boll') {
|
|
52
|
-
return { name: 'boll', stateKey: BOLL_STATE_KEY }
|
|
53
|
-
}
|
|
54
|
-
return undefined
|
|
55
|
-
},
|
|
56
|
-
getAllIndicators: () => [],
|
|
57
|
-
} as T
|
|
58
|
-
}
|
|
59
|
-
return undefined
|
|
60
|
-
}),
|
|
61
|
-
getCanvas: vi.fn(),
|
|
62
|
-
getMainPane: vi.fn(),
|
|
63
|
-
getSubPane: vi.fn(),
|
|
64
|
-
getAllSubPanes: vi.fn(),
|
|
65
|
-
getTheme: vi.fn(),
|
|
66
|
-
getStyles: vi.fn(),
|
|
67
|
-
getBarStyles: vi.fn(),
|
|
68
|
-
getConfig: vi.fn(),
|
|
69
|
-
setConfig: vi.fn(),
|
|
70
|
-
on: vi.fn(),
|
|
71
|
-
off: vi.fn(),
|
|
72
|
-
once: vi.fn(),
|
|
73
|
-
emit: vi.fn(),
|
|
74
|
-
} as unknown as PluginHost
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function createMockRenderContext(
|
|
78
|
-
ctx: CanvasRenderingContext2D,
|
|
79
|
-
overrides: Partial<RenderContext> = {}
|
|
80
|
-
): RenderContext {
|
|
81
|
-
const mockPane = {
|
|
82
|
-
height: 200,
|
|
83
|
-
yAxis: {
|
|
84
|
-
priceToY: (price: number) => price * 10,
|
|
85
|
-
getDisplayRange: () => ({ minPrice: 0, maxPrice: 200 }),
|
|
86
|
-
getPriceOffset: () => 0,
|
|
87
|
-
getScaleType: () => 'linear',
|
|
88
|
-
},
|
|
89
|
-
} as unknown as Pane
|
|
90
|
-
|
|
91
|
-
// Create default test data with sufficient length
|
|
92
|
-
const defaultData: KLineData[] = Array.from({ length: 100 }, (_, i) => ({
|
|
93
|
-
timestamp: 1000000000000 + i * 60000,
|
|
94
|
-
open: 100 + i,
|
|
95
|
-
high: 101 + i,
|
|
96
|
-
low: 99 + i,
|
|
97
|
-
close: 100 + i,
|
|
98
|
-
volume: 1000 + i * 100,
|
|
99
|
-
}))
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
ctx,
|
|
103
|
-
data: defaultData,
|
|
104
|
-
// BOLL period defaults to 20 — range must cover post-warm-up indices for draw() to execute
|
|
105
|
-
range: { start: 0, end: 100 },
|
|
106
|
-
visibleRange: { start: 0, end: 100 },
|
|
107
|
-
crosshair: null,
|
|
108
|
-
crosshairIndex: null,
|
|
109
|
-
dpr: 1,
|
|
110
|
-
scrollLeft: 0,
|
|
111
|
-
pane: mockPane,
|
|
112
|
-
kLineCenters: Array.from({ length: 100 }, (_, i) => i * 10 + 5),
|
|
113
|
-
...overrides,
|
|
114
|
-
} as RenderContext
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function createTestBOLLState(overrides: Partial<BOLLRenderState> = {}): BOLLRenderState {
|
|
118
|
-
return {
|
|
119
|
-
timestamp: Date.now(),
|
|
120
|
-
series: Array.from({ length: 100 }, (_, i) =>
|
|
121
|
-
i < 19
|
|
122
|
-
? undefined
|
|
123
|
-
: { upper: 110 + i * 0.1, middle: 100 + i * 0.1, lower: 90 + i * 0.1 }
|
|
124
|
-
),
|
|
125
|
-
params: {
|
|
126
|
-
period: 20,
|
|
127
|
-
multiplier: 2,
|
|
128
|
-
showUpper: true,
|
|
129
|
-
showMiddle: true,
|
|
130
|
-
showLower: true,
|
|
131
|
-
showBand: true,
|
|
132
|
-
},
|
|
133
|
-
visibleMin: 90,
|
|
134
|
-
visibleMax: 120,
|
|
135
|
-
...overrides,
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
describe('createBOLLRendererPlugin', () => {
|
|
140
|
-
it('should create a renderer plugin with correct metadata', () => {
|
|
141
|
-
const plugin = createBOLLRendererPlugin()
|
|
142
|
-
|
|
143
|
-
expect(plugin.name).toBe('boll')
|
|
144
|
-
expect(plugin.version).toBe('2.2.0')
|
|
145
|
-
expect(plugin.paneId).toBe('main')
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
it('should have onInstall method', () => {
|
|
149
|
-
const plugin = createBOLLRendererPlugin()
|
|
150
|
-
expect(typeof plugin.onInstall).toBe('function')
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
it('should declare BOLL_STATE_KEY namespace', () => {
|
|
154
|
-
const plugin = createBOLLRendererPlugin()
|
|
155
|
-
plugin.onInstall(createMockPluginHost())
|
|
156
|
-
expect(plugin.getDeclaredNamespaces()).toEqual([BOLL_STATE_KEY])
|
|
157
|
-
})
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
describe('BOLL renderer draw', () => {
|
|
161
|
-
let ctx: CanvasRenderingContext2D
|
|
162
|
-
let plugin: TestableBOLLRenderer
|
|
163
|
-
|
|
164
|
-
beforeEach(() => {
|
|
165
|
-
ctx = createMockCanvasContext()
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
it('should not draw when StateStore has no BOLL state', () => {
|
|
169
|
-
const mockHost = createMockPluginHost(undefined)
|
|
170
|
-
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
171
|
-
plugin.onInstall(mockHost)
|
|
172
|
-
|
|
173
|
-
const context = createMockRenderContext(ctx)
|
|
174
|
-
plugin.draw(context)
|
|
175
|
-
|
|
176
|
-
// Should not call any drawing methods
|
|
177
|
-
expect(ctx.beginPath).not.toHaveBeenCalled()
|
|
178
|
-
expect(ctx.stroke).not.toHaveBeenCalled()
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
it('should not draw when state has no valid data', () => {
|
|
182
|
-
const state = createTestBOLLState({
|
|
183
|
-
visibleMin: Infinity,
|
|
184
|
-
visibleMax: -Infinity,
|
|
185
|
-
})
|
|
186
|
-
const mockHost = createMockPluginHost(state)
|
|
187
|
-
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
188
|
-
plugin.onInstall(mockHost)
|
|
189
|
-
|
|
190
|
-
const context = createMockRenderContext(ctx)
|
|
191
|
-
plugin.draw(context)
|
|
192
|
-
|
|
193
|
-
expect(ctx.beginPath).not.toHaveBeenCalled()
|
|
194
|
-
expect(ctx.stroke).not.toHaveBeenCalled()
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
it('should save and restore context', () => {
|
|
198
|
-
const state = createTestBOLLState()
|
|
199
|
-
const mockHost = createMockPluginHost(state)
|
|
200
|
-
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
201
|
-
plugin.onInstall(mockHost)
|
|
202
|
-
|
|
203
|
-
const context = createMockRenderContext(ctx)
|
|
204
|
-
plugin.draw(context)
|
|
205
|
-
|
|
206
|
-
expect(ctx.save).toHaveBeenCalledTimes(1)
|
|
207
|
-
expect(ctx.restore).toHaveBeenCalledTimes(1)
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
it('should draw band when showBand is true', () => {
|
|
211
|
-
const state = createTestBOLLState({ params: { ...createTestBOLLState().params, showBand: true } })
|
|
212
|
-
const mockHost = createMockPluginHost(state)
|
|
213
|
-
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
214
|
-
plugin.onInstall(mockHost)
|
|
215
|
-
|
|
216
|
-
const context = createMockRenderContext(ctx)
|
|
217
|
-
plugin.draw(context)
|
|
218
|
-
|
|
219
|
-
expect(ctx.fill).toHaveBeenCalled()
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
it('should not draw band when showBand is false', () => {
|
|
223
|
-
const state = createTestBOLLState({ params: { ...createTestBOLLState().params, showBand: false } })
|
|
224
|
-
const mockHost = createMockPluginHost(state)
|
|
225
|
-
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
226
|
-
plugin.onInstall(mockHost)
|
|
227
|
-
|
|
228
|
-
const context = createMockRenderContext(ctx)
|
|
229
|
-
plugin.draw(context)
|
|
230
|
-
|
|
231
|
-
expect(ctx.fill).not.toHaveBeenCalled()
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
it('should draw upper line when showUpper is true', () => {
|
|
235
|
-
const state = createTestBOLLState({ params: { ...createTestBOLLState().params, showUpper: true } })
|
|
236
|
-
const mockHost = createMockPluginHost(state)
|
|
237
|
-
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
238
|
-
plugin.onInstall(mockHost)
|
|
239
|
-
|
|
240
|
-
const context = createMockRenderContext(ctx)
|
|
241
|
-
plugin.draw(context)
|
|
242
|
-
|
|
243
|
-
// Should have at least one stroke call for the lines
|
|
244
|
-
expect(ctx.stroke).toHaveBeenCalled()
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
it('should use correct colors for BOLL lines', () => {
|
|
248
|
-
const state = createTestBOLLState()
|
|
249
|
-
const mockHost = createMockPluginHost(state)
|
|
250
|
-
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
251
|
-
plugin.onInstall(mockHost)
|
|
252
|
-
|
|
253
|
-
const context = createMockRenderContext(ctx)
|
|
254
|
-
plugin.draw(context)
|
|
255
|
-
|
|
256
|
-
// Verify strokeStyle was set (for lines)
|
|
257
|
-
expect(ctx.stroke).toHaveBeenCalled()
|
|
258
|
-
})
|
|
259
|
-
|
|
260
|
-
it('should not crash when series has undefined values', () => {
|
|
261
|
-
const state = createTestBOLLState({
|
|
262
|
-
series: Array.from({ length: 25 }, (_, i) =>
|
|
263
|
-
i < 19 ? undefined : { upper: 110, middle: 100, lower: 90 }
|
|
264
|
-
),
|
|
265
|
-
})
|
|
266
|
-
const mockHost = createMockPluginHost(state)
|
|
267
|
-
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
268
|
-
plugin.onInstall(mockHost)
|
|
269
|
-
|
|
270
|
-
const context = createMockRenderContext(ctx, { range: { start: 0, end: 25 } })
|
|
271
|
-
|
|
272
|
-
expect(() => plugin.draw(context)).not.toThrow()
|
|
273
|
-
})
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
describe('BOLL renderer config', () => {
|
|
277
|
-
it('getConfig should return current params from StateStore', () => {
|
|
278
|
-
const state = createTestBOLLState({
|
|
279
|
-
params: { period: 25, multiplier: 3, showUpper: false, showMiddle: true, showLower: false, showBand: false },
|
|
280
|
-
})
|
|
281
|
-
const mockHost = createMockPluginHost(state)
|
|
282
|
-
const plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
283
|
-
plugin.onInstall(mockHost)
|
|
284
|
-
|
|
285
|
-
const config = plugin.getConfig()
|
|
286
|
-
|
|
287
|
-
expect(config.period).toBe(25)
|
|
288
|
-
expect(config.multiplier).toBe(3)
|
|
289
|
-
expect(config.showUpper).toBe(false)
|
|
290
|
-
})
|
|
291
|
-
|
|
292
|
-
it('getConfig should return empty object when no state', () => {
|
|
293
|
-
const mockHost = createMockPluginHost(undefined)
|
|
294
|
-
const plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
295
|
-
plugin.onInstall(mockHost)
|
|
296
|
-
|
|
297
|
-
const config = plugin.getConfig()
|
|
298
|
-
|
|
299
|
-
expect(config).toEqual({})
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
it('setConfig should be a no-op', () => {
|
|
303
|
-
const mockHost = createMockPluginHost(createTestBOLLState())
|
|
304
|
-
const plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
305
|
-
plugin.onInstall(mockHost)
|
|
306
|
-
|
|
307
|
-
// setConfig should not throw
|
|
308
|
-
expect(() => plugin.setConfig({ period: 50 })).not.toThrow()
|
|
309
|
-
|
|
310
|
-
// Config should still come from StateStore, not the setConfig call
|
|
311
|
-
const config = plugin.getConfig()
|
|
312
|
-
expect(config.period).toBe(20) // Original value from state
|
|
313
|
-
})
|
|
314
|
-
})
|
|
1
|
+
// @ts-nocheck - Test file with intentional type relaxations for mocking
|
|
2
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
3
|
+
import { createBOLLRendererPlugin } from '../Indicator/boll'
|
|
4
|
+
import { BOLL_STATE_KEY, type BOLLRenderState } from '@/core/indicators/bollState'
|
|
5
|
+
import { BOLL_COLORS } from '@/core/theme/colors'
|
|
6
|
+
import type { PluginHost, RenderContext, RendererPluginWithHost } from '@/plugin'
|
|
7
|
+
import type { KLineData } from '@/types/price'
|
|
8
|
+
import type { Pane } from '@/core/layout/pane'
|
|
9
|
+
|
|
10
|
+
// Type helper for tests
|
|
11
|
+
interface TestableBOLLRenderer extends RendererPluginWithHost {
|
|
12
|
+
draw: (context: RenderContext) => void
|
|
13
|
+
getConfig: () => Record<string, unknown>
|
|
14
|
+
setConfig: (config: Record<string, unknown>) => void
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function createMockCanvasContext(): CanvasRenderingContext2D {
|
|
18
|
+
return {
|
|
19
|
+
save: vi.fn(),
|
|
20
|
+
restore: vi.fn(),
|
|
21
|
+
translate: vi.fn(),
|
|
22
|
+
beginPath: vi.fn(),
|
|
23
|
+
moveTo: vi.fn(),
|
|
24
|
+
lineTo: vi.fn(),
|
|
25
|
+
stroke: vi.fn(),
|
|
26
|
+
fill: vi.fn(),
|
|
27
|
+
closePath: vi.fn(),
|
|
28
|
+
strokeStyle: '',
|
|
29
|
+
fillStyle: '',
|
|
30
|
+
lineWidth: 0,
|
|
31
|
+
lineJoin: '',
|
|
32
|
+
lineCap: '',
|
|
33
|
+
} as unknown as CanvasRenderingContext2D
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function createMockPluginHost(state?: BOLLRenderState): PluginHost {
|
|
37
|
+
return {
|
|
38
|
+
setSharedState: vi.fn(),
|
|
39
|
+
getSharedState: vi.fn(<T>(key: string): T | undefined => {
|
|
40
|
+
if (key === BOLL_STATE_KEY) {
|
|
41
|
+
return state as T
|
|
42
|
+
}
|
|
43
|
+
return undefined
|
|
44
|
+
}),
|
|
45
|
+
clearByOwner: vi.fn(),
|
|
46
|
+
registerService: vi.fn(),
|
|
47
|
+
getService: vi.fn(<T>(name: string) => {
|
|
48
|
+
if (name === 'indicatorScheduler') {
|
|
49
|
+
return {
|
|
50
|
+
getIndicatorMetadata: (indicatorName: string) => {
|
|
51
|
+
if (indicatorName === 'boll') {
|
|
52
|
+
return { name: 'boll', stateKey: BOLL_STATE_KEY }
|
|
53
|
+
}
|
|
54
|
+
return undefined
|
|
55
|
+
},
|
|
56
|
+
getAllIndicators: () => [],
|
|
57
|
+
} as T
|
|
58
|
+
}
|
|
59
|
+
return undefined
|
|
60
|
+
}),
|
|
61
|
+
getCanvas: vi.fn(),
|
|
62
|
+
getMainPane: vi.fn(),
|
|
63
|
+
getSubPane: vi.fn(),
|
|
64
|
+
getAllSubPanes: vi.fn(),
|
|
65
|
+
getTheme: vi.fn(),
|
|
66
|
+
getStyles: vi.fn(),
|
|
67
|
+
getBarStyles: vi.fn(),
|
|
68
|
+
getConfig: vi.fn(),
|
|
69
|
+
setConfig: vi.fn(),
|
|
70
|
+
on: vi.fn(),
|
|
71
|
+
off: vi.fn(),
|
|
72
|
+
once: vi.fn(),
|
|
73
|
+
emit: vi.fn(),
|
|
74
|
+
} as unknown as PluginHost
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function createMockRenderContext(
|
|
78
|
+
ctx: CanvasRenderingContext2D,
|
|
79
|
+
overrides: Partial<RenderContext> = {}
|
|
80
|
+
): RenderContext {
|
|
81
|
+
const mockPane = {
|
|
82
|
+
height: 200,
|
|
83
|
+
yAxis: {
|
|
84
|
+
priceToY: (price: number) => price * 10,
|
|
85
|
+
getDisplayRange: () => ({ minPrice: 0, maxPrice: 200 }),
|
|
86
|
+
getPriceOffset: () => 0,
|
|
87
|
+
getScaleType: () => 'linear',
|
|
88
|
+
},
|
|
89
|
+
} as unknown as Pane
|
|
90
|
+
|
|
91
|
+
// Create default test data with sufficient length
|
|
92
|
+
const defaultData: KLineData[] = Array.from({ length: 100 }, (_, i) => ({
|
|
93
|
+
timestamp: 1000000000000 + i * 60000,
|
|
94
|
+
open: 100 + i,
|
|
95
|
+
high: 101 + i,
|
|
96
|
+
low: 99 + i,
|
|
97
|
+
close: 100 + i,
|
|
98
|
+
volume: 1000 + i * 100,
|
|
99
|
+
}))
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
ctx,
|
|
103
|
+
data: defaultData,
|
|
104
|
+
// BOLL period defaults to 20 — range must cover post-warm-up indices for draw() to execute
|
|
105
|
+
range: { start: 0, end: 100 },
|
|
106
|
+
visibleRange: { start: 0, end: 100 },
|
|
107
|
+
crosshair: null,
|
|
108
|
+
crosshairIndex: null,
|
|
109
|
+
dpr: 1,
|
|
110
|
+
scrollLeft: 0,
|
|
111
|
+
pane: mockPane,
|
|
112
|
+
kLineCenters: Array.from({ length: 100 }, (_, i) => i * 10 + 5),
|
|
113
|
+
...overrides,
|
|
114
|
+
} as RenderContext
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function createTestBOLLState(overrides: Partial<BOLLRenderState> = {}): BOLLRenderState {
|
|
118
|
+
return {
|
|
119
|
+
timestamp: Date.now(),
|
|
120
|
+
series: Array.from({ length: 100 }, (_, i) =>
|
|
121
|
+
i < 19
|
|
122
|
+
? undefined
|
|
123
|
+
: { upper: 110 + i * 0.1, middle: 100 + i * 0.1, lower: 90 + i * 0.1 }
|
|
124
|
+
),
|
|
125
|
+
params: {
|
|
126
|
+
period: 20,
|
|
127
|
+
multiplier: 2,
|
|
128
|
+
showUpper: true,
|
|
129
|
+
showMiddle: true,
|
|
130
|
+
showLower: true,
|
|
131
|
+
showBand: true,
|
|
132
|
+
},
|
|
133
|
+
visibleMin: 90,
|
|
134
|
+
visibleMax: 120,
|
|
135
|
+
...overrides,
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
describe('createBOLLRendererPlugin', () => {
|
|
140
|
+
it('should create a renderer plugin with correct metadata', () => {
|
|
141
|
+
const plugin = createBOLLRendererPlugin()
|
|
142
|
+
|
|
143
|
+
expect(plugin.name).toBe('boll')
|
|
144
|
+
expect(plugin.version).toBe('2.2.0')
|
|
145
|
+
expect(plugin.paneId).toBe('main')
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('should have onInstall method', () => {
|
|
149
|
+
const plugin = createBOLLRendererPlugin()
|
|
150
|
+
expect(typeof plugin.onInstall).toBe('function')
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it('should declare BOLL_STATE_KEY namespace', () => {
|
|
154
|
+
const plugin = createBOLLRendererPlugin()
|
|
155
|
+
plugin.onInstall(createMockPluginHost())
|
|
156
|
+
expect(plugin.getDeclaredNamespaces()).toEqual([BOLL_STATE_KEY])
|
|
157
|
+
})
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
describe('BOLL renderer draw', () => {
|
|
161
|
+
let ctx: CanvasRenderingContext2D
|
|
162
|
+
let plugin: TestableBOLLRenderer
|
|
163
|
+
|
|
164
|
+
beforeEach(() => {
|
|
165
|
+
ctx = createMockCanvasContext()
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
it('should not draw when StateStore has no BOLL state', () => {
|
|
169
|
+
const mockHost = createMockPluginHost(undefined)
|
|
170
|
+
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
171
|
+
plugin.onInstall(mockHost)
|
|
172
|
+
|
|
173
|
+
const context = createMockRenderContext(ctx)
|
|
174
|
+
plugin.draw(context)
|
|
175
|
+
|
|
176
|
+
// Should not call any drawing methods
|
|
177
|
+
expect(ctx.beginPath).not.toHaveBeenCalled()
|
|
178
|
+
expect(ctx.stroke).not.toHaveBeenCalled()
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
it('should not draw when state has no valid data', () => {
|
|
182
|
+
const state = createTestBOLLState({
|
|
183
|
+
visibleMin: Infinity,
|
|
184
|
+
visibleMax: -Infinity,
|
|
185
|
+
})
|
|
186
|
+
const mockHost = createMockPluginHost(state)
|
|
187
|
+
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
188
|
+
plugin.onInstall(mockHost)
|
|
189
|
+
|
|
190
|
+
const context = createMockRenderContext(ctx)
|
|
191
|
+
plugin.draw(context)
|
|
192
|
+
|
|
193
|
+
expect(ctx.beginPath).not.toHaveBeenCalled()
|
|
194
|
+
expect(ctx.stroke).not.toHaveBeenCalled()
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
it('should save and restore context', () => {
|
|
198
|
+
const state = createTestBOLLState()
|
|
199
|
+
const mockHost = createMockPluginHost(state)
|
|
200
|
+
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
201
|
+
plugin.onInstall(mockHost)
|
|
202
|
+
|
|
203
|
+
const context = createMockRenderContext(ctx)
|
|
204
|
+
plugin.draw(context)
|
|
205
|
+
|
|
206
|
+
expect(ctx.save).toHaveBeenCalledTimes(1)
|
|
207
|
+
expect(ctx.restore).toHaveBeenCalledTimes(1)
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
it('should draw band when showBand is true', () => {
|
|
211
|
+
const state = createTestBOLLState({ params: { ...createTestBOLLState().params, showBand: true } })
|
|
212
|
+
const mockHost = createMockPluginHost(state)
|
|
213
|
+
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
214
|
+
plugin.onInstall(mockHost)
|
|
215
|
+
|
|
216
|
+
const context = createMockRenderContext(ctx)
|
|
217
|
+
plugin.draw(context)
|
|
218
|
+
|
|
219
|
+
expect(ctx.fill).toHaveBeenCalled()
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('should not draw band when showBand is false', () => {
|
|
223
|
+
const state = createTestBOLLState({ params: { ...createTestBOLLState().params, showBand: false } })
|
|
224
|
+
const mockHost = createMockPluginHost(state)
|
|
225
|
+
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
226
|
+
plugin.onInstall(mockHost)
|
|
227
|
+
|
|
228
|
+
const context = createMockRenderContext(ctx)
|
|
229
|
+
plugin.draw(context)
|
|
230
|
+
|
|
231
|
+
expect(ctx.fill).not.toHaveBeenCalled()
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
it('should draw upper line when showUpper is true', () => {
|
|
235
|
+
const state = createTestBOLLState({ params: { ...createTestBOLLState().params, showUpper: true } })
|
|
236
|
+
const mockHost = createMockPluginHost(state)
|
|
237
|
+
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
238
|
+
plugin.onInstall(mockHost)
|
|
239
|
+
|
|
240
|
+
const context = createMockRenderContext(ctx)
|
|
241
|
+
plugin.draw(context)
|
|
242
|
+
|
|
243
|
+
// Should have at least one stroke call for the lines
|
|
244
|
+
expect(ctx.stroke).toHaveBeenCalled()
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
it('should use correct colors for BOLL lines', () => {
|
|
248
|
+
const state = createTestBOLLState()
|
|
249
|
+
const mockHost = createMockPluginHost(state)
|
|
250
|
+
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
251
|
+
plugin.onInstall(mockHost)
|
|
252
|
+
|
|
253
|
+
const context = createMockRenderContext(ctx)
|
|
254
|
+
plugin.draw(context)
|
|
255
|
+
|
|
256
|
+
// Verify strokeStyle was set (for lines)
|
|
257
|
+
expect(ctx.stroke).toHaveBeenCalled()
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
it('should not crash when series has undefined values', () => {
|
|
261
|
+
const state = createTestBOLLState({
|
|
262
|
+
series: Array.from({ length: 25 }, (_, i) =>
|
|
263
|
+
i < 19 ? undefined : { upper: 110, middle: 100, lower: 90 }
|
|
264
|
+
),
|
|
265
|
+
})
|
|
266
|
+
const mockHost = createMockPluginHost(state)
|
|
267
|
+
plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
268
|
+
plugin.onInstall(mockHost)
|
|
269
|
+
|
|
270
|
+
const context = createMockRenderContext(ctx, { range: { start: 0, end: 25 } })
|
|
271
|
+
|
|
272
|
+
expect(() => plugin.draw(context)).not.toThrow()
|
|
273
|
+
})
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
describe('BOLL renderer config', () => {
|
|
277
|
+
it('getConfig should return current params from StateStore', () => {
|
|
278
|
+
const state = createTestBOLLState({
|
|
279
|
+
params: { period: 25, multiplier: 3, showUpper: false, showMiddle: true, showLower: false, showBand: false },
|
|
280
|
+
})
|
|
281
|
+
const mockHost = createMockPluginHost(state)
|
|
282
|
+
const plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
283
|
+
plugin.onInstall(mockHost)
|
|
284
|
+
|
|
285
|
+
const config = plugin.getConfig()
|
|
286
|
+
|
|
287
|
+
expect(config.period).toBe(25)
|
|
288
|
+
expect(config.multiplier).toBe(3)
|
|
289
|
+
expect(config.showUpper).toBe(false)
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
it('getConfig should return empty object when no state', () => {
|
|
293
|
+
const mockHost = createMockPluginHost(undefined)
|
|
294
|
+
const plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
295
|
+
plugin.onInstall(mockHost)
|
|
296
|
+
|
|
297
|
+
const config = plugin.getConfig()
|
|
298
|
+
|
|
299
|
+
expect(config).toEqual({})
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
it('setConfig should be a no-op', () => {
|
|
303
|
+
const mockHost = createMockPluginHost(createTestBOLLState())
|
|
304
|
+
const plugin = createBOLLRendererPlugin() as TestableBOLLRenderer
|
|
305
|
+
plugin.onInstall(mockHost)
|
|
306
|
+
|
|
307
|
+
// setConfig should not throw
|
|
308
|
+
expect(() => plugin.setConfig({ period: 50 })).not.toThrow()
|
|
309
|
+
|
|
310
|
+
// Config should still come from StateStore, not the setConfig call
|
|
311
|
+
const config = plugin.getConfig()
|
|
312
|
+
expect(config.period).toBe(20) // Original value from state
|
|
313
|
+
})
|
|
314
|
+
})
|