Files
Jyotisha/frontend/tests/rectification-readopt-card-20261002.test.ts
T
Jesse_ChenandClaude Opus 5.5 6987875b84
Independent Staging Quality Gate / validate (push) Successful in 14m56s
Independent Staging Quality Gate / publish (push) Successful in 3m23s
feat(rectification): post-adopt verdict says whether the adopted time still fits and offers 改用 HH:MM; renumber BUG-1170→1172 (BUG-1173)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
2026-10-02 07:40:30 +08:00

49 lines
2.8 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { RectificationSegmentDelivery } from "../src/components/rectification-segment-delivery.tsx";
import { buildInferenceState } from "../src/lib/rectification-agentic/core/build-state.ts";
import { buildRangeDelivery } from "../src/lib/rectification-agentic/v9/divergence-panel.ts";
// BUG-1173 (product 10-01 option A): after adoption the card stays 「已采用」 while the adopted
// minute fits the verdict, and offers 「改用 HH:MM」 only when the verdict moved off it.
// Fictional complete scan; D9 changes ascendant at offset 10.
const minutes = Array.from({ length: 21 }, (_, offset) => ({ offset, date: "2000-06-14",
time: `09:${String(offset).padStart(2, "0")}`, signs: { D1: 1, D9: offset < 10 ? 2 : 3 } }));
const state = buildInferenceState({ range_start: "09:00", range_end: "09:20",
candidates: [{ id: "09:15", time: "09:15", relative_support: 70, raw_score: 30, cluster_times: ["09:15"] },
{ id: "09:03", time: "09:03", relative_support: 30, raw_score: 5, cluster_times: ["09:03"] }],
events: [], probes: [], segment_targets: ["D1", "D9"], segment_minutes: minutes, segment_scan_complete: true });
const publicCandidates = [{ candidateId: "cand-1", time: "09:15" }, { candidateId: "cand-2", time: "09:03" }] as never;
function render(acceptedTime: string) {
const delivery = buildRangeDelivery({ inference: state, publicCandidates, acceptedTime });
const adoption = state.segment_summary!.adoption_minute!;
const html = renderToStaticMarkup(createElement(RectificationSegmentDelivery, {
summary: state.segment_summary!, delivery, rangeLabel: null, resultId: "result-1",
selection: { resultId: "result-1", candidateId: delivery.representative_candidate_id ?? "cand-1", date: "2000-06-14", time: acceptedTime, contract: "segment-v1" },
busy: false, accepting: false, onAccept: () => {}, markdown: null,
}));
return { delivery, adoption, html };
}
test("adopted minute left the verdict: 「改用 HH:MM」 with the current minute named", () => {
const { delivery, adoption, html } = render("09:03");
assert.ok(state.segment_summary?.adoption_minute, "fixture yields a server adoption minute");
assert.notEqual(adoption.time, "09:03");
assert.equal(delivery.readopt_minute, adoption.time);
assert.match(html, new RegExp(`改用 ${adoption.time}`));
assert.match(html, /现在按 09:03 排盘/);
assert.doesNotMatch(html, /aria-pressed="true"/);
});
test("adopted minute still fits after the server minute moved: stays 「已采用」", () => {
const { delivery, adoption, html } = render("09:12");
assert.notEqual(adoption.time, "09:12");
assert.equal(delivery.readopt_minute, null);
assert.match(html, /已采用/);
assert.doesNotMatch(html, /改用 09:/);
});