diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-18 09:52:14 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-18 09:52:14 +0800 |
| commit | c71930f79b102f5a3cade7877dba425462ed758a (patch) | |
| tree | a56e55c076c0ef5238582f97cc2989c7b0217f13 /frontend | |
| parent | 0022c0748ada1e9022f63f7e985398d26111dc06 (diff) | |
| download | strategy-lab-c71930f79b102f5a3cade7877dba425462ed758a.tar.gz | |
test(frontend): 第二轮首页聚合真实渲染集成测试
[变更性质] 测试补充,归入第二轮验证件。
[新增内容] mock listProjects/listDatasets/listRuns/getAIUsage 后渲染 ProjectsPage,断言 4 张 metric-card 与 2 处 sparkline-cell 的真实 DOM 输出。
[影响范围] frontend/src/lib/round2DashboardIntegration.test.ts(2 用例)。
Diffstat (limited to 'frontend')
| -rw-r--r-- | frontend/src/lib/round2DashboardIntegration.test.ts | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/frontend/src/lib/round2DashboardIntegration.test.ts b/frontend/src/lib/round2DashboardIntegration.test.ts new file mode 100644 index 0000000..363e1da --- /dev/null +++ b/frontend/src/lib/round2DashboardIntegration.test.ts @@ -0,0 +1,58 @@ +// @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()); + +// Leader round2: 登录后默认页 = 指标卡行 + 项目行迷你权益缩略图。 +describe('ProjectsPage dashboard round2 (metric row + row sparkline, real render)', () => { + it('renders the 4-card metric row with真实聚合 numbers', async () => { + render(ProjectsPage); + await waitFor(() => expect(vi.mocked(getAIUsage)).toHaveBeenCalled()); + const cards = document.querySelectorAll('[data-testid="metric-card"]'); + await waitFor(() => expect(cards.length).toBe(4)); + const values = [...document.querySelectorAll('.metric-row .mvalue')].map((n) => n.textContent!.replace(/\s+/g, ' ').trim()); + expect(values[0]).toBe('2'); + expect(values[1]).toBe('3'); + expect(values[2]).toContain('已完成'); + expect(values[2]).toContain('2'); + }); + + it('renders an inline sparkline row cell for projects whose latest run has equity, none for data-less ones', async () => { + render(ProjectsPage); + await waitFor(() => expect(vi.mocked(listRuns)).toHaveBeenCalled()); + const rows = await waitFor(() => document.querySelectorAll('tbody tr')); + await waitFor(() => expect(document.querySelector('svg[data-testid="sparkline"]')).toBeTruthy()); + const rowA = [...document.querySelectorAll('tbody tr')].find((r) => r.textContent!.includes('项目A'))!; + const rowB = [...document.querySelectorAll('tbody tr')].find((r) => r.textContent!.includes('项目B'))!; + expect(rowA.querySelector('svg[data-testid="sparkline"]'), '项目A has equity → sparkline renders').toBeTruthy(); + expect(rowB.querySelector('svg[data-testid="sparkline"]'), '项目B has no equity → stays empty').toBeNull(); + }); +}); |
