



























@@ -1,10 +1,30 @@
1-import { describe, expect, it } from "vitest";
1+import { afterEach, describe, expect, it, vi } from "vitest";
22import {
33getGatewayRetryAfterMs,
44isConfigApplyNoopForSnapshot,
55isConfigHashConflict,
66isConfigPatchNoopForSnapshot,
7+waitForConfigRestartSettle,
78} from "./suite-runtime-gateway.js";
9+import type { QaSuiteRuntimeEnv } from "./suite-runtime-types.js";
10+11+const fetchWithSsrFGuardMock = vi.hoisted(() => vi.fn());
12+13+vi.mock("openclaw/plugin-sdk/ssrf-runtime", () => ({
14+fetchWithSsrFGuard: fetchWithSsrFGuardMock,
15+}));
16+17+afterEach(() => {
18+fetchWithSsrFGuardMock.mockReset();
19+vi.useRealTimers();
20+});
21+22+function createRestartSettleEnv(waitReady: (params: unknown) => Promise<void>) {
23+return {
24+gateway: { baseUrl: "http://127.0.0.1:43123" },
25+transport: { waitReady },
26+} as unknown as Pick<QaSuiteRuntimeEnv, "gateway" | "transport">;
27+}
828929describe("qa suite gateway helpers", () => {
1030it("reads retry-after from the primary gateway error before appended logs", () => {
@@ -113,4 +133,45 @@ describe("qa suite gateway helpers", () => {
113133),
114134).toBe(false);
115135});
136+137+it("waits for transport readiness after gateway restart health", async () => {
138+const release = vi.fn(async () => {});
139+fetchWithSsrFGuardMock.mockResolvedValue({
140+response: { ok: true },
141+ release,
142+});
143+const waitReady = vi.fn(async () => {});
144+145+await waitForConfigRestartSettle(createRestartSettleEnv(waitReady), 0, 1_000);
146+147+expect(fetchWithSsrFGuardMock).toHaveBeenCalledWith(
148+expect.objectContaining({
149+url: "http://127.0.0.1:43123/readyz",
150+auditContext: "qa-lab-suite-wait-for-gateway-healthy",
151+}),
152+);
153+expect(waitReady).toHaveBeenCalledWith({
154+gateway: { baseUrl: "http://127.0.0.1:43123" },
155+timeoutMs: expect.any(Number),
156+});
157+expect(release).toHaveBeenCalled();
158+});
159+160+it("keeps polling gateway health instead of sleeping blindly through restart settle", async () => {
161+vi.useFakeTimers();
162+const release = vi.fn(async () => {});
163+fetchWithSsrFGuardMock.mockRejectedValueOnce(new Error("restart boundary")).mockResolvedValue({
164+response: { ok: true },
165+ release,
166+});
167+const waitReady = vi.fn(async () => {});
168+169+const settling = waitForConfigRestartSettle(createRestartSettleEnv(waitReady), 500, 5_000);
170+171+await vi.advanceTimersByTimeAsync(1_250);
172+await settling;
173+174+expect(fetchWithSsrFGuardMock).toHaveBeenCalledTimes(2);
175+expect(waitReady).toHaveBeenCalledTimes(1);
176+});
116177});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。