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:/); });