Files
easy_tdx_max/web-ui/e2e/watchlist.spec.ts
T
awayingsandClaude Code fb35677802 feat: 自选列表新增「近3日/近1周/近2周」涨跌幅三列(issue #7)
交易日偏移口径:T = 上证指数日线(交易日历)中 <= 今天的最后一天,
D_n = T 往前 n 个交易日,锚点 = 个股日线(/bars 同款 QFQ)中
date <= D_n 的最后一根 bar。后端只回锚点收盘价,涨跌幅由前端用
SSE 实时价现算,盘中三列随报价免费跳动、无需轮询本接口。

- 新增 GET /watchlist/returns + 纯计算模块 web/returns.py(零 IO,单测覆盖
  停牌回退/次新 null/除权日 QFQ/非交易日回退等口径)
- 个股日线与交易日历均进程内缓存(当日不变、次日失效),重复刷新零行情请求;
  日历缺今天(serve 盘前启动)时按 60s 间隔重取,避免 T 整体前移
- 取数并发 ≤ 4(TDX 防封红线);单只失败只落 error,不影响整表
- 前端 +3 列(着色复用 dirClass/fmtPctSigned),e2e 同步断言

与 issue 定稿的两处偏差(/simplify 收敛,"减少不必要的改动"):
- 删除 windows 查询参数:列名与窗口一一对应(issue 亦将"用户自定义窗口"
  列为 out of scope),固定 3/5/10
- 个股缓存由磁盘 JSON 改为进程内 dict:可观测行为不变(当日不重复请求),
  但 serve 重启后当天首次请求会重取一次

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-11 11:39:10 +08:00

55 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 自选页 E2E:加入自选(行情校验 + 名称补全走 mock)→ 表格出现 → 删除 → 消失。
// 另覆盖 issue #7 的「近3日 / 近1周 / 近2周」三列(交易日偏移口径,锚点走后端
// /watchlist/returns,涨跌幅由前端用实时价现算)。
//
// 每轮 E2E 用独立的临时 EASY_TDX_CONFIG_DIR,自选从空开始,断言可写死。
import { expect, test } from '@playwright/test'
test('自选页增删自选', async ({ page }) => {
await page.goto('/watchlist')
// 初始为空(临时配置目录)
await expect(page.locator('.empty-row')).toBeVisible()
// 空行 colspan 与表头列数一致(新增 3 列后 = 15)
await expect(page.locator('.empty-row td')).toHaveAttribute('colspan', '15')
// 加入 600519(市场自动识别 SH;名称走 mock /mac/symbol-info → 贵州茅台)
await page.fill('.code-input', '600519')
await page.getByRole('button', { name: '加入自选' }).click()
await expect(page.locator('.data-row')).toHaveCount(1, { timeout: 30_000 })
await expect(page.locator('.data-row .cell-name')).toHaveText('贵州茅台')
await expect(page.locator('.data-row .cell-code')).toHaveText('SH600519')
// 删除后表格回到空态
await page.locator('.data-row .del').first().click()
await expect(page.locator('.data-row')).toHaveCount(0)
await expect(page.locator('.empty-row')).toBeVisible()
})
test('自选页近3日/近1周/近2周涨跌幅三列', async ({ page }) => {
await page.goto('/watchlist')
await page.fill('.code-input', '600519')
await page.getByRole('button', { name: '加入自选' }).click()
await expect(page.locator('.data-row')).toHaveCount(1, { timeout: 30_000 })
// 表头:现价/涨跌幅之后依次是 近3日、近1周、近2周(共 15 列 = 12 + 3
const headers = page.locator('.qtable thead th')
await expect(headers).toHaveCount(15)
await expect(headers.nth(2)).toHaveText('涨跌幅')
await expect(headers.nth(3)).toHaveText('近3日')
await expect(headers.nth(4)).toHaveText('近1周')
await expect(headers.nth(5)).toHaveText('近2周')
// 数据格:与表头列数一致,三列都是带符号百分比(合成行情锚点 → 一定会算出数)
const cells = page.locator('.data-row td')
await expect(cells).toHaveCount(15)
for (const i of [3, 4, 5]) {
await expect(cells.nth(i)).toHaveText(/^[+-]?\d+\.\d+%$/)
}
await page.locator('.data-row .del').first().click()
await expect(page.locator('.data-row')).toHaveCount(0)
})