summaryrefslogtreecommitdiff
path: root/frontend/src/lib/sparkline.test.ts
blob: aecf20d2a86ff840fe167562bd8aa4f14c869ca0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// @ts-nocheck
import { describe, expect, it, vi } from 'vitest';
import { mount, unmount } from 'svelte';
import Sparkline from '../components/Sparkline.svelte';

// Leader round2: 项目列表每行内嵌迷你权益缩略图——
// 用最近一个回测 equity 的首尾点画 sparkline SVG;
// 无数据就整个组件留空(不渲染 svg)。

describe('Sparkline (real render)', () => {
  it('renders an svg with a first→last polyline when handed endpoints', async () => {
    const host = document.createElement('div');
    const inst = mount(Sparkline, {
      target: host,
      props: { first: 100, last: 90, up: false, ariaLabel: '最近回测权益缩略' }
    });
    await new Promise((r) => setTimeout(r, 50));
    const svg = host.querySelector('svg');
    expect(svg, 'sparkline must be a real svg element').toBeTruthy();
    const path = svg.querySelector('path, polyline');
    expect(path).toBeTruthy();
    const d = (path.getAttribute('d') || path.getAttribute('points')) ?? '';
    // polyline from left edge to right edge: both endpoints present in geometry
    expect(d).toContain('0'); // first x
    const coordsCount = d.trim().split(/[\s,L,M]+/).filter(Boolean).length;
    expect(coordsCount).toBeGreaterThanOrEqual(4); // 2 points × (x,y)
    unmount(inst);
    host.remove();
  });

  it('renders NOTHING (no svg) for missing data — 留空不渲染', async () => {
    const host = document.createElement('div');
    const inst = mount(Sparkline, { target: host, props: { first: null, last: null, ariaLabel: 'x' } });
    await new Promise((r) => setTimeout(r, 50));
    expect(host.querySelector('svg')).toBeNull();
    expect(host.textContent.trim()).toBe('');
    unmount(inst);
    host.remove();
  });

  it('方向语义:down 变红(危险色),up 变绿(成功色)', async () => {
    const down = document.createElement('div');
    const inst1 = mount(Sparkline, {
      target: down,
      props: { first: 100, last: 90, up: false, ariaLabel: 'x' }
    });
    await new Promise((r) => setTimeout(r, 30));
    const downColor = down.querySelector('path, polyline')?.getAttribute('stroke') ?? '';
    unmount(inst1);
    down.remove();

    const up = document.createElement('div');
    const inst2 = mount(Sparkline, {
      target: up,
      props: { first: 100, last: 130, up: true, ariaLabel: 'x' }
    });
    await new Promise((r) => setTimeout(r, 30));
    const upColor = up.querySelector('path, polyline')?.getAttribute('stroke') ?? '';
    unmount(inst2);
    up.remove();

    expect(downColor).not.toBe('');
    expect(upColor).not.toBe('');
    expect(downColor).not.toBe(upColor);
  });
});