import { describe, expect, it } from "vitest" import type { SelectionChartPoint } from "../api/selection.types" import { buildSelectionChartOption } from "./selection-chart-option" function point(index: number): SelectionChartPoint { return { close: index + 10.5, d: index + 20, high: index + 11, j: index + 30, k: index + 10, low: index + 9, open: index + 10, trade_date: `2026-${String(Math.floor(index / 28) + 1).padStart(2, "0")}-${String((index % 28) + 1).padStart(2, "0")}`, trend_white: index + 10.2, trend_yellow: index + 10.4, volume: index + 1000, } } describe("selection chart option", () => { it("aligns all three grids and opens on exactly the last 120 points", () => { const points = Array.from({ length: 250 }, (_, index) => point(index)) const option = buildSelectionChartOption(points) const dataZoom = option.dataZoom as Array<{ endValue: string startValue: string xAxisIndex: number[] }> const series = option.series as Array<{ data: unknown[] name: string xAxisIndex: number yAxisIndex: number }> const legends = option.legend as Array<{ data: string[] }> expect(dataZoom).toHaveLength(2) expect(dataZoom[0]).toMatchObject({ endValue: points[249].trade_date, startValue: points[130].trade_date, xAxisIndex: [0, 1, 2], }) expect(dataZoom[1].xAxisIndex).toEqual([0, 1, 2]) expect(legends[0]?.data).toEqual(["知行白线", "知行黄线"]) expect(series.find((item) => item.name === "日线")).toMatchObject({ xAxisIndex: 0, yAxisIndex: 0, }) expect(series.find((item) => item.name === "知行白线")).toMatchObject({ data: points.map((item) => item.trend_white), xAxisIndex: 0, yAxisIndex: 0, }) expect(series.find((item) => item.name === "知行黄线")).toMatchObject({ data: points.map((item) => item.trend_yellow), xAxisIndex: 0, yAxisIndex: 0, }) expect(series.find((item) => item.name === "成交量")).toMatchObject({ xAxisIndex: 1, yAxisIndex: 1, }) expect(series.filter((item) => item.xAxisIndex === 2)).toHaveLength(3) expect(series[0].data[0]).toEqual([10, 10.5, 9, 11]) }) it("keeps missing candles and indicator values empty", () => { const incomplete = { ...point(0), close: null, d: null, high: null, j: null, k: null, trend_white: null, trend_yellow: null, volume: null, } const option = buildSelectionChartOption([incomplete]) const series = option.series as Array<{ connectNulls?: boolean data: unknown[] name: string }> const candle = series[0].data[0] as number[] const volume = series.find((item) => item.name === "成交量") const lines = series.filter((item) => item.connectNulls === false) expect(candle).toHaveLength(4) expect(candle.every(Number.isNaN)).toBe(true) expect(volume?.data[0]).toMatchObject({ value: null }) expect(lines).toHaveLength(5) for (const indicator of lines) { expect(indicator.data).toEqual([null]) } }) })