|
|
import { describe, expect, it } from "vitest";
|
|
|
import {
|
|
|
FLOCK_HOLD_DECISION_MS,
|
|
|
FLOCK_HOLD_MSG,
|
|
|
FLOCK_HOLD_TOTAL_MS,
|
|
|
buildFlockQuoteHoldState,
|
|
|
flockHoldSessionId,
|
|
|
formatFlockHoldRemainingLabel,
|
|
|
isFlockQuoteHoldExpired,
|
|
|
shouldAutoDeclineFlockHold,
|
|
|
toFlockQuoteHoldPublic,
|
|
|
} from "@/lib/constants/flock-quote-hold";
|
|
|
|
|
|
describe("flock quote hold — 60s/5min", () => {
|
|
|
it("构建 60s 决策窗 + 5min 总硬限", () => {
|
|
|
const now = 1_700_000_000_000;
|
|
|
const s = buildFlockQuoteHoldState({
|
|
|
quoteId: "q1",
|
|
|
sessionId: flockHoldSessionId("q1"),
|
|
|
customerId: "CUST_001",
|
|
|
nowMs: now,
|
|
|
});
|
|
|
expect(s.decision_deadline_ms).toBe(now + FLOCK_HOLD_DECISION_MS);
|
|
|
expect(s.total_deadline_ms).toBe(now + FLOCK_HOLD_TOTAL_MS);
|
|
|
expect(s.quote_session_id).toBe("flock_q1");
|
|
|
});
|
|
|
|
|
|
it("60s 边界:恰好到期应 auto-decline;filling 不因决策窗 decline", () => {
|
|
|
const now = 1_000;
|
|
|
const s = buildFlockQuoteHoldState({
|
|
|
quoteId: "q1",
|
|
|
sessionId: "flock_q1",
|
|
|
customerId: "CUST_001",
|
|
|
nowMs: now,
|
|
|
});
|
|
|
expect(shouldAutoDeclineFlockHold(s, now + FLOCK_HOLD_DECISION_MS - 1)).toBe(
|
|
|
false,
|
|
|
);
|
|
|
expect(shouldAutoDeclineFlockHold(s, now + FLOCK_HOLD_DECISION_MS)).toBe(
|
|
|
true,
|
|
|
);
|
|
|
expect(
|
|
|
shouldAutoDeclineFlockHold(
|
|
|
{ ...s, status: "filling" },
|
|
|
now + FLOCK_HOLD_DECISION_MS + 10_000,
|
|
|
),
|
|
|
).toBe(false);
|
|
|
});
|
|
|
|
|
|
it("5 分钟总硬限边界", () => {
|
|
|
const now = 1_000;
|
|
|
const s = buildFlockQuoteHoldState({
|
|
|
quoteId: "q1",
|
|
|
sessionId: "flock_q1",
|
|
|
customerId: "CUST_001",
|
|
|
nowMs: now,
|
|
|
});
|
|
|
expect(isFlockQuoteHoldExpired(s, now + FLOCK_HOLD_TOTAL_MS - 1)).toBe(
|
|
|
false,
|
|
|
);
|
|
|
expect(isFlockQuoteHoldExpired(s, now + FLOCK_HOLD_TOTAL_MS)).toBe(true);
|
|
|
});
|
|
|
|
|
|
it("倒计时文案", () => {
|
|
|
const now = 10_000;
|
|
|
expect(formatFlockHoldRemainingLabel(now + 45_000, now)).toBe("45秒");
|
|
|
expect(formatFlockHoldRemainingLabel(now + 65_000, now)).toBe("1分05秒");
|
|
|
});
|
|
|
|
|
|
it("超时提示含保留首价语义", () => {
|
|
|
expect(FLOCK_HOLD_MSG.decisionTimeout).toMatch(/初步报价|超时/);
|
|
|
expect(FLOCK_HOLD_MSG.totalTimeoutApi).toMatch(/5 分钟/);
|
|
|
});
|
|
|
|
|
|
it("public.available:awaiting 过决策窗 false;filling 仍 true 直至总硬限", () => {
|
|
|
const now = 5_000;
|
|
|
const s = buildFlockQuoteHoldState({
|
|
|
quoteId: "q1",
|
|
|
sessionId: "flock_q1",
|
|
|
customerId: "CUST_001",
|
|
|
nowMs: now,
|
|
|
});
|
|
|
expect(toFlockQuoteHoldPublic(s, now).available).toBe(true);
|
|
|
expect(
|
|
|
toFlockQuoteHoldPublic(s, now + FLOCK_HOLD_DECISION_MS).available,
|
|
|
).toBe(false);
|
|
|
expect(
|
|
|
toFlockQuoteHoldPublic(
|
|
|
{ ...s, status: "filling" },
|
|
|
now + FLOCK_HOLD_DECISION_MS + 1_000,
|
|
|
).available,
|
|
|
).toBe(true);
|
|
|
expect(
|
|
|
toFlockQuoteHoldPublic(
|
|
|
{ ...s, status: "filling" },
|
|
|
now + FLOCK_HOLD_TOTAL_MS,
|
|
|
).available,
|
|
|
).toBe(false);
|
|
|
});
|
|
|
});
|