rebuild(stage-5): establish market data gateway and charts

This commit is contained in:
leefer
2026-07-30 02:35:42 +08:00
parent 40ad5d6836
commit cf0ab7026f
45 changed files with 2701 additions and 46 deletions
+118
View File
@@ -0,0 +1,118 @@
const fs = require("node:fs");
const path = require("node:path");
const { expect, test } = require("@playwright/test");
const evidence = path.resolve(__dirname, "../../docs/evidence/stage-5");
test.beforeAll(() => fs.mkdirSync(evidence, { recursive: true }));
async function authenticate(page) {
await page.goto("/");
await page.getByLabel("账号名").fill("stage5admin");
await page.getByLabel("密码").fill("Stage5-pass-123!");
await page.getByRole("button", { name: "登录", exact: true }).click();
await expect(page.locator(".sidebar, .field-error")).toBeVisible();
if (!(await page.locator(".sidebar").isVisible())) {
await page.getByRole("tab", { name: "注册" }).click();
await page.getByRole("button", { name: "注册并登录" }).click();
}
}
function chartPayload(interval) {
const daily = [
["2026-07-23", 3500, 3540, 3480, 3530],
["2026-07-24", 3530, 3568, 3510, 3552],
["2026-07-25", 3550, 3580, 3524, 3540],
["2026-07-28", 3542, 3590, 3530, 3582],
["2026-07-29", 3585, 3612, 3570, 3604],
];
const minute = [
["09:30", 3600, 3608, 3594, 3604, 3602],
["10:30", 3604, 3616, 3600, 3610, 3607],
["11:30", 3610, 3614, 3602, 3606, 3608],
["14:00", 3606, 3620, 3604, 3618, 3610],
["15:00", 3618, 3622, 3608, 3612, 3613],
];
return {
entity_type: "index",
identifier: "000001.SH",
code: "000001",
name: "上证指数",
interval,
trade_date: "2026-07-29",
observed_at: "2026-07-29T15:00:00+08:00",
previous_close: 3594,
range_start: interval === "minute" ? "09:30" : null,
range_end: interval === "minute" ? "15:00" : null,
points: (interval === "day" ? daily : minute).map((row) => ({
time: row[0],
open: row[1],
high: row[2],
low: row[3],
close: row[4],
volume: 100000,
amount: 360000000,
average: interval === "minute" ? row[5] : null,
})),
};
}
test("latest snapshot, grouped search, chart preview and entity detail", async ({ page }) => {
const consoleErrors = [];
page.on("console", (message) => {
if (message.type() === "error" && !message.text().includes("401 (Unauthorized)")) {
consoleErrors.push(message.text());
}
});
await page.route("**/api/market/summary", (route) =>
route.fulfill({
contentType: "application/json",
body: JSON.stringify({
context: {
requested_date: "2026-07-30",
actual_date: "2026-07-29",
previous_date: "2026-07-28",
observed_at: "2026-07-29T15:00:00+08:00",
state: "final",
carried_forward: true,
message: "沿用最近真实收盘快照",
},
values: { temperature: 42, limit_up: 68, limit_down: 4, broken: 24, seal_rate: 73.9, amount: 1628000000000 },
}),
}),
);
await page.route("**/api/market/entities/index/000001.SH/charts/*", (route) => {
const interval = route.request().url().endsWith("/minute") ? "minute" : "day";
return route.fulfill({ contentType: "application/json", body: JSON.stringify(chartPayload(interval)) });
});
await authenticate(page);
await expect(page.locator(".market-strip-row")).toContainText("涨停 68");
await expect(page.locator(".market-strip-row")).toContainText("07/29 15:00");
await page.keyboard.press("Control+K");
const dialog = page.getByRole("dialog", { name: "全局搜索" });
await dialog.getByPlaceholder("搜索股票、板块、题材或指数").fill("上证");
await expect(dialog.getByRole("button", { name: /上证指数/ })).toBeVisible();
await expect(dialog.locator(".market-chart")).toBeVisible();
await expect(dialog).toContainText("数据日期 2026-07-29");
await page.screenshot({ path: path.join(evidence, "search-preview-light-1920x1080.jpg"), type: "jpeg", quality: 82 });
await dialog.getByRole("button", { name: /上证指数/ }).click();
await expect(page).toHaveURL(/\/market\/index\/000001.SH/);
await expect(page.getByRole("heading", { name: "上证指数" })).toBeVisible();
await page.getByRole("button", { name: "分时" }).click();
await expect(page.locator(".chart-zero")).toHaveCount(1);
await expect(page.locator(".preview-meta")).toContainText("09:3015:00");
await page.getByRole("button", { name: "夜间" }).click();
await page.screenshot({ path: path.join(evidence, "entity-detail-dark-1920x1080.jpg"), type: "jpeg", quality: 82 });
expect(await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth)).toBe(0);
await page.setViewportSize({ width: 390, height: 844 });
await expect(page.locator(".market-chart")).toBeVisible();
expect(await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth)).toBe(0);
await page.screenshot({ path: path.join(evidence, "entity-detail-dark-390x844.jpg"), type: "jpeg", quality: 82 });
expect(consoleErrors).toEqual([]);
});