refactor(chart): enforce 400-line source limit
Some checks failed
Package component / package (push) Failing after 4m19s
Some checks failed
Package component / package (push) Failing after 4m19s
This commit is contained in:
306
src/components/waveformChartCases/dataLifecycle.test.ts
Normal file
306
src/components/waveformChartCases/dataLifecycle.test.ts
Normal file
@@ -0,0 +1,306 @@
|
||||
import { flushPromises } from '@vue/test-utils'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { type WaveformData } from '../waveform'
|
||||
|
||||
import { gridSeries, mountSizedChart } from '../../test/waveformChart'
|
||||
|
||||
describe('WaveformChart', () => {
|
||||
it('keeps other independent tracks unchanged when one data window is replaced', async () => {
|
||||
const wrapper = await mountSizedChart(gridSeries(2), {
|
||||
displayMode: 'independent',
|
||||
grid: { rowCount: 1, columnCount: 2 },
|
||||
})
|
||||
const originalEndpoints = wrapper
|
||||
.findAll('.waveform-chart__axis-endpoint--end')
|
||||
.map((endpoint) => endpoint.text())
|
||||
|
||||
await wrapper.setProps({
|
||||
data: {
|
||||
kind: 'series',
|
||||
series: [
|
||||
{
|
||||
id: 'channel-0',
|
||||
name: '通道 1',
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0.25, y: 0 },
|
||||
{ x: 0.75, y: 1 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'channel-1',
|
||||
name: '通道 2',
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 1 },
|
||||
{ x: 1, y: 2 },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
await flushPromises()
|
||||
|
||||
const nextEndpoints = wrapper
|
||||
.findAll('.waveform-chart__axis-endpoint--end')
|
||||
.map((endpoint) => endpoint.text())
|
||||
expect(nextEndpoints[0]).not.toBe(originalEndpoints[0])
|
||||
expect(nextEndpoints[1]).toBe(originalEndpoints[1])
|
||||
})
|
||||
|
||||
it('rebuilds cached domains only when the data reference changes', async () => {
|
||||
const firstData: WaveformData = {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 1, y: 1 },
|
||||
],
|
||||
}
|
||||
const wrapper = await mountSizedChart(firstData)
|
||||
expect(wrapper.get('.waveform-chart__axis-endpoint--end').text()).toBe('1.00')
|
||||
|
||||
firstData.points.push({ x: 2, y: 2 })
|
||||
await flushPromises()
|
||||
expect(wrapper.get('.waveform-chart__axis-endpoint--end').text()).toBe('1.00')
|
||||
|
||||
await wrapper.setProps({ data: { ...firstData, points: [...firstData.points] } })
|
||||
await flushPromises()
|
||||
expect(wrapper.get('.waveform-chart__axis-endpoint--end').text()).toBe('2.00')
|
||||
})
|
||||
|
||||
it('keeps controlled annotations when replacing the loaded data window', async () => {
|
||||
const annotations = [
|
||||
{ id: 'window-note', seriesId: 'series-0', x: 0.5, y: 0.5, text: '窗口标注' },
|
||||
]
|
||||
const wrapper = await mountSizedChart(
|
||||
{
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 1, y: 1 },
|
||||
],
|
||||
},
|
||||
{ annotations },
|
||||
)
|
||||
expect(wrapper.find('[data-annotation-id="window-note"]').exists()).toBe(true)
|
||||
|
||||
await wrapper.setProps({
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 2, y: 0 },
|
||||
{ x: 3, y: 1 },
|
||||
],
|
||||
},
|
||||
})
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.find('[data-annotation-id="window-note"]').exists()).toBe(false)
|
||||
expect(annotations).toEqual([
|
||||
{ id: 'window-note', seriesId: 'series-0', x: 0.5, y: 0.5, text: '窗口标注' },
|
||||
])
|
||||
|
||||
await wrapper.setProps({
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 1, y: 1 },
|
||||
],
|
||||
},
|
||||
})
|
||||
await flushPromises()
|
||||
expect(wrapper.find('[data-annotation-id="window-note"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders named multi-channel paths as independent tracks by default', async () => {
|
||||
const wrapper = await mountSizedChart({
|
||||
kind: 'series',
|
||||
series: [
|
||||
{
|
||||
name: 'BT2_2M',
|
||||
unit: 'T',
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 1, y: 2 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'BT1_2M',
|
||||
unit: 'T',
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: -1 },
|
||||
{ x: 2, y: 3 },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
const paths = wrapper.findAll('.waveform-chart__line')
|
||||
|
||||
expect(paths).toHaveLength(2)
|
||||
expect(wrapper.findAll('.waveform-chart__svg')).toHaveLength(1)
|
||||
expect(wrapper.findAll('.waveform-chart__track')).toHaveLength(2)
|
||||
expect(wrapper.findAll('.waveform-chart__axis--x')).toHaveLength(2)
|
||||
expect(wrapper.findAll('.waveform-chart__overlay--independent')).toHaveLength(2)
|
||||
expect(paths[0].attributes('stroke')).toBe('#0960bd')
|
||||
expect(paths[1].attributes('stroke')).toBe('#ff7f0e')
|
||||
expect(paths[0].attributes('data-series-name')).toBe('BT2_2M')
|
||||
const yAxisLabels = wrapper.findAll('.waveform-chart__y-axis-label')
|
||||
expect(yAxisLabels.map((label) => label.text())).toEqual(['BT2_2M', 'BT1_2M'])
|
||||
expect(yAxisLabels.map((label) => label.attributes('fill'))).toEqual(['#0960bd', '#ff7f0e'])
|
||||
const labelX = Number(
|
||||
yAxisLabels[0].attributes('transform')?.match(/^translate\(([-\d.]+),/)?.[1],
|
||||
)
|
||||
expect(labelX).toBeLessThan(-46)
|
||||
expect(Number(wrapper.get('.waveform-chart__y-axis-label-bg').attributes('x'))).toBe(
|
||||
labelX - 12,
|
||||
)
|
||||
expect(yAxisLabels.every((label) => !label.text().includes('(T)'))).toBe(true)
|
||||
expect(wrapper.findAll('.waveform-chart__track-label')).toHaveLength(0)
|
||||
expect(
|
||||
wrapper.findAll('.waveform-chart__axis-endpoint--end').map((item) => item.text()),
|
||||
).toEqual(['1.00', '2.00'])
|
||||
})
|
||||
|
||||
it('keeps the zero Y-axis label on upper compact tracks', async () => {
|
||||
const wrapper = await mountSizedChart(
|
||||
{
|
||||
kind: 'series',
|
||||
series: [
|
||||
{
|
||||
name: 'first',
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 1, y: 1 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'second',
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: -1 },
|
||||
{ x: 1, y: 2 },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{ displayMode: 'compact' },
|
||||
)
|
||||
|
||||
const tracks = wrapper.findAll('.waveform-chart__track')
|
||||
const firstAxisTicks = tracks[0].findAll('.waveform-chart__axis--y .tick')
|
||||
const zeroTicks = firstAxisTicks.filter((tick) => Number(tick.text()) === 0)
|
||||
const firstTrackHeight = Number(tracks[0].attributes('data-track-height'))
|
||||
const zeroTickY = Number(
|
||||
zeroTicks[0].attributes('transform')?.match(/translate\(0,\s*([\d.]+)\)/)?.[1],
|
||||
)
|
||||
|
||||
expect(zeroTicks).toHaveLength(1)
|
||||
expect(Math.abs(zeroTickY - firstTrackHeight)).toBeLessThanOrEqual(1)
|
||||
})
|
||||
|
||||
it.each(['independent', 'separated', 'compact'] as const)(
|
||||
'shows a non-zero Y-axis start value once in %s mode',
|
||||
async (displayMode) => {
|
||||
const wrapper = await mountSizedChart(
|
||||
{
|
||||
kind: 'series',
|
||||
series: [
|
||||
{
|
||||
name: 'first',
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 0.11 },
|
||||
{ x: 1, y: 0.89 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'second',
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 4 },
|
||||
{ x: 1, y: 5 },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{ displayMode },
|
||||
)
|
||||
|
||||
const firstTrack = wrapper.findAll('.waveform-chart__track')[0]
|
||||
const firstTrackHeight = Number(firstTrack.attributes('data-track-height'))
|
||||
const startTicks = firstTrack.findAll('.waveform-chart__axis--y .tick').filter((tick) => {
|
||||
const match = tick.attributes('transform')?.match(/translate\(0,\s*([\d.]+)\)/)
|
||||
return match ? Math.abs(Number(match[1]) - firstTrackHeight) <= 1 : false
|
||||
})
|
||||
|
||||
expect(startTicks).toHaveLength(1)
|
||||
expect(Number(startTicks[0].text())).toBe(0.1)
|
||||
},
|
||||
)
|
||||
|
||||
it.each(['independent', 'separated'] as const)(
|
||||
'shows the Y-axis end value once on every track in %s mode',
|
||||
async (displayMode) => {
|
||||
const wrapper = await mountSizedChart(
|
||||
{
|
||||
kind: 'series',
|
||||
series: [
|
||||
{
|
||||
name: 'first',
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 0.11 },
|
||||
{ x: 1, y: 0.89 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'second',
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 4.11 },
|
||||
{ x: 1, y: 4.89 },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{ displayMode },
|
||||
)
|
||||
|
||||
const expectedEndValues = [0.9, 4.9]
|
||||
wrapper.findAll('.waveform-chart__track').forEach((track, index) => {
|
||||
const endTicks = track.findAll('.waveform-chart__axis--y .tick').filter((tick) => {
|
||||
const match = tick.attributes('transform')?.match(/translate\(0,\s*([\d.]+)\)/)
|
||||
return match ? Math.abs(Number(match[1])) <= 1 : false
|
||||
})
|
||||
|
||||
expect(endTicks).toHaveLength(1)
|
||||
expect(Number(endTicks[0].text())).toBe(expectedEndValues[index])
|
||||
})
|
||||
},
|
||||
)
|
||||
})
|
||||
Reference in New Issue
Block a user