diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-18 18:36:34 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-18 18:36:34 +0800 |
| commit | 7ac49d4b64aea042fd0bf0549e39cc8bdddd2513 (patch) | |
| tree | 56a4594c53d9e9b19c157873d25dc27a74b09cd1 | |
| parent | b2c2f9db4b334427c34b2111a4b6609b7af0339b (diff) | |
| download | strategy-lab-7ac49d4b64aea042fd0bf0549e39cc8bdddd2513.tar.gz | |
[实现方案] 守门测试:assumptions 折叠区渲染/缺省不渲染/渲染路径不含旧拼串文案(弹簧88 例全绿)
| -rw-r--r-- | frontend/src/lib/assumptions.test.ts | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/frontend/src/lib/assumptions.test.ts b/frontend/src/lib/assumptions.test.ts new file mode 100644 index 0000000..26bb916 --- /dev/null +++ b/frontend/src/lib/assumptions.test.ts @@ -0,0 +1,85 @@ +// @ts-nocheck +import { describe, expect, it, vi } from 'vitest'; +import { mount, unmount } from 'svelte'; +import resultsRaw from '../pages/ProjectResultsTab.svelte?raw'; +import backtestRaw from '../pages/ProjectBacktestTab.svelte?raw'; + +// 用户拍板方案 1:执行假设长文不再混入用户面 warnings。 +// worker 已把 EXECUTION_ASSUMPTIONS 移到 result.assumptions(tests/worker/test_backtest.py +// test_assumptions_out_of_warnings 守门 worker 侧);本文件守门前端渲染侧: +// 技术口径只在 assumptions 字段驱动下渲染,且默认折叠(Collapsible)。 + +const PROJECT_ID = '7630e296-0b2f-44c3-85f1-fe695e7a7e4b'; +const RUN_ID = '569b23d0-1111-4222-8333-4444444444442'; +const ASSUMPTIONS = { slippage: '0.1%', 'next_bar_open_fill': true }; + +function resultBody(withAssumptions) { + return { + id: RUN_ID, project_id: PROJECT_ID, version_id: 'v', dataset_id: 'd', + status: 'succeeded', + config: { capital: 100000, commission: 0.0003, slippage: 0.001 }, + created_at: '2026-01-01T00:00:00Z', + result: { + engine: { name: 'backtrader', version: '1.9' }, + metrics: { total_return: 0.0123, annual_return: 0.05, max_drawdown: -0.033, sharpe: 0.9, trade_count: 1, final_equity: 101234.5 }, + equity: [{ date: '2024-01-02', equity: 100000, cash: 100000 }], + orders: [], trades: [], closed_trades: [], + logs: [], warnings: ['真实警告:数据源公告休市'], + assumptions: withAssumptions ? ASSUMPTIONS : undefined, + elapsed_ms: 1, + }, + }; +} + +const fetchMock = (body) => (url) => { + if (/\/api\/runs\/[0-9a-f-]+$/.test(String(url))) return Promise.resolve(new Response(JSON.stringify(body), { status: 200, headers: { 'content-type': 'application/json' } })); + if (/\/api\/projects\/[0-9a-f-]+$/.test(String(url))) + return Promise.resolve(new Response(JSON.stringify({ id: PROJECT_ID, name: '端到端验收项目', draft_code: 'x=1', draft_generation: 2 }), { status: 200, headers: { 'content-type': 'application/json' } })); + return Promise.resolve(new Response('{"items":[]}', { status: 200, headers: { 'content-type': 'application/json' } })); +}; + +async function mountResultsTab(body) { + vi.stubGlobal('ResizeObserver', class { observe() {} unobserve() {} disconnect() {} }); + vi.stubGlobal('fetch', fetchMock(body)); + const ProjectResultsTab = (await import('../pages/ProjectResultsTab.svelte')).default; + const host = document.createElement('div'); + document.body.appendChild(host); + const inst = mount(ProjectResultsTab, { target: host, props: { projectId: PROJECT_ID, runId: RUN_ID } }); + await new Promise((r) => setTimeout(r, 80)); + return { inst, host }; +} + +describe('技术口径:assumptions 独立折叠区,不混入 warnings', () => { + it('assumptions 渲染在折叠区;warnings 列表只含真实警告', { timeout: 20000 }, async () => { + const { inst, host } = await mountResultsTab(resultBody(true)); + try { + const text = host.textContent.replace(/\s+/g, ' '); + // warnings Alert 渲染真实警告 + expect(text).toContain('真实警告:数据源公告休市'); + // assumptions keys/values 不出现在 warnings <li> + const warnLis = [...host.querySelectorAll('li')].map((n) => n.textContent); + for (const k of Object.keys(ASSUMPTIONS)) { + expect(warnLis.some((w) => w.includes(k))).toBe(false); + } + // 折叠区标题存在(默认收起,仅结构存在不展开内容) + expect(host.querySelector('[data-testid="assumptions-toggle"]')?.textContent).toContain('技术口径'); + expect(host.querySelector('[data-testid="assumptions-list"]')).toBeTruthy(); + } finally { unmount(inst); host.remove(); vi.unstubAllGlobals(); } + }); + + it('没有 assumptions 字段则不渲染技术口径区', async () => { + const { inst, host } = await mountResultsTab(resultBody(false)); + try { + expect(host.querySelector('[data-testid="assumptions-toggle"]')).toBeNull(); + expect(host.querySelector('[data-testid="assumptions-list"]')).toBeNull(); + } finally { unmount(inst); host.remove(); vi.unstubAllGlobals(); } + }); + + it('渲染路径源码不含 "execution assumptions" 旧拼串文案', () => { + for (const src of [resultsRaw, backtestRaw]) { + expect(src).not.toContain('execution assumptions'); + // assumptions 数据只进 技术口径 折叠区(一个 dl 列表锚点) + expect(src).toContain('assumptions-list'); + } + }); +}); |
