You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
2.7 KiB
106 lines
2.7 KiB
import { describe, expect, it, vi } from "vitest";
|
|
import { pollQuoteUntilDone } from "@/hooks/use-quote-polling";
|
|
import {
|
|
POLL_INTERVAL_MS,
|
|
POLL_TIMEOUT_MS,
|
|
} from "@/lib/frontend/constants";
|
|
import type { QuoteDetail } from "@/lib/frontend/types";
|
|
|
|
function processingQuote(): QuoteDetail {
|
|
return {
|
|
quote_id: "QTE_test",
|
|
request_id: "req-1",
|
|
status: "processing",
|
|
currency: "USD",
|
|
};
|
|
}
|
|
|
|
function doneQuote(): QuoteDetail {
|
|
return {
|
|
quote_id: "QTE_test",
|
|
request_id: "req-1",
|
|
status: "done",
|
|
currency: "USD",
|
|
is_realtime: true,
|
|
quotes: [],
|
|
};
|
|
}
|
|
|
|
describe("pollQuoteUntilDone", () => {
|
|
it("前 3 次网络失败第 4 次成功 → done", async () => {
|
|
let calls = 0;
|
|
const result = await pollQuoteUntilDone(async () => {
|
|
calls += 1;
|
|
if (calls < 4) {
|
|
return { ok: false };
|
|
}
|
|
return { ok: true, data: doneQuote() };
|
|
});
|
|
expect(result.type).toBe("done");
|
|
if (result.type === "done") {
|
|
expect(result.quote.status).toBe("done");
|
|
}
|
|
expect(calls).toBe(4);
|
|
});
|
|
|
|
it("超过 POLL_TIMEOUT_MS 仍 processing → timeout", async () => {
|
|
vi.useFakeTimers();
|
|
const promise = pollQuoteUntilDone(async () => ({
|
|
ok: true,
|
|
data: processingQuote(),
|
|
}));
|
|
|
|
await vi.advanceTimersByTimeAsync(
|
|
POLL_TIMEOUT_MS + POLL_INTERVAL_MS,
|
|
);
|
|
const result = await promise;
|
|
expect(result.type).toBe("timeout");
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it("failed 状态 → error 含可读文案", async () => {
|
|
const result = await pollQuoteUntilDone(async () => ({
|
|
ok: true,
|
|
data: {
|
|
...doneQuote(),
|
|
status: "failed",
|
|
error_code: "ADDRESS_SUGGESTION_NOT_FOUND",
|
|
error_message: "未找到用户确认的 MotherShip 地址",
|
|
},
|
|
}));
|
|
expect(result.type).toBe("error");
|
|
if (result.type === "error") {
|
|
expect(result.message).toBe("未找到用户确认的 MotherShip 地址");
|
|
}
|
|
});
|
|
|
|
it("processing 超过 10s 后使用更短轮询间隔", async () => {
|
|
vi.useFakeTimers();
|
|
let calls = 0;
|
|
const intervals: number[] = [];
|
|
let last = Date.now();
|
|
|
|
const promise = pollQuoteUntilDone(async () => {
|
|
const now = Date.now();
|
|
if (calls > 0) {
|
|
intervals.push(now - last);
|
|
}
|
|
last = now;
|
|
calls += 1;
|
|
if (calls < 7) {
|
|
return { ok: true, data: processingQuote() };
|
|
}
|
|
return { ok: true, data: doneQuote() };
|
|
});
|
|
|
|
for (let i = 0; i < 6; i += 1) {
|
|
await vi.advanceTimersByTimeAsync(2_000);
|
|
}
|
|
await vi.advanceTimersByTimeAsync(800);
|
|
const result = await promise;
|
|
expect(result.type).toBe("done");
|
|
expect(intervals.some((gap) => gap <= 800)).toBe(true);
|
|
vi.useRealTimers();
|
|
});
|
|
});
|