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:
283
src/components/waveformChartCases/renderingStyles.test.ts
Normal file
283
src/components/waveformChartCases/renderingStyles.test.ts
Normal file
@@ -0,0 +1,283 @@
|
||||
import { flushPromises } from '@vue/test-utils'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { flushAnimationFrames } from '../../test/setup'
|
||||
import { type WaveformData } from '../waveform'
|
||||
|
||||
import { mountSizedChart } from '../../test/waveformChart'
|
||||
|
||||
describe('WaveformChart', () => {
|
||||
it('places start, middle, and end step transitions at the expected X positions', async () => {
|
||||
const lineTypes = ['step-start', 'step-middle', 'step-end', 'step-after'] as const
|
||||
const wrapper = await mountSizedChart({
|
||||
kind: 'series',
|
||||
series: lineTypes.map((lineType) => ({
|
||||
id: lineType,
|
||||
trackId: 'steps',
|
||||
name: lineType,
|
||||
lineType,
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 2, y: 10 },
|
||||
],
|
||||
},
|
||||
})),
|
||||
})
|
||||
const pathCoordinates = (lineType: (typeof lineTypes)[number]) =>
|
||||
Array.from(
|
||||
(
|
||||
wrapper.get(`.waveform-chart__line[data-series-id="${lineType}"]`).attributes('d') ?? ''
|
||||
).matchAll(/[ML]([\d.-]+),([\d.-]+)/g),
|
||||
(match) => ({ x: Number(match[1]), y: Number(match[2]) }),
|
||||
)
|
||||
|
||||
const start = pathCoordinates('step-start')
|
||||
const middle = pathCoordinates('step-middle')
|
||||
const end = pathCoordinates('step-end')
|
||||
const after = pathCoordinates('step-after')
|
||||
expect(start.map((point) => point.x)).toEqual([start[0]?.x, start[0]?.x, start.at(-1)?.x])
|
||||
expect(middle[1]?.x).toBe(middle[2]?.x)
|
||||
expect(middle[1]?.x).toBe((middle[0]!.x + middle.at(-1)!.x) / 2)
|
||||
expect(end.map((point) => point.x)).toEqual([end[0]?.x, end.at(-1)?.x, end.at(-1)?.x])
|
||||
expect(after).toEqual(end)
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('renders per-series lines, point symbols, error bars, and matching legend swatches', async () => {
|
||||
const wrapper = await mountSizedChart({
|
||||
kind: 'series',
|
||||
series: [
|
||||
{
|
||||
id: 'triangle-errors',
|
||||
trackId: 'styled-track',
|
||||
name: '三角误差',
|
||||
lineType: 'none',
|
||||
pointType: 'triangle',
|
||||
errorBar: { visible: true },
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 1, error: 0.25 },
|
||||
{ x: 1, y: 2, error: 0.5 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'line-only',
|
||||
trackId: 'styled-track',
|
||||
name: '纯线',
|
||||
lineType: 'linear',
|
||||
lineStyle: 'dashed',
|
||||
pointType: 'none',
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 2 },
|
||||
{ x: 1, y: 3 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'step-errors',
|
||||
trackId: 'styled-track',
|
||||
name: '阶梯误差',
|
||||
lineType: 'step-after',
|
||||
lineStyle: 'dash-dot',
|
||||
pointType: 'circle',
|
||||
errorBar: { visible: true, color: '#222222', width: 2, capWidth: 10 },
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 3, lowerError: 0.5, upperError: 1 },
|
||||
{ x: 1, y: 4 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'errors-only',
|
||||
trackId: 'styled-track',
|
||||
name: '纯误差棒',
|
||||
lineType: 'none',
|
||||
pointType: 'none',
|
||||
errorBar: { visible: true },
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: 4, error: 0.5 },
|
||||
{ x: 1, y: 5, error: 0.5 },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(wrapper.find('.waveform-chart__line[data-series-id="triangle-errors"]').exists()).toBe(
|
||||
false,
|
||||
)
|
||||
const stepLine = wrapper.get('.waveform-chart__line[data-series-id="step-errors"]')
|
||||
expect(stepLine.attributes('data-line-type')).toBe('step-after')
|
||||
expect(stepLine.attributes('data-line-style')).toBe('dash-dot')
|
||||
expect(stepLine.attributes('stroke-dasharray')).toBe('8 5 1.5 5')
|
||||
expect(
|
||||
wrapper
|
||||
.get('.waveform-chart__line[data-series-id="line-only"]')
|
||||
.attributes('stroke-dasharray'),
|
||||
).toBe('8 5')
|
||||
expect(stepLine.attributes('d')).toMatch(/^M[\d.-]+,([\d.-]+)L[\d.-]+,\1L/)
|
||||
expect(
|
||||
wrapper
|
||||
.get('.waveform-chart__points[data-series-id="triangle-errors"]')
|
||||
.attributes('data-point-type'),
|
||||
).toBe('triangle')
|
||||
expect(wrapper.findAll('.waveform-chart__point')).toHaveLength(2)
|
||||
expect(
|
||||
wrapper
|
||||
.get('.waveform-chart__points[data-series-id="triangle-errors"] .waveform-chart__point')
|
||||
.attributes('d'),
|
||||
).toMatch(/M.*M/)
|
||||
expect(wrapper.findAll('.waveform-chart__error-bar')).toHaveLength(3)
|
||||
expect(
|
||||
wrapper
|
||||
.get('.waveform-chart__error-bars[data-series-id="step-errors"] .waveform-chart__error-bar')
|
||||
.attributes('stroke'),
|
||||
).toBe('#222222')
|
||||
const errorsOnlySeries = wrapper.get('.waveform-chart__series[data-series-id="errors-only"]')
|
||||
expect(errorsOnlySeries.find('.waveform-chart__line').exists()).toBe(false)
|
||||
expect(errorsOnlySeries.find('.waveform-chart__point').exists()).toBe(false)
|
||||
expect(errorsOnlySeries.find('.waveform-chart__error-bar').exists()).toBe(true)
|
||||
|
||||
const swatches = wrapper.findAll('.waveform-legend__swatch')
|
||||
expect(swatches.map((swatch) => swatch.attributes('data-line-type'))).toEqual([
|
||||
'none',
|
||||
'linear',
|
||||
'step-after',
|
||||
'none',
|
||||
])
|
||||
expect(swatches[0]?.attributes('data-error-bar-visible')).toBe('true')
|
||||
expect(swatches.map((swatch) => swatch.attributes('data-line-style'))).toEqual([
|
||||
'solid',
|
||||
'dashed',
|
||||
'dash-dot',
|
||||
'solid',
|
||||
])
|
||||
expect(swatches[1]?.get('.waveform-legend__line').attributes('stroke-dasharray')).toBe('8 5')
|
||||
expect(swatches[2]?.get('.waveform-legend__line').attributes('stroke-dasharray')).toBe(
|
||||
'8 5 1.5 5',
|
||||
)
|
||||
expect(swatches[2]?.attributes('data-error-bar-visible')).toBe('true')
|
||||
expect(swatches[3]?.attributes('data-error-bar-visible')).toBe('true')
|
||||
expect(swatches[0]!.findAll('path').map((path) => path.classes())).toEqual([
|
||||
['waveform-legend__error-bar'],
|
||||
['waveform-legend__point'],
|
||||
])
|
||||
const stepSwatchPaths = swatches[2]!.findAll('path')
|
||||
expect(stepSwatchPaths.map((path) => path.classes())).toEqual([
|
||||
['waveform-legend__line'],
|
||||
['waveform-legend__error-bar'],
|
||||
['waveform-legend__point'],
|
||||
])
|
||||
expect(stepSwatchPaths[0]?.attributes()).toMatchObject({
|
||||
d: 'M1 8H25',
|
||||
stroke: '#389e0d',
|
||||
'stroke-width': '1.5',
|
||||
})
|
||||
expect(stepSwatchPaths[1]?.attributes()).toMatchObject({
|
||||
d: 'M8 2H18M13 2V14M8 14H18',
|
||||
stroke: '#222222',
|
||||
'stroke-width': '2',
|
||||
'stroke-linecap': 'butt',
|
||||
})
|
||||
expect(stepSwatchPaths[2]?.attributes('transform')).toBe('translate(13 8)')
|
||||
expect(swatches[3]!.findAll('path').map((path) => path.classes())).toEqual([
|
||||
['waveform-legend__error-bar'],
|
||||
])
|
||||
|
||||
const renderedSeriesNodes = wrapper
|
||||
.findAll('.waveform-chart__line, .waveform-chart__point, .waveform-chart__error-bar')
|
||||
.map((node) => node.element)
|
||||
const overlay = wrapper.get('.waveform-chart__overlay--independent')
|
||||
const overlayWidth = Number(overlay.attributes('width'))
|
||||
const overlayHeight = Number(overlay.attributes('height'))
|
||||
Object.defineProperty(overlay.element, 'getBoundingClientRect', {
|
||||
value: () => ({ left: 0, top: 0, width: overlayWidth, height: overlayHeight }),
|
||||
})
|
||||
overlay.element.dispatchEvent(
|
||||
new MouseEvent('pointermove', {
|
||||
clientX: overlayWidth / 2,
|
||||
clientY: overlayHeight / 2,
|
||||
bubbles: true,
|
||||
}),
|
||||
)
|
||||
flushAnimationFrames()
|
||||
await flushPromises()
|
||||
expect(
|
||||
wrapper
|
||||
.findAll('.waveform-chart__line, .waveform-chart__point, .waveform-chart__error-bar')
|
||||
.map((node) => node.element),
|
||||
).toEqual(renderedSeriesNodes)
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('binds overlaid series to at most four value axes in multi-axis mode', async () => {
|
||||
const data: WaveformData = {
|
||||
kind: 'series',
|
||||
series: Array.from({ length: 5 }, (_, index) => ({
|
||||
id: `overlaid-${index}`,
|
||||
trackId: 'shared-frame',
|
||||
name: `叠加通道 ${index + 1}`,
|
||||
data: {
|
||||
kind: 'points',
|
||||
points: [
|
||||
{ x: 0, y: index * 100 },
|
||||
{ x: 1, y: index * 100 + 10 },
|
||||
],
|
||||
},
|
||||
})),
|
||||
}
|
||||
const wrapper = await mountSizedChart(data, { overlayMode: 'multi-axis' })
|
||||
|
||||
expect(wrapper.attributes('data-overlay-mode')).toBe('multi-axis')
|
||||
expect(
|
||||
wrapper
|
||||
.findAll('.waveform-chart__axis--y')
|
||||
.map((axis) => axis.attributes('data-y-axis-side')),
|
||||
).toEqual(['left', 'left', 'right', 'right'])
|
||||
expect(
|
||||
wrapper.findAll('.waveform-chart__line').map((line) => line.attributes('data-y-axis-index')),
|
||||
).toEqual(['0', '1', '2', '3', '3'])
|
||||
expect(wrapper.findAll('.waveform-track__multi-axis-title')).toHaveLength(4)
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('does not render empty multi-axis title backgrounds', async () => {
|
||||
const data: WaveformData = {
|
||||
kind: 'series',
|
||||
series: [
|
||||
{
|
||||
id: 'empty-title-a',
|
||||
trackId: 'shared-frame',
|
||||
name: '',
|
||||
data: { kind: 'samples', values: [0, 1], sampleRate: 1 },
|
||||
},
|
||||
{
|
||||
id: 'empty-title-b',
|
||||
trackId: 'shared-frame',
|
||||
name: ' ',
|
||||
data: { kind: 'samples', values: [10, 20], sampleRate: 1 },
|
||||
},
|
||||
],
|
||||
}
|
||||
const wrapper = await mountSizedChart(data, { overlayMode: 'multi-axis', yLabel: '' })
|
||||
|
||||
expect(wrapper.findAll('.waveform-chart__axis--y')).toHaveLength(2)
|
||||
expect(wrapper.findAll('.waveform-track__multi-axis-title')).toHaveLength(0)
|
||||
expect(wrapper.findAll('.waveform-chart__y-axis-label-bg')).toHaveLength(0)
|
||||
|
||||
wrapper.unmount()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user