summaryrefslogtreecommitdiff
path: root/frontend/src/lib/round2DashboardIntegration.test.ts
blob: eaa703c5b5d84a04597d35d1725aa46233367ef9 (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
// @ts-nocheck
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';
import { render, cleanup, waitFor } from '@testing-library/svelte';

vi.mock('../lib/client', async (importOriginal) => {
  const actual = await importOriginal<typeof import('../lib/client')>();
  return {
    ...actual,
    listProjects: vi.fn(),
    listDatasets: vi.fn(),
    listRuns: vi.fn(),
    getAIUsage: vi.fn()
  };
});

import ProjectsPage from '../pages/ProjectsPage.svelte';
import { listProjects, listDatasets, listRuns, getAIUsage } from '../lib/client';

beforeEach(() => {
  vi.mocked(listProjects).mockReset().mockResolvedValue({ items: [
    { id: 'pA', name: '项目A', description: null, draft_code: '', draft_generation: 1, created_at: '2026-01-01T00:00:00Z', updated_at: '2026-01-01T00:00:00Z' },
    { id: 'pB', name: '项目B', description: null, draft_code: '', draft_generation: 0, created_at: '2026-01-01T00:00:00Z', updated_at: '2026-01-01T00:00:00Z' }
  ]});
  vi.mocked(listDatasets).mockReset().mockResolvedValue({ items: [{ id: 'd1' }, { id: 'd2' }, { id: 'd3' }] });
  vi.mocked(listRuns).mockReset().mockResolvedValue({ items: [
    { id: 'r1', project_id: 'pA', status: 'succeeded', created_at: '2026-02-01T00:00:00Z', result: { equity: [{ equity: 100 }, { equity: 101 }, { equity: 112 }] } },
    { id: 'r2', project_id: 'pB', status: 'succeeded', created_at: '2026-02-01T00:00:00Z', result: null }
  ]});
  vi.mocked(getAIUsage).mockReset().mockResolvedValue({ totals: { input_tokens: 500, output_tokens: 200, requests: 2 } });
});

afterEach(() => cleanup());

// round6 旅程重排:首页去 4 张大卡,改为「问候 + 一行指标摘要(小字)
// + 新建主 CTA + 项目卡列表(名称/状态 badge/迷你 sparkline)」。
describe('ProjectsPage journey round6 (greeting + metrics summary + project cards)', () => {
  it('renders a one-line metrics summary, not 4 big cards', async () => {
    render(ProjectsPage);
    await waitFor(() => expect(vi.mocked(getAIUsage)).toHaveBeenCalled());
    await waitFor(() => expect(document.querySelector('[data-testid="metrics-summary"]')).toBeTruthy());
    expect(document.querySelectorAll('[data-testid="metric-card"]').length).toBe(0);
    const summary = document.querySelector('[data-testid="metrics-summary"]')!.textContent!.replace(/\s+/g, ' ');
    expect(summary).toContain('2 个项目');
    expect(summary).toContain('3 个数据集');
    expect(summary).toContain('2 次回测');
    expect(summary).toContain('AI 请求 2');
  });

  it('renders project cards with status badge and inline sparkline for equity runs', async () => {
    render(ProjectsPage);
    await waitFor(() => expect(vi.mocked(listRuns)).toHaveBeenCalled());
    await waitFor(() => expect(document.querySelector('[data-testid="sparkline"]')).toBeTruthy());
    const linkA = document.querySelector('[data-testid="project-link"]');
    expect(linkA).toBeTruthy();
    expect(linkA!.textContent).toContain('项目A');
    // 项目B has a succeeded run without equity → “完成” badge, no sparkline
    const cardB = [...document.querySelectorAll('[role="listitem"]')].find((n) => n.textContent!.includes('项目B'))!;
    expect(cardB.querySelector('[data-testid="sparkline"]')).toBeNull();
    expect(cardB.textContent).toContain('完成');
  });
});