feat: expand and secure mentor library
This commit is contained in:
+102
-1
@@ -47,6 +47,65 @@ function session(role = "admin", subscribed = true) {
|
||||
};
|
||||
}
|
||||
|
||||
function mentorDirectory(role = "admin") {
|
||||
const mentors = [
|
||||
{
|
||||
id: "source-a",
|
||||
name: "原帖老师",
|
||||
description: "依据长期实盘原帖提炼",
|
||||
tagline: "先看周期,再看机会。",
|
||||
focus: ["情绪周期", "仓位纪律"],
|
||||
evidence: { grade: "A", label: "实盘原帖", note: "长期原始实盘记录" },
|
||||
quality: { score: 6, total: 6, status: "pass" },
|
||||
private: false,
|
||||
},
|
||||
{
|
||||
id: "source-b",
|
||||
name: "多源老师",
|
||||
description: "依据公开访谈与多源资料整理",
|
||||
tagline: "确认之后再行动。",
|
||||
focus: ["主线确认", "风险管理"],
|
||||
evidence: { grade: "B", label: "多源整理", note: "公开访谈与多源材料" },
|
||||
quality: { score: 6, total: 6, status: "pass" },
|
||||
private: false,
|
||||
},
|
||||
{
|
||||
id: "source-c",
|
||||
name: "推演老师",
|
||||
description: "公开语录较少,以行为推演为主",
|
||||
tagline: "只讨论可验证的行为。",
|
||||
focus: ["行为推演", "诚实边界"],
|
||||
evidence: { grade: "C", label: "行为推演", note: "公开语录较少" },
|
||||
quality: { score: 5, total: 6, status: "conditional" },
|
||||
private: false,
|
||||
},
|
||||
];
|
||||
for (let index = 1; index <= 18; index += 1) {
|
||||
const grade = ["A", "B", "C"][(index - 1) % 3];
|
||||
mentors.push({
|
||||
id: `extra-${index}`,
|
||||
name: `扩展模型${String(index).padStart(2, "0")}`,
|
||||
description: `用于验证完整目录密度的${grade}级思维模型`,
|
||||
tagline: "保持证据边界。",
|
||||
focus: ["市场结构", "条件预案"],
|
||||
evidence: { grade, label: { A: "原始语料", B: "多源整理", C: "行为材料" }[grade], note: `${grade}级测试素材` },
|
||||
quality: { score: 6, total: 6, status: "pass" },
|
||||
private: false,
|
||||
});
|
||||
}
|
||||
if (role === "admin") mentors.unshift({
|
||||
id: "private-owner",
|
||||
name: "私有老师",
|
||||
description: "依据个人复盘记录提炼",
|
||||
tagline: "只对自己开放。",
|
||||
focus: ["个人复盘", "交易纪律"],
|
||||
evidence: { grade: "A", label: "私有原始语料", note: "仅限管理员本人使用" },
|
||||
quality: { score: null, total: null, status: "private" },
|
||||
private: true,
|
||||
});
|
||||
return mentors;
|
||||
}
|
||||
|
||||
async function mockApplication(page, authSession = session()) {
|
||||
await page.route("**/api/**", async (route) => {
|
||||
const url = new URL(route.request().url());
|
||||
@@ -157,7 +216,9 @@ async function mockApplication(page, authSession = session()) {
|
||||
created_at: "2026-07-23T09:12:00+08:00",
|
||||
}],
|
||||
};
|
||||
} else if (url.pathname === "/api/mentors/setup") payload = { trade_date: "20260722", mentors: [] };
|
||||
} else if (url.pathname === "/api/mentors/setup") {
|
||||
payload = { trade_date: "20260722", mentors: mentorDirectory(authSession.user.role) };
|
||||
}
|
||||
else if (url.pathname === "/api/heaven/setup") {
|
||||
await route.fulfill({ status: 503, contentType: "application/json", body: JSON.stringify({ error: "测试环境不加载问天数据" }) });
|
||||
return;
|
||||
@@ -430,3 +491,43 @@ test("heaven workspace controls fit a narrow viewport", async ({ page }) => {
|
||||
expect(heartControls.x + heartControls.width).toBeLessThanOrEqual(375);
|
||||
expect(await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth)).toBeLessThanOrEqual(1);
|
||||
});
|
||||
|
||||
test("mentor directory exposes evidence filters and private owner metadata", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1440, height: 900 });
|
||||
await mockApplication(page, session("admin", true));
|
||||
await page.goto("/index.html");
|
||||
await page.locator('[data-view="mentorView"]').first().click();
|
||||
|
||||
await expect(page.locator("#mentorList .mentor-option")).toHaveCount(22);
|
||||
await expect(page.locator('#mentorList [data-mentor-id="private-owner"] .mentor-badge.private')).toContainText("仅自己");
|
||||
await expect(page.locator('#mentorList [data-mentor-id="source-a"] .mentor-badge.grade-a')).toHaveText("A");
|
||||
await expect(page.locator('#mentorList [data-mentor-id="source-c"] .mentor-badge.quality')).toHaveText("5/6");
|
||||
|
||||
await page.locator("#mentorSearchInput").fill("行为推演");
|
||||
await expect(page.locator("#mentorList .mentor-option")).toHaveCount(1);
|
||||
await expect(page.locator("#mentorCount")).toHaveText("1 / 22 位");
|
||||
await page.locator("#mentorSearchInput").fill("");
|
||||
await page.locator('[data-mentor-grade="B"]').click();
|
||||
await expect(page.locator("#mentorList .mentor-option")).toHaveCount(7);
|
||||
await page.locator('#mentorList [data-mentor-id="source-b"]').click();
|
||||
await expect(page.locator("#activeMentorName")).toHaveText("多源老师");
|
||||
await expect(page.locator("#activeMentorBadges")).toContainText("B · 多源整理");
|
||||
await expect(page.locator("#activeMentorEvidence")).toHaveText("公开访谈与多源材料");
|
||||
});
|
||||
|
||||
test("mobile mentor directory opens as a searchable selector and hides private mentors", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 375, height: 812 });
|
||||
await mockApplication(page, session("user", true));
|
||||
await page.goto("/index.html");
|
||||
await page.locator('[data-view="mentorView"]').first().click();
|
||||
|
||||
await expect(page.locator("#mentorDirectoryToggle")).toBeVisible();
|
||||
await page.locator("#mentorDirectoryToggle").click();
|
||||
await expect(page.locator("#mentorView .mentor-sidebar")).toHaveClass(/is-open/);
|
||||
await expect(page.locator("#mentorList .mentor-option")).toHaveCount(21);
|
||||
await expect(page.locator('#mentorList [data-mentor-id="private-owner"]')).toHaveCount(0);
|
||||
await page.locator('#mentorList [data-mentor-id="source-c"]').click();
|
||||
await expect(page.locator("#mentorView .mentor-sidebar")).not.toHaveClass(/is-open/);
|
||||
await expect(page.locator("#mobileActiveMentorName")).toHaveText("推演老师");
|
||||
expect(await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth)).toBeLessThanOrEqual(1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user