后端: - RegistrationSettingRequest 协议字段改为可选指针,注册开关单独保存不再覆盖协议正文 - 新增 RegistrationAgreement / AgreementTitleForMessage:标题未配置时跟随品牌名生成,读取失败返回空标题而非猜一个不存在的协议名 - PublicAuthSettings 下发 agreementTitle / agreementContent,首用户分支同样携带 - 新增 registration_agreement_test.go 覆盖品牌名兜底、存储合并与失败降级 前端: - 注册页协议标题与条款改为消费后台配置;读取失败时隐藏协议入口并支持重新读取 - 验证码获取按钮内联到输入框右侧,联系方式为空即禁用;sms_email 双通道合并为单输入框 - 协议弹窗重排:条目标题独立成行加重、空态虚线提示、底部补充同意说明;深浅主题适配 - 协议勾选行改为状态化区域,复选框适配 AntD 6 结构(方框在 .ant-checkbox 本体,修正深色主题白底白勾) - 后台「服务协议名称与条款」区块补齐表单内边距并对齐区块头/页脚,协议名称限宽 文档:http-api.mdx 更新协议字段语义与失败降级说明;pending-test.mdx 增加手工验证清单
74 lines
4.1 KiB
TypeScript
74 lines
4.1 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
||
import { readFileSync } from "node:fs";
|
||
|
||
import { DEFAULT_CLASSIC_SKIN, duplicateSkinDefinition, skinCSSVariables } from "../src/lib/skin-themes";
|
||
|
||
const source = (path: string) => readFileSync(new URL(`../src/${path}`, import.meta.url), "utf8");
|
||
|
||
describe("authentication follows the application theme", () => {
|
||
test("classic login surfaces have distinct light and dark palettes", () => {
|
||
// globals.css 在不同平台上可能是 LF 或 CRLF;先归一化再分段,
|
||
// 否则按字面换行查找 .dark 段会返回 -1,把断言变成永远失败。
|
||
const css = source("styles/globals.css").replace(/\r\n/g, "\n");
|
||
const dark = css.slice(css.indexOf(".dark {\n --background:"));
|
||
for (const [mode, background, panel, card] of [
|
||
["light", "#ffffff", "#f7f7f7", "#ffffff"],
|
||
["dark", "#08090c", "#0b0c10", "#121318"],
|
||
] as const) {
|
||
const variables = skinCSSVariables(DEFAULT_CLASSIC_SKIN, mode);
|
||
const modeCSS = mode === "dark" ? dark : css.slice(0, css.indexOf(".auth-scene {"));
|
||
expect(variables["--auth-page-bg"]).toBe(background);
|
||
expect(variables["--auth-panel-bg"]).toBe(panel);
|
||
expect(variables["--auth-card-bg"]).toBe(card);
|
||
for (const key of ["--auth-page-bg", "--auth-panel-bg", "--auth-card-bg", "--auth-accent", "--auth-muted"]) {
|
||
expect(modeCSS).toContain(`${key}: ${variables[key]};`);
|
||
}
|
||
}
|
||
});
|
||
|
||
test("auth inherits the global Ant Design provider instead of forcing dark controls", () => {
|
||
const scene = source("pages/auth/auth-scene.tsx");
|
||
expect(scene).not.toContain("ConfigProvider");
|
||
expect(scene).not.toContain("getAntThemeConfig");
|
||
expect(scene).not.toContain("auth-card-dark");
|
||
expect(scene.match(/<main className="([^"]+)"/)?.[1]).not.toContain("text-white");
|
||
expect(scene).toContain("auth-scene-hero");
|
||
expect(scene).toContain("<BrandLogo theme={theme}");
|
||
expect(source("components/layout/app-providers.tsx")).toContain("getAntThemeConfig(dark, appearance.activeSkin)");
|
||
});
|
||
|
||
test("form labels, links and notices do not assume white text", () => {
|
||
for (const page of ["login", "register", "forgot-password"]) {
|
||
const form = source(`pages/auth/${page}.tsx`);
|
||
expect(form).not.toMatch(/(?:text|border|bg)-white/);
|
||
expect(form).not.toMatch(/text-(?:blue|amber)-[123]00/);
|
||
expect(form).toContain("auth-scene-label");
|
||
expect(form).toContain("auth-scene-icon");
|
||
}
|
||
expect(source("pages/auth/register.tsx")).toContain("auth-scene-notice");
|
||
expect(source("pages/auth/forgot-password.tsx")).toContain("auth-scene-notice");
|
||
});
|
||
|
||
test("focus and autofill keep theme-aware foregrounds and visible focus", () => {
|
||
const css = source("styles/globals.css");
|
||
expect(css).not.toContain(".auth-card-dark");
|
||
expect(css).toContain(".auth-scene-card input:-webkit-autofill");
|
||
expect(css).toContain("-webkit-text-fill-color: var(--foreground) !important");
|
||
expect(css).toContain("box-shadow: 0 0 0 1000px var(--auth-card-bg) inset !important");
|
||
expect(css).toContain(".auth-scene-link:focus-visible");
|
||
expect(css).toContain("box-shadow: 0 0 0 var(--focus-ring-width) color-mix(in srgb, var(--ring) 18%, transparent)");
|
||
});
|
||
|
||
test("custom auth palettes are preserved per mode", () => {
|
||
const skin = duplicateSkinDefinition(DEFAULT_CLASSIC_SKIN, ["classic"]);
|
||
skin.tokens.light.authPanel = "#f6ebe3";
|
||
skin.tokens.light.authCard = "#fffdf9";
|
||
skin.tokens.dark.authPanel = "#21120e";
|
||
skin.tokens.dark.authCard = "#361f17";
|
||
expect(skinCSSVariables(skin, "light")["--auth-panel-bg"]).toBe("#f6ebe3");
|
||
expect(skinCSSVariables(skin, "light")["--auth-card-bg"]).toBe("#fffdf9");
|
||
expect(skinCSSVariables(skin, "dark")["--auth-panel-bg"]).toBe("#21120e");
|
||
expect(skinCSSVariables(skin, "dark")["--auth-card-bg"]).toBe("#361f17");
|
||
});
|
||
});
|