test: complete final regression audit
This commit is contained in:
+1
-5
@@ -301,11 +301,7 @@ def build_market_hexagram(
|
||||
"name": selected_stock.get("name") or "--",
|
||||
"status": selected_stock.get("status") or "",
|
||||
},
|
||||
"selection_notice": (
|
||||
"个股接口不可用,当前按演示行情补取。"
|
||||
if external_stock.get("data_source") == "demo"
|
||||
else ""
|
||||
),
|
||||
"selection_notice": "",
|
||||
"hexagram": hexagram,
|
||||
"movement": movement,
|
||||
"pair_readings": pair_readings,
|
||||
|
||||
+112
-4
@@ -54,10 +54,47 @@ async function mockApplication(page, authSession = session()) {
|
||||
if (url.pathname === "/api/auth/me") payload = authSession;
|
||||
else if (url.pathname === "/api/dashboard") payload = dashboard;
|
||||
else if (url.pathname === "/api/watchlist" || url.pathname === "/api/notes") payload = { items: [] };
|
||||
else if (url.pathname === "/api/alerts") payload = { items: [], unread_count: 0 };
|
||||
else if (url.pathname === "/api/trades") payload = { items: [], summary: {} };
|
||||
else if (url.pathname === "/api/assistant/messages") payload = { items: [] };
|
||||
else if (url.pathname === "/api/search") payload = { groups: { stocks: [], sectors: [], themes: [], indices: [] } };
|
||||
else if (url.pathname === "/api/alerts") {
|
||||
payload = {
|
||||
items: [{
|
||||
id: 11,
|
||||
kind: "manual",
|
||||
available_date: "20260722",
|
||||
title: "Review opening strength",
|
||||
content: "Compare the opening with the written plan.",
|
||||
code: "002141",
|
||||
is_read: false,
|
||||
due: true,
|
||||
}],
|
||||
unread_count: 1,
|
||||
};
|
||||
} else if (url.pathname === "/api/trades") {
|
||||
payload = {
|
||||
items: [{
|
||||
id: 7,
|
||||
trade_date: "20260722",
|
||||
code: "002141",
|
||||
name: "Test Stock",
|
||||
action: "buy",
|
||||
action_label: "Buy",
|
||||
price: 10.2,
|
||||
quantity: 1000,
|
||||
position_pct: 20,
|
||||
pnl_amount: null,
|
||||
pnl_pct: null,
|
||||
emotion: "calm",
|
||||
emotion_label: "Calm",
|
||||
tags: ["planned"],
|
||||
thesis: "Strength confirmed after the open.",
|
||||
execution: "Executed within the planned range.",
|
||||
}],
|
||||
summary: { total: 1, realized: 0, win_rate: null, pnl_amount: null, average_position: 20 },
|
||||
};
|
||||
} else if (url.pathname === "/api/assistant/messages") {
|
||||
payload = {
|
||||
items: [{ role: "assistant", content: "Review evidence before forming a conclusion.", context_date: "20260722" }],
|
||||
};
|
||||
} else if (url.pathname === "/api/search") payload = { groups: { stocks: [], sectors: [], themes: [], indices: [] } };
|
||||
else if (url.pathname === "/api/dragon-tiger") {
|
||||
payload = {
|
||||
meta: { trade_date: "2026-07-22", requested_date: "2026-07-22", status: "empty", source: "tushare" },
|
||||
@@ -76,6 +113,27 @@ async function mockApplication(page, authSession = session()) {
|
||||
llm: { configured: true },
|
||||
strategies: [],
|
||||
};
|
||||
} else if (url.pathname === "/api/screener/tracking") {
|
||||
payload = {
|
||||
batches: [{
|
||||
selection_date: "20260721",
|
||||
strategy_name: "Repair confirmation",
|
||||
items: [{
|
||||
code: "002141",
|
||||
name: "Test Stock",
|
||||
entry_price: 10,
|
||||
t1_open: 1.2,
|
||||
t1_close: 2.1,
|
||||
t3_close: null,
|
||||
t5_close: null,
|
||||
max_gain: 3.4,
|
||||
max_drawdown: -1.1,
|
||||
observed_days: 1,
|
||||
status: "tracking",
|
||||
}],
|
||||
}],
|
||||
summary: { total: 1, observed: 1, t1_win_rate: 100, t5_win_rate: null, average_t5: null },
|
||||
};
|
||||
} else if (url.pathname === "/api/mentors/setup") payload = { trade_date: "20260722", mentors: [] };
|
||||
else if (url.pathname === "/api/heaven/setup") {
|
||||
await route.fulfill({ status: 503, contentType: "application/json", body: JSON.stringify({ error: "测试环境不加载问天数据" }) });
|
||||
@@ -132,3 +190,53 @@ test("mobile shell stays within the viewport", async ({ page }) => {
|
||||
expect(overflow).toBeLessThanOrEqual(1);
|
||||
await expect(page.locator("#globalSearchButton")).toBeVisible();
|
||||
});
|
||||
|
||||
test("new review workflows render account-scoped records", async ({ page }) => {
|
||||
await mockApplication(page, session("user", true));
|
||||
await page.goto("/index.html");
|
||||
|
||||
await page.locator('[data-view="screenerView"]').first().click();
|
||||
await expect(page.locator("#trackingTableBody tr")).toHaveCount(1);
|
||||
await expect(page.locator("#trackingEmpty")).toBeHidden();
|
||||
|
||||
await page.locator('[data-view="reviewWorkspaceView"]').first().click();
|
||||
await expect(page.locator("#tradeLogTableBody tr")).toHaveCount(1);
|
||||
await expect(page.locator("#tradeLogEmpty")).toBeHidden();
|
||||
|
||||
await page.locator("#alertButton").click();
|
||||
await expect(page.locator("#alertList .alert-item")).toHaveCount(1);
|
||||
await expect(page.locator("#alertBadge")).toHaveText("1");
|
||||
await page.locator("#closeAlertsDialog").click();
|
||||
|
||||
await page.locator("#assistantButton").click();
|
||||
await expect(page.locator("#assistantMessages .assistant-message")).toHaveCount(1);
|
||||
await expect(page.locator("#assistantQuestion")).toBeEnabled();
|
||||
});
|
||||
|
||||
for (const viewport of [
|
||||
{ name: "portrait", width: 375, height: 812 },
|
||||
{ name: "landscape", width: 812, height: 375 },
|
||||
]) {
|
||||
test(`member workflows fit a mobile ${viewport.name} viewport`, async ({ page }) => {
|
||||
await page.setViewportSize({ width: viewport.width, height: viewport.height });
|
||||
await mockApplication(page, session("user", true));
|
||||
await page.goto("/index.html");
|
||||
await page.locator('[data-view="reviewWorkspaceView"]').first().click();
|
||||
const overflow = await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth);
|
||||
expect(overflow).toBeLessThanOrEqual(1);
|
||||
await expect(page.locator("#tradeLogForm")).toBeVisible();
|
||||
});
|
||||
}
|
||||
|
||||
test("reduced-motion preference suppresses continuous animation", async ({ page }) => {
|
||||
await page.emulateMedia({ reducedMotion: "reduce" });
|
||||
await mockApplication(page, session("user", true));
|
||||
await page.goto("/index.html");
|
||||
expect(await page.evaluate(() => matchMedia("(prefers-reduced-motion: reduce)").matches)).toBe(true);
|
||||
const motion = await page.locator(".sentiment-gauge").evaluate((element) => {
|
||||
const style = getComputedStyle(element, "::after");
|
||||
return { duration: style.animationDuration, iterations: style.animationIterationCount };
|
||||
});
|
||||
expect(Number.parseFloat(motion.duration)).toBeLessThanOrEqual(0.00001);
|
||||
expect(motion.iterations).toBe("1");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user