Files
waveform-analysis/src/components/waveformChartCases/multiAxisAndPagination.test.ts

319 lines
10 KiB
TypeScript
Raw Normal View History

import { flushPromises } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import { flushAnimationFrames } from '../../test/setup'
import { type WaveformData } from '../waveform'
import { gridSeries, mountSizedChart } from '../../test/waveformChart'
describe('WaveformChart', () => {
it('resolves a separate scientific multiplier for every Y axis', async () => {
const wrapper = await mountSizedChart(
{
kind: 'series',
series: [
{
trackId: 'shared-frame',
name: '普通量程',
data: {
kind: 'points',
points: [
{ x: 0, y: 0 },
{ x: 1, y: 1 },
],
},
},
{
trackId: 'shared-frame',
name: '大量程',
data: {
kind: 'points',
points: [
{ x: 0, y: 0 },
{ x: 1, y: 254 },
],
},
},
{
trackId: 'shared-frame',
name: '小量程',
data: {
kind: 'points',
points: [
{ x: 0, y: 0 },
{ x: 1, y: 0.0002 },
],
},
},
],
},
{ overlayMode: 'multi-axis' },
)
expect(
wrapper
.findAll('.waveform-chart__axis-exponent--y')
.map((label) => [label.attributes('data-y-axis-index'), label.text()]),
).toEqual([
['1', 'E+02'],
['2', 'E-04'],
])
})
it('reprojects annotations with the Y axis assigned to their series', async () => {
const data: WaveformData = {
kind: 'series',
series: [
{
id: 'low',
trackId: 'shared-frame',
name: '低量程',
data: {
kind: 'points',
points: [
{ x: 0, y: 0 },
{ x: 1, y: 10 },
],
},
},
{
id: 'high',
trackId: 'shared-frame',
name: '高量程',
data: {
kind: 'points',
points: [
{ x: 0, y: 1000 },
{ x: 1, y: 2000 },
],
},
},
],
}
const wrapper = await mountSizedChart(data, {
annotations: [{ id: 'high-note', seriesId: 'high', x: 0.5, y: 1500, text: '高值' }],
})
const singleAxisY = wrapper.get('.waveform-annotation__arrow').attributes('y2')
await wrapper.setProps({ overlayMode: 'multi-axis' })
await flushPromises()
expect(wrapper.get('.waveform-annotation__arrow').attributes('y2')).not.toBe(singleAxisY)
wrapper.unmount()
})
it('paginates channels into a row-major two by one grid', async () => {
const wrapper = await mountSizedChart(gridSeries(5), {
grid: { rowCount: 2, columnCount: 1 },
})
expect(wrapper.findAll('.waveform-chart__track')).toHaveLength(2)
expect(
wrapper.findAll('.waveform-chart__line').map((line) => line.attributes('data-series-id')),
).toEqual(['channel-0', 'channel-1'])
const previousButton = () => wrapper.get('.ant-pagination-prev button')
const nextButton = () => wrapper.get('.ant-pagination-next button')
expect(wrapper.get('.ant-pagination-item-1').classes()).toContain('ant-pagination-item-active')
expect(wrapper.get('.ant-pagination-prev').classes()).toContain('ant-pagination-disabled')
await nextButton().trigger('click')
expect(
wrapper.findAll('.waveform-chart__line').map((line) => line.attributes('data-series-id')),
).toEqual(['channel-2', 'channel-3'])
expect(wrapper.emitted('page-change')?.at(-1)).toEqual([2, 3])
await previousButton().trigger('click')
expect(wrapper.get('.ant-pagination-item-1').classes()).toContain('ant-pagination-item-active')
expect(wrapper.emitted('page-change')?.at(-1)).toEqual([1, 3])
await nextButton().trigger('click')
await nextButton().trigger('click')
expect(
wrapper.findAll('.waveform-chart__line').map((line) => line.attributes('data-series-id')),
).toEqual(['channel-4'])
expect(wrapper.get('.ant-pagination-item-3').classes()).toContain('ant-pagination-item-active')
expect(wrapper.get('.ant-pagination-next').classes()).toContain('ant-pagination-disabled')
})
it('overlays series with the same track ID without changing the next frame', async () => {
const wrapper = await mountSizedChart(
{
kind: 'series',
series: [
{
id: 'primary',
trackId: 'frame-1',
name: 'BT2_2M',
data: {
kind: 'points',
points: [
{ x: 0, y: 0 },
{ x: 1, y: 1 },
],
},
},
{
id: 'second-frame',
name: 'BT1_2M',
data: {
kind: 'points',
points: [
{ x: 0, y: 2 },
{ x: 1, y: 3 },
],
},
},
{
id: 'comparison',
trackId: 'frame-1',
name: 'TEST_CH_1',
data: {
kind: 'points',
points: [
{ x: 0, y: 0.5 },
{ x: 1, y: 1.5 },
],
},
},
],
},
{ frameNumber: 1, grid: { rowCount: 2, columnCount: 1 } },
)
const tracks = wrapper.findAll('.waveform-chart__track')
expect(tracks).toHaveLength(2)
expect(
tracks[0].findAll('.waveform-chart__line').map((line) => line.attributes('data-series-id')),
).toEqual(['primary', 'comparison'])
expect(
tracks[1].findAll('.waveform-chart__line').map((line) => line.attributes('data-series-id')),
).toEqual(['second-frame'])
expect(tracks[0].find('.waveform-chart__y-axis-label').exists()).toBe(false)
expect(tracks[0].findAll('.waveform-chart__axis--y .tick').length).toBeGreaterThan(0)
expect(tracks[1].get('.waveform-chart__y-axis-label').text()).toBe('BT1_2M')
expect(wrapper.findAll('.waveform-chart__legend')).toHaveLength(1)
const legend = wrapper.get('.waveform-chart__legend')
expect(legend.attributes('data-position')).toBe('top-right')
expect(legend.attributes('data-orientation')).toBe('vertical')
expect(legend.get('.waveform-legend__panel').attributes('style')).toContain(
'background-color: rgba(255, 255, 255, 0.7)',
)
expect(legend.findAll('.waveform-chart__legend-item').map((item) => item.text())).toEqual([
'BT2_2M',
'TEST_CH_1',
])
expect(
legend
.findAll('.waveform-legend__swatch')
.map((swatch) => swatch.get('path').attributes('stroke')),
).toEqual(['#0960bd', '#389e0d'])
expect(wrapper.findAll('.waveform-chart__watermark').map((item) => item.text())).toEqual([
'1',
'2',
])
expect(wrapper.find('.ant-pagination').exists()).toBe(false)
const firstTrackOverlay = tracks[0].get('.waveform-chart__overlay')
const overlayWidth = Number(firstTrackOverlay.attributes('width'))
const overlayHeight = Number(firstTrackOverlay.attributes('height'))
Object.defineProperty(firstTrackOverlay.element, 'getBoundingClientRect', {
value: () => ({ left: 0, top: 0, width: overlayWidth, height: overlayHeight }),
})
firstTrackOverlay.element.dispatchEvent(
new MouseEvent('pointermove', {
clientX: overlayWidth / 2,
clientY: overlayHeight / 2,
bubbles: true,
}),
)
flushAnimationFrames()
await flushPromises()
const tooltipSeries = wrapper.findAll('.waveform-chart__tooltip-series')
expect(tooltipSeries).toHaveLength(2)
expect(tooltipSeries.map((item) => item.text())).toEqual([
expect.stringContaining('BT2_2M'),
expect.stringContaining('TEST_CH_1'),
])
})
it('resolves automatic legend orientation and supports explicit overrides', async () => {
const wrapper = await mountSizedChart(
{
kind: 'series',
series: [
{
id: 'first',
trackId: 'shared',
name: 'first',
data: {
kind: 'points',
points: [
{ x: 0, y: 0 },
{ x: 1, y: 1 },
],
},
},
{
id: 'second',
trackId: 'shared',
name: 'second',
data: {
kind: 'points',
points: [
{ x: 0, y: 1 },
{ x: 1, y: 2 },
],
},
},
],
},
{ grid: { rowCount: 1, columnCount: 1 } },
)
const positions = [
'top-left',
'top',
'top-right',
'right',
'bottom-right',
'bottom',
'bottom-left',
'left',
] as const
for (const position of positions) {
await wrapper.setProps({ legend: { position, orientation: 'auto' } })
const legend = wrapper.get('.waveform-chart__legend')
const expectedOrientation =
position === 'top' || position === 'bottom' ? 'horizontal' : 'vertical'
expect(legend.attributes('data-position')).toBe(position)
expect(legend.attributes('data-orientation')).toBe(expectedOrientation)
expect(legend.get('.waveform-legend__viewport').classes()).toContain(
`waveform-legend__viewport--${position}`,
)
expect(
legend
.get('.waveform-legend__panel')
.classes()
.includes('waveform-legend__panel--vertical'),
).toBe(expectedOrientation === 'vertical')
}
await wrapper.setProps({ legend: { position: 'top', orientation: 'vertical' } })
expect(wrapper.get('.waveform-chart__legend').attributes('data-orientation')).toBe('vertical')
expect(wrapper.get('.waveform-legend__panel').classes()).toContain(
'waveform-legend__panel--vertical',
)
await wrapper.setProps({ legend: { position: 'left', orientation: 'horizontal' } })
expect(wrapper.get('.waveform-chart__legend').attributes('data-orientation')).toBe('horizontal')
expect(wrapper.get('.waveform-legend__panel').classes()).toContain(
'waveform-legend__panel--horizontal',
)
expect(wrapper.attributes('data-chart-left-margin')).toBe('64')
})
})