Homepage no longer waits on /api/onboarding for six starter questions. Natal answers show the spoken layer first; the Level 2 skeleton sits in a collapsed 完整分析 block. Wide tables scroll sideways on a phone. Form inputs are 16px so iOS does not zoom on focus.
73 lines
2.8 KiB
TypeScript
73 lines
2.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
|
|
const css = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8");
|
|
|
|
function ruleFor(selector: string): string {
|
|
const start = css.indexOf(selector);
|
|
assert.notEqual(start, -1, `missing ${selector}`);
|
|
const open = css.indexOf("{", start);
|
|
const close = css.indexOf("}", open);
|
|
return css.slice(open, close + 1);
|
|
}
|
|
|
|
test("three-column markdown tables still card-stack on a phone", () => {
|
|
assert.match(
|
|
css,
|
|
/@media \(max-width: 767px\) \{[\s\S]*\.markdown-table table:has\(thead th:nth-child\(3\):last-child\) tbody tr/,
|
|
);
|
|
assert.match(
|
|
css,
|
|
/\.markdown-table table:has\(thead th:nth-child\(3\):last-child\) tbody td:nth-child\(3\)/,
|
|
);
|
|
});
|
|
|
|
test("four-or-more-column chat tables become horizontally scrollable on a phone", () => {
|
|
const mobile = css.slice(css.indexOf("@media (max-width: 767px)"));
|
|
assert.match(
|
|
mobile,
|
|
/\.conversation \.markdown-table table:not\(:has\(thead th:nth-child\(3\):last-child\)\) \{[\s\S]*width:\s*auto;[\s\S]*min-width:\s*max-content;/,
|
|
);
|
|
assert.match(
|
|
mobile,
|
|
/\.conversation \.markdown-table:has\(table:not\(:has\(thead th:nth-child\(3\):last-child\)\)\) \{[\s\S]*overscroll-behavior-x:\s*contain;/,
|
|
);
|
|
});
|
|
|
|
test("wide-table scroll hint uses canvas tokens so dark theme stays in family", () => {
|
|
const mobile = css.slice(css.indexOf("@media (max-width: 767px)"));
|
|
const hint = mobile.slice(
|
|
mobile.indexOf(".conversation .markdown-table:has(table:not(:has(thead th:nth-child(3):last-child)))"),
|
|
);
|
|
const block = hint.slice(0, hint.indexOf(".conversation .markdown-table table:not"));
|
|
assert.match(block, /var\(--color-canvas\)/);
|
|
assert.doesNotMatch(block, /#[0-9a-fA-F]{3,8}/);
|
|
});
|
|
|
|
test("the conversation pane itself still forbids page-level sideways scrolling", () => {
|
|
assert.match(css, /\.conversation \{[^}]*overflow-x:\s*hidden;/);
|
|
});
|
|
|
|
test("global text inputs are 16px so iOS does not zoom on focus", () => {
|
|
const inputRule = ruleFor(
|
|
"input:not([type=\"radio\"]):not([type=\"checkbox\"]):not([class^=\"ant-\"])",
|
|
);
|
|
assert.match(inputRule, /font-size:\s*var\(--type-body-md\)/);
|
|
assert.doesNotMatch(inputRule, /--type-body-sm/);
|
|
});
|
|
|
|
test("otp and composer keep their existing safe sizes", () => {
|
|
assert.match(ruleFor(".otp-input"), /font-size:\s*20px/);
|
|
assert.match(ruleFor(".composer textarea {"), /font-size:\s*var\(--type-body-md\)/);
|
|
});
|
|
|
|
test("personal-report tables are not retargeted by the chat wide-table rule", () => {
|
|
const mobile = css.slice(css.indexOf("@media (max-width: 767px)"));
|
|
const wide = mobile.match(
|
|
/\.conversation \.markdown-table table:not\(:has\(thead th:nth-child\(3\):last-child\)\) \{[^}]+\}/,
|
|
);
|
|
assert.ok(wide);
|
|
assert.doesNotMatch(wide[0], /personal-report/);
|
|
});
|