Files
Jyotisha/frontend/tests/rectification-delivery-ui-simplify-20260908.test.ts
T
Jesse_ChenandCursor 7e3b6cdc7a
Independent Staging Quality Gate / validate (push) Successful in 25m9s
Independent Staging Quality Gate / publish (push) Successful in 37m19s
fix(rectification): simplify delivery card and guard double turns (BUG-595, BUG-596)
Make the range card row-select, drop the composer 先这样 control and adopt status bar, keep delivery copy to three sentences with a folded verification report, and skip a second no-message agent run after a terminal delivery turn.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-08 19:56:48 +08:00

99 lines
4.5 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";
import { createElement } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import {
deliveryTurnNarration,
postAdoptVerifyDoneCopy,
RECTIFICATION_USER_COPY,
} from "../src/lib/rectification-agentic/user-copy.ts";
import {
alreadyDelivered,
markDeliveryTurn,
resetDeliveryTurnGuardForTests,
} from "../src/lib/rectification-agentic/v9/delivery-turn-guard.ts";
import { RectificationVerificationReport } from "../src/components/rectification-verification-report.tsx";
test("delivery body is three sentences and omits the eight-method report", () => {
const text = deliveryTurnNarration({
credibleRange: ["04:51", "04:59"],
representativeTime: "04:53",
eventCount: 7,
fitPercent: 80,
});
assert.equal(text, "这次给出的范围 04:5104:59,排盘用 04:53。对照了 7 件经历,事件吻合率 80%。这只是代表性候选,不是已确认的唯一出生分钟。");
assert.doesNotMatch(text, /方法1/);
assert.doesNotMatch(text, /Technique Audit/);
});
test("skipping the last reverse-verify keeps the original post-adopt sentence", () => {
assert.equal(
postAdoptVerifyDoneCopy("05:07", true),
RECTIFICATION_USER_COPY.postAdoptVerifyDone,
);
assert.equal(
postAdoptVerifyDoneCopy("05:07", false),
"已采用 05:07,新建对话即按这个时间排盘。",
);
});
test("verification report fold is closed and renders a real table", () => {
const html = renderToStaticMarkup(createElement(RectificationVerificationReport, {
markdown: "| 方法 | 结果 |\n| --- | --- |\n| 1 | 吻合 |",
}));
assert.match(html, /<details/);
assert.doesNotMatch(html, /<details[^>]*\sopen/);
assert.match(html, /查看验证报告/);
assert.match(html, /<table/);
});
test("already_delivered blocks a second no-message run for the same result within 60s", () => {
resetDeliveryTurnGuardForTests();
const caseId = "11111111-1111-4111-8111-111111111111";
const resultId = "22222222-2222-4222-8222-222222222222";
assert.equal(alreadyDelivered({ caseId, resultId, hasUserMessage: false, now: 1_000 }), false);
markDeliveryTurn({ caseId, resultId, now: 1_000 });
assert.equal(alreadyDelivered({ caseId, resultId, hasUserMessage: false, now: 1_500 }), true);
assert.equal(alreadyDelivered({ caseId, resultId, hasUserMessage: true, now: 1_500 }), false);
assert.equal(alreadyDelivered({
caseId,
resultId: "33333333-3333-4333-8333-333333333333",
hasUserMessage: false,
now: 1_500,
}), false);
assert.equal(alreadyDelivered({ caseId, resultId, hasUserMessage: false, now: 62_000 }), false);
resetDeliveryTurnGuardForTests();
});
test("agent-run returns already_delivered before billing and the route skips a second turn", () => {
const agentRun = readFileSync(new URL("../src/lib/rectification-agentic/v9/agent-run.ts", import.meta.url), "utf8");
const route = readFileSync(new URL("../src/app/api/rectification/agent/route.ts", import.meta.url), "utf8");
const exit = readFileSync(new URL("../src/lib/rectification-agentic/v9/turn-exit.ts", import.meta.url), "utf8");
const regenerate = readFileSync(
new URL("../src/app/api/rectification/cases/[caseId]/turns/[turnId]/regenerate/route.ts", import.meta.url),
"utf8",
);
const guardStart = agentRun.indexOf("alreadyDelivered({");
const reserve = agentRun.indexOf("const reserve = await billing.reserve()");
assert.ok(guardStart >= 0 && guardStart < reserve);
assert.match(agentRun, /errorCode: "already_delivered"/);
assert.match(route, /result\.errorCode === "already_delivered"/);
assert.match(route, /trigger: "opening"/);
assert.match(exit, /trigger: "finalizeSuccessfulTurnExit"/);
assert.match(regenerate, /trigger: "regenerate"/);
assert.match(route, /logRectificationDeliveryTurn/);
});
test("composer wrap no longer hosts 先这样 or the adopt status bar", () => {
const chat = readFileSync(new URL("../src/components/rectification-agentic-chat.tsx", import.meta.url), "utf8");
const wrap = chat.slice(chat.indexOf("className=\"composer-wrap\""), chat.indexOf("className=\"composer-footer\""));
assert.doesNotMatch(wrap, /CHOICE_STOP_LABEL/);
assert.doesNotMatch(wrap, /rectification-collect-stop/);
assert.doesNotMatch(wrap, /rectification-composer-meta/);
assert.doesNotMatch(wrap, /rectification-adopt-status/);
assert.match(chat, /CHOICE_STOP_LABEL/);
assert.match(chat, /postAdoptVerifyDoneCopy/);
});