Files
Jyotisha/frontend/tests/starter-entry-soften.test.ts
T
Jesse_ChenandClaude Opus 5.5 6ad0bea320 feat(rectification): start from an offer card in the consultation, come back to it (BUG-1247~1251)
TASK-rectification-in-chat-step1-20261006, direct execution.

- The homepage 生时校正 pill and the text trigger (isRectificationHandoffQuestion)
  are gone. The consult agent decides (RECTIFICATION_OFFER_RULE, one
  definition) and calls offer-birth-time-rectification; the server decides
  whether a card may show (self, product on, no case in progress,
  feature_pricing price). The offer is stored with the answer and travels on
  run.completed; the card hangs under that answer.
- Opening from the card binds the offer to the case in the consultation's own
  messages (no table change); GET/POST /api/rectification/cases/[caseId]/source
  find the source and go back: one divider (time changed or not), earlier
  answers captioned 按校正前的时间, and a 按新时间重新看 button that sends only
  when clicked. Auto-return after the post-adopt check or a terminal case, only
  for work done in this view.
- Model history skips the divider and notes answers written with the old time.

Full suite 4987 / fail 24, identical to 6ec8efd5 (4973 / 24), no test name
lost; tsc 0; lint 0 errors; build keeps / Static, first-load gzip +0.20%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
2026-10-07 12:58:58 +08:00

44 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
const starterHome = readFileSync(new URL("../src/components/starter-home.tsx", import.meta.url), "utf8");
const css = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8");
const design = readFileSync(new URL("../DESIGN.md", import.meta.url), "utf8");
function starterEntryBlock(): string {
const start = css.indexOf(".starter-entry {");
const end = css.indexOf(".starter-entry > svg");
assert.ok(start >= 0 && end > start);
return css.slice(start, end);
}
test("starter entries stay native buttons with a 36px pill and a 44px hit area", () => {
assert.match(starterHome, /<button[\s\S]*className="starter-entry"/);
// 原值: 2 新值: 1(生时校正 pill 删除) 原因: BUG-1247(TASK-rectification-in-chat-step1-20261006 P3/C1):首页生时校正按钮与文字口令删除,校正只从对话里的提议卡进入
assert.equal(starterHome.match(/className="starter-entry"/g)?.length, 1);
assert.doesNotMatch(starterHome, /starter-hero|product-entrypoint|daily-starlanguage-card|birth-rectification-card/);
assert.doesNotMatch(starterHome, /正在加载|InlineSpinner|animate-spin/);
const block = starterEntryBlock();
assert.match(block, /min-height:\s*36px/);
assert.match(block, /--starter-entry-border:\s*color-mix\(in srgb, var\(--color-border\) 62%, transparent\)/);
assert.match(block, /border:\s*1px solid var\(--starter-entry-border\)/);
assert.doesNotMatch(block, /border:\s*1px solid var\(--color-border-strong\)/);
assert.match(css, /\.starter-entry::after\s*\{[^}]*inset:\s*-4px/);
});
test("starter entry hover stays softer than the action color and focus is a 3px ring", () => {
const hover = css.slice(css.indexOf(".starter-entry:not(:disabled):hover"), css.indexOf(".starter-entry:focus-visible"));
assert.match(hover, /color-mix\(in srgb, var\(--color-border-strong\) 45%, var\(--color-border\)\)/);
assert.doesNotMatch(hover, /border-color:\s*var\(--color-action\)/);
assert.match(css, /\.starter-entry:focus-visible\s*\{[^}]*outline:\s*3px solid color-mix\(in srgb, var\(--color-focus\) 80%, transparent\)/);
assert.match(css, /\.starter-entry\[data-opening="true"\]\s*\{\s*cursor:\s*progress/);
// 原值:入口行 max-width: 100% 位于 max-width: 375px 媒体块。
// 新值:同一防溢出规则位于既有 max-width: 480px 媒体块。
// 原因:BUG-1012 按 BUG-697 收敛断点,不扩白名单;按钮尺寸、焦点与防溢出要求不变。
assert.match(css, /@media \(max-width:\s*480px\)\s*\{[^}]*\.starter-entry-row\s*\{\s*max-width:\s*100%/);
assert.match(css, /@media \(prefers-reduced-motion:\s*reduce\)[\s\S]*transition-duration:\s*\.01ms !important/);
assert.match(design, /--starter-entry-border/);
assert.match(design, /inset: -4px/);
});