waveform-analysis 0.1.63 → 0.1.64

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.
Files changed (83) hide show
  1. package/README.md +9 -2
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +953 -946
  4. package/dist/style.css +1 -1
  5. package/dist/types/types/chart.d.ts +2 -1
  6. package/package.json +1 -1
  7. package/src/components/WaveformChart.vue +1 -1
  8. package/src/components/core/xDomain.ts +26 -2
  9. package/src/components/rendering/WaveformLegend.vue +1 -1
  10. package/src/components/rendering/WaveformSeriesLayer.vue +1 -1
  11. package/src/demo/DemoChartHost.vue +1 -0
  12. package/src/types/chart.ts +2 -1
  13. package/src/App.test.ts +0 -400
  14. package/src/components/annotation/components.test.ts +0 -372
  15. package/src/components/annotation/markup.test.ts +0 -371
  16. package/src/components/annotation/serialization.test.ts +0 -114
  17. package/src/components/core/constants.test.ts +0 -29
  18. package/src/components/core/fixedYDomainLayout.test.ts +0 -204
  19. package/src/components/core/grid.test.ts +0 -197
  20. package/src/components/core/latestTaskScheduler.test.ts +0 -51
  21. package/src/components/core/layout.test.ts +0 -373
  22. package/src/components/core/title.test.ts +0 -76
  23. package/src/components/core/useWaveformData.test.ts +0 -95
  24. package/src/components/core/useWaveformRenderSampling.test.ts +0 -17
  25. package/src/components/core/xDomain.test.ts +0 -28
  26. package/src/components/core/yAxisNice.test.ts +0 -174
  27. package/src/components/core/yAxisSlotLayout.test.ts +0 -165
  28. package/src/components/core/yDomain.test.ts +0 -56
  29. package/src/components/interaction/WaveformTooltip.test.ts +0 -276
  30. package/src/components/interaction/viewportInteractionState.test.ts +0 -101
  31. package/src/components/utils/useAnimationFrameThrottle.test.ts +0 -53
  32. package/src/components/waveformChartCases/annotationEditingAndReprojection.test.ts +0 -257
  33. package/src/components/waveformChartCases/compactAndSharedHover.test.ts +0 -358
  34. package/src/components/waveformChartCases/dataAndHoverPerformance.test.ts +0 -358
  35. package/src/components/waveformChartCases/dataLifecycle.test.ts +0 -310
  36. package/src/components/waveformChartCases/frameGridAndFormatting.test.ts +0 -389
  37. package/src/components/waveformChartCases/gridFill.test.ts +0 -95
  38. package/src/components/waveformChartCases/incompleteDataHover.test.ts +0 -155
  39. package/src/components/waveformChartCases/interactionAndAnnotationCreation.test.ts +0 -328
  40. package/src/components/waveformChartCases/layoutAndDomains.test.ts +0 -371
  41. package/src/components/waveformChartCases/legendVisibility.test.ts +0 -350
  42. package/src/components/waveformChartCases/multiAxisAndPagination.test.ts +0 -400
  43. package/src/components/waveformChartCases/multiAxisLabelAlignment.test.ts +0 -61
  44. package/src/components/waveformChartCases/presentationAndAxes.test.ts +0 -345
  45. package/src/components/waveformChartCases/presentationMode.test.ts +0 -327
  46. package/src/components/waveformChartCases/renderingStyles.test.ts +0 -283
  47. package/src/components/waveformChartCases/sizingAndTitles.test.ts +0 -370
  48. package/src/components/waveformChartCases/trackOrder.test.ts +0 -323
  49. package/src/components/waveformChartCases/viewportBoxAndPan.test.ts +0 -365
  50. package/src/components/waveformChartCases/viewportConstraintsAndReset.test.ts +0 -311
  51. package/src/components/waveformChartCases/viewportLifecycle.test.ts +0 -132
  52. package/src/components/waveformChartCases/viewportReset.test.ts +0 -251
  53. package/src/components/waveformChartCases/wheelZoomOut.test.ts +0 -114
  54. package/src/components/waveformChartCases/workerSamplingIntegration.test.ts +0 -117
  55. package/src/components/waveformChartCases/xDomainStrategy.test.ts +0 -168
  56. package/src/components/waveformChartCases/yAxisLayout.test.ts +0 -103
  57. package/src/components/waveformChartCases/zoomIntentAndDataRebind.test.ts +0 -213
  58. package/src/components/waveformChartCases/zoomPointConstraints.test.ts +0 -308
  59. package/src/components/waveformLegendGeometry.test.ts +0 -21
  60. package/src/components/waveformNormalization.test.ts +0 -170
  61. package/src/core/data.test.ts +0 -241
  62. package/src/core/rendering.test.ts +0 -267
  63. package/src/core/renderingStrategies.test.ts +0 -90
  64. package/src/core/samplingReference.test.ts +0 -124
  65. package/src/core/wasmSampling.test.ts +0 -205
  66. package/src/core/workerSampling/multiresolution.test.ts +0 -69
  67. package/src/core/workerSampling/protocol.test.ts +0 -34
  68. package/src/core/workerSampling/repository.test.ts +0 -400
  69. package/src/core/workerSampling/repositoryCache.test.ts +0 -163
  70. package/src/core/workerSampling/repositorySampling.test.ts +0 -106
  71. package/src/core/workerSampling/repositoryTypedDataset.test.ts +0 -89
  72. package/src/core/workerSampling/repositoryWasmDataset.test.ts +0 -70
  73. package/src/data/simulatedWaveforms.test.ts +0 -60
  74. package/src/demo/plotMarginControls.test.ts +0 -29
  75. package/src/demo/xAxisLabelControls.test.ts +0 -86
  76. package/src/test/setup.ts +0 -82
  77. package/src/test/waveformChart.ts +0 -75
  78. package/src/utils/domain.test.ts +0 -28
  79. package/src/utils/formatters.test.ts +0 -131
  80. package/src/utils/sampling.test.ts +0 -226
  81. package/src/views/FixedYDomainDemo.test.ts +0 -44
  82. package/src/views/WasmSamplingDemo.test.ts +0 -13
  83. package/src/views/wasmSamplingDemoSampling.test.ts +0 -27
package/src/App.test.ts DELETED
@@ -1,400 +0,0 @@
1
- import { flushPromises, mount } from '@vue/test-utils'
2
- import { InputNumber, Select } from 'ant-design-vue'
3
- import { describe, expect, it, vi } from 'vitest'
4
- import { ColorPicker } from 'vue3-colorpicker'
5
-
6
- import App from './App.vue'
7
- import { WaveformChart, type WaveformData } from './components'
8
-
9
- describe('App workspace layout', { timeout: 20_000 }, () => {
10
- it('restores full data and invalidates a pending zoom request', async () => {
11
- vi.useFakeTimers()
12
- const wrapper = mount(App)
13
- try {
14
- await flushPromises()
15
- const chart = wrapper.getComponent(WaveformChart)
16
- const pointCount = (data: WaveformData) =>
17
- data.kind === 'series' && data.series[0]?.data.kind === 'points'
18
- ? data.series[0].data.points.length
19
- : 0
20
- const initialPointCount = pointCount(chart.props('data') as WaveformData)
21
- chart.vm.$emit('zoom-end', { start: 0, end: 0.001 })
22
- await wrapper.get('[aria-label="重置波形视图"]').trigger('click')
23
- await vi.advanceTimersByTimeAsync(100)
24
- await flushPromises()
25
- expect(pointCount(chart.props('data') as WaveformData)).toBe(initialPointCount)
26
- } finally {
27
- wrapper.unmount()
28
- vi.useRealTimers()
29
- }
30
- })
31
- it('places controls in the sidebar beside the chart', async () => {
32
- const wrapper = mount(App)
33
- await flushPromises()
34
- const panel = wrapper.get('#waveform-control-panel')
35
- const frameControls = panel.get('.frame-style-controls')
36
- expect(panel.find('h1').exists()).toBe(false)
37
- expect(panel.find('[aria-label="波形展示方式"]').exists()).toBe(true)
38
- expect(panel.find('[aria-label="波形叠加方式"]').exists()).toBe(true)
39
- expect(panel.find('[aria-label="波形网格尺寸"]').exists()).toBe(true)
40
- const gridSizeInputs = panel.get('[aria-label="波形网格尺寸"]').findAllComponents(InputNumber)
41
- expect(gridSizeInputs[0]?.props('value')).toBe(4)
42
- expect(gridSizeInputs[1]?.props('value')).toBe(1)
43
- expect(panel.find('[aria-label="显示水平网格线"]').exists()).toBe(true)
44
- expect(panel.find('[aria-label="显示垂直网格线"]').exists()).toBe(true)
45
- expect(panel.find('[aria-label="显示横轴线"]').exists()).toBe(true)
46
- expect(panel.find('[aria-label="显示纵轴线"]').exists()).toBe(true)
47
- expect(panel.find('[aria-label="水平网格线颜色"]').exists()).toBe(true)
48
- expect(panel.find('[aria-label="垂直网格线颜色"]').exists()).toBe(true)
49
- expect(panel.find('[aria-label="净图模式"]').exists()).toBe(true)
50
- expect(panel.find('[aria-label="显示数值 Tooltip"]').exists()).toBe(true)
51
- expect(panel.find('[aria-label="选择波形线型"]').exists()).toBe(true)
52
- expect(panel.find('[aria-label="设置波形线型"]').exists()).toBe(true)
53
- expect(panel.find('[aria-label="显示零值参考线"]').exists()).toBe(true)
54
- const zeroLineControls = panel.get('.zero-line-controls')
55
- expect(zeroLineControls.findAllComponents(ColorPicker)).toHaveLength(1)
56
- expect(zeroLineControls.find('[aria-label="零值参考线线宽"]').exists()).toBe(true)
57
- expect(zeroLineControls.find('[aria-label="零值参考线线型"]').exists()).toBe(true)
58
- expect(frameControls.findAllComponents(ColorPicker)).toHaveLength(2)
59
- expect(frameControls.text()).toContain('边框颜色')
60
- expect(frameControls.text()).toContain('背景颜色')
61
- expect(frameControls.find('[aria-label="图框线宽"]').exists()).toBe(true)
62
- expect(frameControls.find('[aria-label="图框线型"]').exists()).toBe(true)
63
- expect(
64
- frameControls.get('[aria-label="图框线型"]').getComponent(Select).props('options'),
65
- ).toContainEqual({ label: '点虚线', value: 'dotted' })
66
- expect(frameControls.find('[aria-label="显示图框水印"]').exists()).toBe(true)
67
- expect(frameControls.get('.frame-style-control--switch .ant-switch').classes()).toContain(
68
- 'ant-switch-small',
69
- )
70
- const titleControls = panel.get('.title-controls')
71
- expect(panel.find('[aria-label="显示标题"]').exists()).toBe(true)
72
- expect(titleControls.find('[aria-label="标题名称"]').exists()).toBe(true)
73
- expect(titleControls.find('[aria-label="标题对齐方式"]').exists()).toBe(true)
74
- expect(titleControls.find('[aria-label="标题字体"]').exists()).toBe(true)
75
- expect(titleControls.find('[aria-label="标题字号"]').exists()).toBe(true)
76
- expect(titleControls.find('[aria-label="标题旋转角度"]').exists()).toBe(true)
77
- expect(titleControls.findAllComponents(ColorPicker)).toHaveLength(1)
78
- expect(panel.find('[aria-label="图例位置"]').exists()).toBe(true)
79
- expect(panel.find('[aria-label="图例排列"]').exists()).toBe(true)
80
- const legendColorControl = panel.get('.legend-color-control')
81
- const legendColorPicker = legendColorControl.getComponent(ColorPicker)
82
- expect(legendColorControl.text()).toContain('背景')
83
- expect(legendColorPicker.props('pureColor')).toBe('rgba(255, 255, 255, 0.7)')
84
- expect(legendColorPicker.props('disableAlpha')).toBe(false)
85
- expect(panel.text()).not.toContain('数据摘要')
86
- expect(wrapper.get('.chart-panel').find('.waveform-chart').exists()).toBe(true)
87
- wrapper.unmount()
88
- })
89
-
90
- it('passes clean view, presentation mode, and zero-line controls to the chart', async () => {
91
- const wrapper = mount(App)
92
- await flushPromises()
93
- const chart = wrapper.getComponent(WaveformChart)
94
-
95
- expect(chart.props('cleanView')).toBe(false)
96
- expect(chart.props('presentationMode')).toBe(false)
97
- expect(chart.props('zeroLine')).toMatchObject({ visible: false, color: '#98a2b3', width: 1 })
98
-
99
- await wrapper.get('[aria-label="净图模式"]').trigger('click')
100
- await wrapper.get('[aria-label="展示模式"]').trigger('click')
101
- await wrapper.get('[aria-label="显示零值参考线"]').trigger('click')
102
- await flushPromises()
103
-
104
- expect(chart.props('cleanView')).toBe(true)
105
- expect(chart.props('presentationMode')).toBe(true)
106
- expect(chart.props('zeroLine')).toMatchObject({ visible: true, color: '#98a2b3', width: 1 })
107
- wrapper.unmount()
108
- })
109
-
110
- it('passes horizontal and vertical grid controls to every track', async () => {
111
- const wrapper = mount(App)
112
- await flushPromises()
113
- const chart = wrapper.getComponent(WaveformChart)
114
-
115
- await wrapper.get('[aria-label="显示水平网格线"]').trigger('click')
116
- await flushPromises()
117
-
118
- const grid = chart.props('grid')
119
- const trackLines = grid?.trackLines
120
- expect(trackLines).toBeTruthy()
121
- expect(Object.keys(trackLines ?? {}).length).toBeGreaterThan(0)
122
- expect(Object.values(trackLines ?? {})).toEqual(
123
- expect.arrayContaining([
124
- expect.objectContaining({
125
- horizontal: false,
126
- vertical: true,
127
- horizontalColor: '#dfe5ef',
128
- verticalColor: '#dfe5ef',
129
- }),
130
- ]),
131
- )
132
- wrapper.unmount()
133
- })
134
-
135
- it('passes independent X and Y axis-line controls to the chart', async () => {
136
- const wrapper = mount(App)
137
- await flushPromises()
138
- const chart = wrapper.getComponent(WaveformChart)
139
-
140
- expect(chart.props('axes')).toEqual({
141
- x: { lineVisible: false },
142
- y: { lineVisible: false },
143
- })
144
-
145
- await wrapper.get('[aria-label="显示横轴线"]').trigger('click')
146
- await wrapper.get('[aria-label="显示纵轴线"]').trigger('click')
147
- await flushPromises()
148
-
149
- expect(chart.props('axes')).toEqual({
150
- x: { lineVisible: true },
151
- y: { lineVisible: true },
152
- })
153
- wrapper.unmount()
154
- })
155
-
156
- it('passes tooltip and per-series line-style controls to the chart', async () => {
157
- const wrapper = mount(App)
158
- await flushPromises()
159
- const chart = wrapper.getComponent(WaveformChart)
160
-
161
- expect(chart.props('showTooltip')).toBe(true)
162
- await wrapper.get('[aria-label="显示数值 Tooltip"]').trigger('click')
163
- await flushPromises()
164
- expect(chart.props('showTooltip')).toBe(false)
165
-
166
- const seriesSelect = wrapper.get('[aria-label="选择波形线型"]').getComponent(Select)
167
- const lineStyleSelect = wrapper.get('[aria-label="设置波形线型"]').getComponent(Select)
168
- const firstSeriesId = String(
169
- (chart.props('data') as WaveformData).kind === 'series'
170
- ? (chart.props('data') as Extract<WaveformData, { kind: 'series' }>).series[0]?.id
171
- : '',
172
- )
173
- seriesSelect.vm.$emit('update:value', firstSeriesId)
174
- lineStyleSelect.vm.$emit('update:value', 'dash-dot')
175
- await flushPromises()
176
-
177
- const currentData = chart.props('data') as Extract<WaveformData, { kind: 'series' }>
178
- expect(currentData.series.find((series) => series.id === firstSeriesId)?.lineStyle).toBe(
179
- 'dash-dot',
180
- )
181
- wrapper.unmount()
182
- })
183
-
184
- it('switches overlaid tracks between single-axis and multi-axis rendering', async () => {
185
- const wrapper = mount(App)
186
- await flushPromises()
187
-
188
- const overlayControl = wrapper.get('[aria-label="波形叠加方式"]')
189
- expect(wrapper.get('.waveform-chart').attributes('data-overlay-mode')).toBe('single-axis')
190
- expect(overlayControl.text()).toContain('单值轴')
191
- expect(overlayControl.text()).toContain('多值轴')
192
-
193
- await overlayControl.findAll('input[type="radio"]')[1]?.setValue(true)
194
- await flushPromises()
195
-
196
- expect(wrapper.get('.waveform-chart').attributes('data-overlay-mode')).toBe('multi-axis')
197
- expect(wrapper.findAll('.waveform-chart__axis--y').length).toBeGreaterThan(1)
198
-
199
- wrapper.unmount()
200
- })
201
-
202
- it('keeps the primary simulated signal in the first frame', async () => {
203
- const wrapper = mount(App)
204
- await flushPromises()
205
-
206
- const firstFrame = wrapper.get('.waveform-chart__track[data-track-index="0"]')
207
- const firstFrameSeries = firstFrame.findAll('.waveform-chart__series')
208
-
209
- expect(firstFrameSeries.map((series) => series.attributes('data-series-name'))).toEqual([
210
- '正弦基波',
211
- ])
212
-
213
- const sineSeries = firstFrame.get('.waveform-chart__series[data-series-name="正弦基波"]')
214
- expect(sineSeries.find('.waveform-chart__line').exists()).toBe(true)
215
- expect(sineSeries.get('.waveform-chart__points').attributes('data-point-type')).toBe('circle')
216
- expect(sineSeries.get('.waveform-chart__error-bar').attributes()).toMatchObject({
217
- stroke: '#0960bd',
218
- 'stroke-width': '1.5',
219
- })
220
-
221
- wrapper.unmount()
222
- })
223
-
224
- it('keeps the simulated channels across the paginated frames', async () => {
225
- const wrapper = mount(App)
226
- await flushPromises()
227
-
228
- const tracks = wrapper.findAll('.waveform-chart__track')
229
- expect(tracks).toHaveLength(4)
230
- expect(
231
- tracks.map((track) =>
232
- track.findAll('.waveform-chart__series').map((item) => item.attributes('data-series-name')),
233
- ),
234
- ).toEqual([['正弦基波'], ['谐波扰动', '谐波对比', '谐波校正'], ['阻尼振荡'], ['阶跃响应']])
235
- expect(
236
- tracks
237
- .slice(1)
238
- .map((track) => track.get('.waveform-chart__line').attributes('data-line-type')),
239
- ).toEqual(['linear', 'linear', 'linear'])
240
- tracks.slice(1).forEach((track) => {
241
- expect(track.find('.waveform-chart__points').exists()).toBe(false)
242
- })
243
-
244
- const chartData = wrapper.getComponent(WaveformChart).props('data') as Extract<
245
- WaveformData,
246
- { kind: 'series' }
247
- >
248
- const simulatedSeries = chartData.series
249
- expect(simulatedSeries.map((item) => item.name)).toEqual([
250
- '正弦基波',
251
- '谐波扰动',
252
- '谐波对比',
253
- '谐波校正',
254
- '阻尼振荡',
255
- '阶跃响应',
256
- '脉冲响应',
257
- '带噪信号',
258
- ])
259
- simulatedSeries.forEach((item) => {
260
- expect(item.data.kind).toBe('points')
261
- if (item.data.kind === 'points') {
262
- expect(item.data.points).toHaveLength(item.name === '阶跃响应' ? 500 : 1000)
263
- expect(item.data.points[0]?.x).toBeCloseTo(item.name === '阶跃响应' ? 5 / 999 : -5, 10)
264
- }
265
- })
266
-
267
- await wrapper.get('.ant-pagination-next button').trigger('click')
268
- await flushPromises()
269
- expect(
270
- wrapper
271
- .findAll('.waveform-chart__track')
272
- .map((track) => track.get('.waveform-chart__series').attributes('data-series-name')),
273
- ).toEqual(['脉冲响应', '带噪信号'])
274
-
275
- wrapper.unmount()
276
- })
277
-
278
- it('updates title content, text styles, and visibility', async () => {
279
- const wrapper = mount(App)
280
- await flushPromises()
281
-
282
- const renderedTitle = () => wrapper.get('.waveform-chart__title-text')
283
- expect(renderedTitle().text()).toBe('模拟波形分析')
284
- expect(renderedTitle().attributes('style')).toContain('Microsoft YaHei')
285
- expect(renderedTitle().attributes('style')).toContain('font-size: 14px')
286
- expect(renderedTitle().attributes('style')).toContain('font-weight: 400')
287
-
288
- await wrapper.get('input[aria-label="标题名称"]').setValue('实验标题')
289
- await wrapper.get('[aria-label="标题粗体"]').trigger('click')
290
- await wrapper.get('[aria-label="标题斜体"]').trigger('click')
291
- await wrapper.get('[aria-label="标题下划线"]').trigger('click')
292
- await flushPromises()
293
-
294
- expect(renderedTitle().text()).toBe('实验标题')
295
- expect(renderedTitle().attributes('style')).toContain('font-weight: 700')
296
- expect(renderedTitle().attributes('style')).toContain('font-style: italic')
297
- expect(renderedTitle().attributes('style')).toContain('text-decoration: underline')
298
-
299
- await wrapper.get('[aria-label="恢复标题常规样式"]').trigger('click')
300
- await flushPromises()
301
- expect(renderedTitle().attributes('style')).toContain('font-weight: 400')
302
- expect(renderedTitle().attributes('style')).toContain('font-style: normal')
303
- expect(renderedTitle().attributes('style')).toContain('text-decoration: none')
304
-
305
- await wrapper.get('[aria-label="显示标题"]').trigger('click')
306
- await flushPromises()
307
- expect(wrapper.find('.waveform-chart__title-area').exists()).toBe(false)
308
-
309
- wrapper.unmount()
310
- })
311
-
312
- it('updates every visible frame from the frame style controls', async () => {
313
- const wrapper = mount(App)
314
- await flushPromises()
315
-
316
- const frameControls = wrapper.get('.frame-style-controls')
317
- const colorPickers = frameControls.findAllComponents(ColorPicker)
318
- const widthInput = frameControls.findAllComponents(InputNumber)[0]
319
- const styleSelect = frameControls.findAllComponents(Select)[0]
320
-
321
- expect(colorPickers).toHaveLength(2)
322
- const initialFrames = wrapper.findAll('.waveform-chart__plot-frame')
323
- expect(
324
- initialFrames.length > 1 &&
325
- initialFrames.every((frame) => frame.attributes('stroke-width') === '2'),
326
- ).toBe(true)
327
-
328
- colorPickers[0].vm.$emit('update:pureColor', 'rgba(220, 38, 38, 0.8)')
329
- colorPickers[1].vm.$emit('update:pureColor', 'rgba(14, 165, 233, 0.25)')
330
- widthInput?.vm.$emit('update:value', 3)
331
- styleSelect?.vm.$emit('update:value', 'dashed')
332
- await flushPromises()
333
-
334
- const frames = wrapper.findAll('.waveform-chart__plot-frame')
335
- const backgrounds = wrapper.findAll('.waveform-chart__plot-background')
336
- expect(frames.length).toBeGreaterThan(1)
337
- expect(backgrounds).toHaveLength(frames.length)
338
- frames.forEach((frame) => {
339
- expect(frame.attributes()).toMatchObject({
340
- stroke: 'rgba(220, 38, 38, 0.8)',
341
- 'stroke-width': '3',
342
- 'stroke-dasharray': '6 4',
343
- })
344
- })
345
- backgrounds.forEach((background) => {
346
- expect(background.attributes('fill')).toBe('rgba(14, 165, 233, 0.25)')
347
- })
348
-
349
- wrapper.unmount()
350
- })
351
-
352
- it('shows and hides every frame watermark from the frame style controls', async () => {
353
- const wrapper = mount(App)
354
- await flushPromises()
355
-
356
- const watermarkToggle = wrapper.get('[aria-label="显示图框水印"]')
357
- const initialWatermarks = wrapper.findAll('.waveform-chart__watermark')
358
- const initialFrameNumbers = initialWatermarks.map((watermark) => watermark.text())
359
-
360
- expect(initialWatermarks.length).toBeGreaterThan(1)
361
-
362
- await watermarkToggle.trigger('click')
363
- await flushPromises()
364
- expect(wrapper.findAll('.waveform-chart__watermark')).toHaveLength(0)
365
-
366
- await watermarkToggle.trigger('click')
367
- await flushPromises()
368
- expect(
369
- wrapper.findAll('.waveform-chart__watermark').map((watermark) => watermark.text()),
370
- ).toEqual(initialFrameNumbers)
371
-
372
- wrapper.unmount()
373
- })
374
-
375
- it('opens and closes the mobile control drawer', async () => {
376
- const wrapper = mount(App)
377
- const toggle = wrapper.get('.mobile-control-toggle')
378
-
379
- expect(toggle.attributes('aria-expanded')).toBe('false')
380
- expect(wrapper.get('.control-panel').classes()).not.toContain('is-open')
381
- expect(wrapper.find('.control-backdrop').exists()).toBe(false)
382
-
383
- await toggle.trigger('click')
384
- expect(toggle.attributes('aria-expanded')).toBe('true')
385
- expect(wrapper.get('.control-panel').classes()).toContain('is-open')
386
- expect(wrapper.find('.control-backdrop').exists()).toBe(true)
387
-
388
- await wrapper.get('.control-backdrop').trigger('click')
389
- expect(toggle.attributes('aria-expanded')).toBe('false')
390
- expect(wrapper.get('.control-panel').classes()).not.toContain('is-open')
391
-
392
- await toggle.trigger('click')
393
- window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }))
394
- await flushPromises()
395
- expect(toggle.attributes('aria-expanded')).toBe('false')
396
- expect(wrapper.find('.control-backdrop').exists()).toBe(false)
397
-
398
- wrapper.unmount()
399
- })
400
- })