summaryrefslogtreecommitdiff
path: root/qa/driver/browser-test.js
diff options
context:
space:
mode:
Diffstat (limited to 'qa/driver/browser-test.js')
-rw-r--r--qa/driver/browser-test.js62
1 files changed, 62 insertions, 0 deletions
diff --git a/qa/driver/browser-test.js b/qa/driver/browser-test.js
index 76fa69b..a52fa03 100644
--- a/qa/driver/browser-test.js
+++ b/qa/driver/browser-test.js
@@ -33,6 +33,7 @@ let lastRebalancePreviewResponse = null;
let lastRebalanceExecuteResponse = null;
let lastRebalanceExecutionsResponse = null;
let lastNavDatesResponse = null;
+let lastNavSeriesResponse = null;
function check(name, ok, detail) {
results.push({ name, ok, detail: detail || "" });
@@ -177,6 +178,11 @@ async function summaryLabelExists(page, label, name) {
lastNavDatesResponse = await r.json();
} catch {}
}
+ if (r.url().includes("/market/nav-series") && r.request().method() === "GET" && r.status() < 400) {
+ try {
+ lastNavSeriesResponse = await r.json();
+ } catch {}
+ }
if (r.status() >= 400 && !/\/api\/instruments\//.test(r.url()) && !/\/api\/market\//.test(r.url()) && !/\/orders/.test(r.url()) && !/\/redemptions/.test(r.url()) && !/\/capital/.test(r.url())) {
consoleErrors.push("resource " + r.status() + ": " + r.url());
}
@@ -225,6 +231,7 @@ async function summaryLabelExists(page, label, name) {
await dividendScenario(page);
await returnsScenario(page);
await navDatesScenario(page);
+ await navSeriesScenario(page);
await plansScenario(page);
await rebalanceScenario(page);
} finally {
@@ -562,6 +569,61 @@ async function navDatesScenario(page) {
await page.screenshot({ path: SHOTS + "/19-nav-dates.png" });
}
+async function navSeriesScenario(page) {
+ // R2: 真实 AKShare 多日净值序列曲线(多日点、不补零;不可用 503 + 空态)。
+ await page.waitForSelector(".returns-panel .returns-nav-series", { timeout: 10000 });
+
+ const token = process.env.QA_TOKEN || "qa-token";
+
+ for (let i = 0; i < 200 && lastNavSeriesResponse === null; i++) {
+ await page.waitForTimeout(100);
+ }
+
+ const series = lastNavSeriesResponse || {};
+ const points = Array.isArray(series.points) ? series.points : [];
+ const positive = points.length > 0 && points.every((point) => Number.parseFloat(point.nav) > 0);
+ const markers = await page.locator(".returns-nav-series .nav-series-marker").count();
+ const declaredPoints = await page.getAttribute(".returns-nav-series", "data-nav-series-points");
+ const emptyExists = (await page.locator(".returns-nav-series-empty").count()) === 1;
+ const emptyText = ((await page.textContent(".returns-nav-series-empty")) || "").trim();
+
+ check(
+ "R2a 序列可用时曲线显示多日净值且不补零",
+ series.code === "000001" &&
+ points.length >= 2 &&
+ positive &&
+ points[0].navDate === "2026-09-21" &&
+ Number.parseInt(declaredPoints, 10) >= 2 &&
+ markers >= 2 &&
+ emptyExists &&
+ emptyText === "暂无真实净值数据",
+ `code=${series.code} points=${JSON.stringify(points).slice(0, 200)} declared=${declaredPoints} markers=${markers}`
+ );
+
+ const failure = await page.evaluate(async (token) => {
+ const response = await fetch("/api/market/nav-series?code=999999", {
+ headers: { Authorization: `Bearer ${token}` },
+ });
+ let body = null;
+ try {
+ body = await response.json();
+ } catch {}
+ return { status: response.status, body };
+ }, token);
+
+ check(
+ "R2b 序列不可用时返回 503 且保留空态",
+ failure.status === 503 &&
+ failure.body &&
+ failure.body.error === "MARKET_DATA_UNAVAILABLE" &&
+ emptyExists &&
+ emptyText === "暂无真实净值数据",
+ `status=${failure.status} body=${JSON.stringify(failure.body).slice(0, 160)}`
+ );
+
+ await page.screenshot({ path: SHOTS + "/20-nav-series.png" });
+}
+
async function postInvestmentPlanViaApi(page, fundId, token) {
return page.evaluate(
async ({ fundId, token }) => {