220 lines
8.3 KiB
TypeScript
220 lines
8.3 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
||
const headers = { "X-WQ-Request": "1" };
|
||
|
||
test("Super Alpha web lifecycle, generic simulation, evidence and type routing", async ({
|
||
page,
|
||
}) => {
|
||
const errors: string[] = [];
|
||
page.on("pageerror", (e) => errors.push(e.message));
|
||
await page.goto("/#superalpha-research");
|
||
await page.getByLabel("密码", { exact: true }).fill("browser-test-password");
|
||
await page.getByRole("button", { name: "进入工作空间" }).click();
|
||
await expect(
|
||
page.getByRole("button", { name: "新建 Super Alpha 方案", exact: true }),
|
||
).toBeVisible();
|
||
await page.request.put("/api/v1/account/credentials", {
|
||
headers,
|
||
data: { email: "test@example.com", password: "synthetic-password" },
|
||
});
|
||
await page.request.post("/api/v1/account/connect", { headers });
|
||
await expect
|
||
.poll(
|
||
async () =>
|
||
(await (await page.request.get("/api/v1/account")).json())
|
||
.connection_status,
|
||
)
|
||
.toBe("connected");
|
||
await page
|
||
.getByRole("button", { name: "新建 Super Alpha 方案", exact: true })
|
||
.click();
|
||
await page.getByLabel("方案名称", { exact: true }).fill("浏览器 SUPER 验收");
|
||
await page
|
||
.getByLabel("研究假设", { exact: true })
|
||
.fill("比较低换手组件与等权基线");
|
||
await page
|
||
.getByLabel("Selection", { exact: true })
|
||
.fill("turnover < {threshold}");
|
||
await page.getByLabel("Combo", { exact: true }).fill("alpha");
|
||
await page
|
||
.getByLabel("参数候选 JSON", { exact: true })
|
||
.fill('{"threshold":{"kind":"number","values":[0.1,0.2]}}');
|
||
await page.getByRole("button", { name: "同步合法设置", exact: true }).click();
|
||
await page.getByRole("button", { name: "选择组合", exact: true }).click();
|
||
await page.getByRole("combobox", { name: "Region", exact: true }).click();
|
||
await page.getByRole("option").filter({ hasText: /^USA$/ }).click();
|
||
await page.getByRole("combobox", { name: "Universe", exact: true }).click();
|
||
await page
|
||
.getByRole("option")
|
||
.filter({ hasText: /^TOP3000$/ })
|
||
.click();
|
||
await page.getByRole("button", { name: "应用组合", exact: true }).click();
|
||
await page.getByRole("button", { name: "保存方案", exact: true }).click();
|
||
await expect(page.getByText("已保存版本 1", { exact: true })).toBeVisible();
|
||
await page
|
||
.getByRole("button", { name: "预览 Selection(首组参数)", exact: true })
|
||
.click();
|
||
await expect(page.locator(".super-components")).toContainText("已核实 2 个");
|
||
await page.getByRole("tab", { name: "固定候选", exact: true }).click();
|
||
const building = page.waitForResponse(
|
||
(r) =>
|
||
r.url().endsWith("/superalpha/candidates") &&
|
||
r.request().method() === "POST",
|
||
);
|
||
await page.getByRole("button", { name: "展开固定候选", exact: true }).click();
|
||
const experiment = await (await building).json();
|
||
expect(experiment.total).toBe(4);
|
||
const table = page.locator(
|
||
".super-research .semi-tabs-pane-active .workspace-table",
|
||
);
|
||
await expect(table.locator("tbody tr.semi-table-row")).toHaveCount(4);
|
||
expect(
|
||
Math.round(
|
||
(await table.locator("tbody tr.semi-table-row").first().boundingBox())!
|
||
.height,
|
||
),
|
||
).toBe(40);
|
||
await table.locator("thead .semi-checkbox").click();
|
||
await page
|
||
.getByRole("button", { name: "预览回测(4)", exact: true })
|
||
.click();
|
||
await expect(
|
||
page.getByText(/浏览器 SUPER 验收 · 4 条候选 · 4 个平台批次/),
|
||
).toBeVisible();
|
||
await expect(
|
||
page.getByText("SUPER · Selection: turnover < 0.1 · Combo: alpha", {
|
||
exact: true,
|
||
}),
|
||
).toBeVisible();
|
||
await page.getByRole("button", { name: "确认启动回测", exact: true }).click();
|
||
await expect(page.getByText("4 / 4 已保存", { exact: true })).toBeVisible({
|
||
timeout: 25000,
|
||
});
|
||
const result = await (
|
||
await page.request.get(
|
||
`/api/v1/superalpha/experiments/${experiment.id}/results`,
|
||
)
|
||
).json();
|
||
expect(
|
||
result.items.every(
|
||
(i: { persistence_status: string }) => i.persistence_status === "saved",
|
||
),
|
||
).toBe(true);
|
||
const alpha = result.items[0].alpha_id;
|
||
await page.goto(`/#alphas?alpha_id=${alpha}`);
|
||
await expect(
|
||
page.getByRole("button", { name: "Super Alpha 管理", exact: true }),
|
||
).toHaveAttribute("aria-current", "page");
|
||
await expect(page.locator(".alpha-detail")).toContainText(
|
||
"Selection rationale",
|
||
);
|
||
await page.getByRole("tab", { name: "组件证据", exact: true }).click();
|
||
await expect(page.locator(".alpha-detail .super-components")).toContainText(
|
||
"已核实 2 个",
|
||
);
|
||
await page
|
||
.getByRole("button", { name: "复制为研究方案", exact: true })
|
||
.click();
|
||
await expect(page.getByLabel("Selection", { exact: true })).toHaveValue(
|
||
result.items[0].selection,
|
||
);
|
||
await page.goto(`/#superalpha-research?experiment_id=${experiment.id}`);
|
||
await page.getByRole("tab", { name: "回测对照", exact: true }).click();
|
||
await expect(page.getByText("4 个回测项", { exact: true })).toBeVisible();
|
||
const checks = page.locator(
|
||
".super-research .semi-tabs-pane-active tbody input[type=checkbox]",
|
||
);
|
||
await checks.nth(0).focus();
|
||
await page.keyboard.press("Space");
|
||
await checks.nth(1).focus();
|
||
await page.keyboard.press("Space");
|
||
await page.getByRole("button", { name: "对照两项(2)" }).click();
|
||
await expect(page.getByRole("dialog")).toContainText("同池对照");
|
||
await page.keyboard.press("Escape");
|
||
await expect(page.getByRole("dialog")).not.toBeVisible();
|
||
for (const width of [1440, 850, 390]) {
|
||
await page.setViewportSize({ width, height: 950 });
|
||
expect(
|
||
await page.evaluate(
|
||
() => document.documentElement.scrollWidth <= innerWidth,
|
||
),
|
||
).toBe(true);
|
||
await page.screenshot({
|
||
path: `../output/playwright/superalpha-${width}.png`,
|
||
});
|
||
}
|
||
expect(errors).toEqual([]);
|
||
});
|
||
|
||
test("Super management scopes, saved views and cross-page selection", async ({
|
||
page,
|
||
}) => {
|
||
await page.goto("/#superalphas");
|
||
await page.getByLabel("密码", { exact: true }).fill("browser-test-password");
|
||
await page.getByRole("button", { name: "进入工作空间" }).click();
|
||
await expect(
|
||
page.getByRole("tab", { name: "待提交", exact: true }),
|
||
).toBeVisible();
|
||
await page.request.put("/api/v1/account/credentials", {
|
||
headers,
|
||
data: { email: "test@example.com", password: "synthetic-password" },
|
||
});
|
||
await page.request.post("/api/v1/account/connect", { headers });
|
||
await expect
|
||
.poll(
|
||
async () =>
|
||
(await (await page.request.get("/api/v1/account")).json())
|
||
.connection_status,
|
||
)
|
||
.toBe("connected");
|
||
const job = await (
|
||
await page.request.post("/api/v1/sync-jobs", {
|
||
headers,
|
||
data: {
|
||
kind: "daily_sync",
|
||
submission: "UNSUBMITTED",
|
||
date_from: "2025-01-01",
|
||
date_to: "2025-01-01",
|
||
},
|
||
})
|
||
).json();
|
||
await expect
|
||
.poll(
|
||
async () =>
|
||
(await (await page.request.get(`/api/v1/sync-jobs/${job.id}`)).json())
|
||
.status,
|
||
)
|
||
.toBe("completed");
|
||
await page.reload();
|
||
const panel = page.locator(".alpha-page-view:not([hidden])");
|
||
await expect(panel.locator(".alpha-link").first()).toBeVisible();
|
||
const data = await (
|
||
await page.request.get(
|
||
"/api/v1/alphas?management_scope=super&submission=UNSUBMITTED",
|
||
)
|
||
).json();
|
||
expect(
|
||
data.items.every((a: { alpha_type: string }) => a.alpha_type === "SUPER"),
|
||
).toBe(true);
|
||
await panel.locator("tbody .semi-checkbox").first().click();
|
||
await panel.locator(".semi-page-item").filter({ hasText: /^2$/ }).click();
|
||
await expect(panel.getByText("已选择 1 条", { exact: false })).toBeVisible();
|
||
await panel.getByRole("button", { name: "保存为新视图" }).click();
|
||
await page.getByLabel("视图名称").fill("SUPER 隔离视图");
|
||
await page.getByRole("button", { name: "保存视图", exact: true }).click();
|
||
await expect(
|
||
panel.getByRole("tab", { name: /SUPER 隔离视图/ }),
|
||
).toBeVisible();
|
||
await page.getByRole("button", { name: "Alpha 管理", exact: true }).click();
|
||
await expect(
|
||
page.getByRole("tab", { name: /SUPER 隔离视图/ }),
|
||
).not.toBeVisible();
|
||
const regular = await (
|
||
await page.request.get("/api/v1/alphas?management_scope=non_super")
|
||
).json();
|
||
expect(
|
||
regular.items.every(
|
||
(a: { alpha_type: string }) => a.alpha_type !== "SUPER",
|
||
),
|
||
).toBe(true);
|
||
});
|