feat(HEL-238): 按确认样图重做手机端系统管理,并加入部署基线门禁
Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
co-authored by
Cursor
multica-agent
parent
2a2d205a38
commit
541fb48c1c
@@ -138,6 +138,11 @@ async function mockMobileApi(page, options = {}) {
|
||||
payload = { items: [] };
|
||||
} else if (path === "/api/search") {
|
||||
payload = { groups: { stocks: [{ id: "002141", code: "002141", name: "贤丰控股", type: "stock", industry: "电子元件" }], sectors: [], themes: [], indices: [] } };
|
||||
} else if (path === "/api/auth/accounts") {
|
||||
payload = {
|
||||
accounts: [{ user_id: auth.user.id, username: auth.user.username, role: auth.user.role, last_used_at: "2026-07-22T09:12:00+08:00" }],
|
||||
current_user_id: auth.user.id,
|
||||
};
|
||||
} else if (path === "/api/account/status") {
|
||||
payload = {
|
||||
birth_profile_configured: true,
|
||||
@@ -284,12 +289,16 @@ test("mobile login renders before authentication", async ({ page }) => {
|
||||
test("four hub pages render their icon grids", async ({ page }) => {
|
||||
await mockMobileApi(page);
|
||||
await openMobile(page);
|
||||
for (const hub of ["market", "tools", "review", "system"]) {
|
||||
for (const hub of ["market", "tools", "review"]) {
|
||||
await page.evaluate((h) => { window.MobileRouter.navigate("#/hub/" + h); }, hub);
|
||||
await expect(page.locator(".m-hub-grid")).toBeVisible();
|
||||
await expect(page.locator(".m-hub-grid .m-grid-item").first()).toBeVisible();
|
||||
expect(await measureOverflow(page)).toBeLessThanOrEqual(1);
|
||||
}
|
||||
await page.evaluate(() => { window.MobileRouter.navigate("#/hub/system"); });
|
||||
await expect(page.locator("[data-system-page='home']")).toBeVisible();
|
||||
await expect(page.locator(".m-sys-row").first()).toBeVisible();
|
||||
expect(await measureOverflow(page)).toBeLessThanOrEqual(1);
|
||||
});
|
||||
|
||||
for (const theme of ["day", "night"]) {
|
||||
@@ -344,7 +353,7 @@ test("system management pages render real content instead of placeholders", asyn
|
||||
}
|
||||
await navigateToFeature(page, "system/profile");
|
||||
await expect(page.locator("#m-sys-birth-date")).toBeVisible();
|
||||
await expect(page.locator("[data-system-switch]")).toBeVisible();
|
||||
await expect(page.locator("[data-system-save-birth]")).toBeVisible();
|
||||
await navigateToFeature(page, "system/password");
|
||||
await expect(page.locator("#m-sys-password-current")).toBeVisible();
|
||||
await navigateToFeature(page, "system/membership");
|
||||
@@ -355,7 +364,64 @@ test("system management pages render real content instead of placeholders", asyn
|
||||
await expect(page.locator("#m-sys-member-limit")).toBeVisible();
|
||||
});
|
||||
|
||||
test("empty profile save click shows a toast instead of a dead button", async ({ page }) => {
|
||||
test("system home groups entries and keeps admin-only items gated", async ({ page }) => {
|
||||
await mockMobileApi(page);
|
||||
await openMobile(page);
|
||||
await page.evaluate(() => { window.MobileRouter.navigate("#/hub/system"); });
|
||||
await expect(page.locator("[data-system-page='home']")).toBeVisible();
|
||||
await expect(page.locator("#m-view")).toContainText("账号");
|
||||
await expect(page.locator("#m-view")).toContainText("偏好");
|
||||
await expect(page.locator("#m-view")).toContainText("管理员专区");
|
||||
await expect(page.locator("[data-theme-toggle]")).toBeVisible();
|
||||
await expect(page.locator("[data-system-switch]")).toBeVisible();
|
||||
expect(await measureOverflow(page)).toBeLessThanOrEqual(1);
|
||||
});
|
||||
|
||||
test("system settings tabs, model editor, delete confirm and theme toggle work", async ({ page }) => {
|
||||
await mockMobileApi(page);
|
||||
await openMobile(page);
|
||||
await navigateToFeature(page, "system/admin");
|
||||
await expect(page.locator("[data-system-admin-panel='market']")).toBeVisible();
|
||||
await page.locator("[data-system-admin-tab='models']").click();
|
||||
await expect(page.locator("[data-system-admin-panel='models']")).toBeVisible();
|
||||
await page.locator("[data-system-edit-model]").first().click();
|
||||
await expect(page.locator(".m-sheet-root.is-open")).toBeVisible();
|
||||
await expect(page.locator(".m-sheet-head h2")).toHaveText("编辑模型");
|
||||
await page.locator("[data-sheet-close]").click();
|
||||
await page.locator("[data-system-admin-tab='market']").click();
|
||||
await expect(page.locator("#m-sys-token")).toBeVisible();
|
||||
|
||||
await navigateToFeature(page, "system/profile");
|
||||
await page.locator("[data-system-delete-birth]").click();
|
||||
await expect(page.locator(".m-dialog")).toBeVisible();
|
||||
await expect(page.locator(".m-dialog")).toContainText("删除命理资料");
|
||||
await page.locator("[data-sheet-close]").click();
|
||||
|
||||
await page.evaluate(() => { window.MobileRouter.navigate("#/hub/system"); });
|
||||
await expect(page.locator("[data-theme-toggle]")).toBeVisible();
|
||||
const before = await page.locator("#m-app").getAttribute("data-theme");
|
||||
await page.locator("[data-theme-toggle]").click();
|
||||
await expect.poll(async () => page.locator("#m-app").getAttribute("data-theme")).not.toBe(before);
|
||||
|
||||
await navigateToFeature(page, "system/members");
|
||||
await page.locator("[data-system-open-member]").click();
|
||||
await expect(page.locator(".m-sheet-root.is-open")).toBeVisible();
|
||||
await expect(page.locator(".m-sheet-head h2")).toContainText("管理会员");
|
||||
});
|
||||
|
||||
test("password mismatch shows inline error instead of a silent submit", async ({ page }) => {
|
||||
await mockMobileApi(page);
|
||||
await openMobile(page);
|
||||
await navigateToFeature(page, "system/password");
|
||||
await page.locator("#m-sys-password-current").fill("OldPass12");
|
||||
await page.locator("#m-sys-password-new").fill("NewPass123");
|
||||
await page.locator("#m-sys-password-confirm").fill("OtherPass123");
|
||||
await page.locator("[data-system-save-password]").click();
|
||||
await expect(page.locator("[data-field-error='confirm']")).toBeVisible();
|
||||
await expect(page.locator("[data-field-error='confirm']")).toContainText("两次输入的密码不一致");
|
||||
});
|
||||
|
||||
test("empty birth profile save shows a validation toast", async ({ page }) => {
|
||||
await mockMobileApi(page);
|
||||
await openMobile(page);
|
||||
await navigateToFeature(page, "system/profile");
|
||||
@@ -371,9 +437,10 @@ test("non-admin cannot open system admin pages as placeholders", async ({ page }
|
||||
await mockMobileApi(page, { auth: authSession("user", true) });
|
||||
await openMobile(page);
|
||||
await page.evaluate(() => { window.MobileRouter.navigate("#/hub/system"); });
|
||||
await expect(page.locator(".m-hub-grid")).toBeVisible();
|
||||
await expect(page.locator('.m-grid-item[data-route="#/feature/system/admin"]')).toHaveCount(0);
|
||||
await expect(page.locator('.m-grid-item[data-route="#/feature/system/members"]')).toHaveCount(0);
|
||||
await expect(page.locator("[data-system-page='home']")).toBeVisible();
|
||||
await expect(page.locator('[data-route="#/feature/system/admin"]')).toHaveCount(0);
|
||||
await expect(page.locator('[data-route="#/feature/system/members"]')).toHaveCount(0);
|
||||
await expect(page.locator("[data-system-switch]")).toBeVisible();
|
||||
await navigateToFeature(page, "system/admin");
|
||||
await expect(page.locator("#m-view")).not.toContainText(PLACEHOLDER_COPY);
|
||||
await expect(page.locator("[data-system-page='forbidden']")).toBeVisible();
|
||||
|
||||
Reference in New Issue
Block a user