// @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(); 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('[data-testid="metric-value"]')].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(); }); });