Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
49 lines
2.5 KiB
TypeScript
49 lines
2.5 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
import { toast } from "sonner";
|
|
|
|
import { NOTICE_DURATION_MS, TOASTER_LABEL, liftToastsAboveModal, notifyError, notifyInfo, notifySuccess } from "../src/lib/notify.ts";
|
|
|
|
// 提示与报错改 toast (2026-09-30): one helper, top centre, 3s / 6s + close.
|
|
const read = (path: string) => readFileSync(new URL(path, import.meta.url), "utf8");
|
|
|
|
test("success and info leave after 3s; errors stay 6s with a close button; blank messages raise nothing", () => {
|
|
const calls: Array<[string, string, Record<string, unknown>]> = [];
|
|
const before = { success: toast.success, info: toast.info, error: toast.error };
|
|
toast.success = (message, options) => { calls.push(["success", String(message), options as Record<string, unknown>]); return 1; };
|
|
toast.info = (message, options) => { calls.push(["info", String(message), options as Record<string, unknown>]); return 1; };
|
|
toast.error = (message, options) => { calls.push(["error", String(message), options as Record<string, unknown>]); return 1; };
|
|
try {
|
|
notifySuccess("已保存。");
|
|
notifyInfo("请输入验证器动态码", { id: "auth-notice" });
|
|
notifyError("保存失败,请重试");
|
|
notifyError(" ");
|
|
assert.deepEqual(calls, [
|
|
["success", "已保存。", { duration: 3_000 }],
|
|
["info", "请输入验证器动态码", { duration: 3_000, id: "auth-notice" }],
|
|
["error", "保存失败,请重试", { duration: 6_000, closeButton: true }],
|
|
]);
|
|
assert.deepEqual(NOTICE_DURATION_MS, { success: 3_000, info: 3_000, error: 6_000 });
|
|
} finally {
|
|
Object.assign(toast, before);
|
|
}
|
|
});
|
|
|
|
test("the toaster sits top centre with the notch offset, and lifting is a no-op without a DOM", () => {
|
|
const toaster = read("../src/components/ui/sonner.tsx");
|
|
assert.match(toaster, /position="top-center"/);
|
|
assert.match(toaster, /containerAriaLabel=\{TOASTER_LABEL\}/);
|
|
assert.match(toaster, /mobileOffset=\{\{ top: "calc\(env\(safe-area-inset-top, 0px\) \+ 12px\)", left: "16px", right: "16px" \}\}/);
|
|
assert.equal(TOASTER_LABEL, "页面提示");
|
|
assert.doesNotThrow(() => liftToastsAboveModal());
|
|
const layout = read("../src/app/layout.tsx");
|
|
assert.match(layout, /<Toaster \/>/);
|
|
});
|
|
|
|
test("no product surface keeps a green success bar", () => {
|
|
const styles = read("../src/app/globals.css");
|
|
assert.doesNotMatch(styles, /\.form-success/);
|
|
assert.doesNotMatch(styles, /\.form-error[^{]*\{[^}]*border-left/);
|
|
});
|