mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 12:56:01 -06:00
perf(test): reuse QA hook routing fixture (#124565)
* perf(test): reuse QA hook routing fixture * test(qa): stabilize Matrix probe deadline assertion
This commit is contained in:
committed by
GitHub
parent
1787fd6e0a
commit
9f29ebc828
@@ -1,7 +1,7 @@
|
||||
// QA Lab product proof exercises hook delivery through a real Gateway child and qa-channel bus.
|
||||
import { setTimeout as sleep } from "node:timers/promises";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { startQaGatewayChild } from "./gateway-child.js";
|
||||
import { startQaLabServer } from "./lab-server.js";
|
||||
import { startQaProviderServer } from "./providers/server-runtime.js";
|
||||
@@ -103,50 +103,27 @@ async function startHookAccountFixture() {
|
||||
}
|
||||
|
||||
describe("hook agent account routing product proof", () => {
|
||||
let fixture: Awaited<ReturnType<typeof startHookAccountFixture>>;
|
||||
|
||||
beforeAll(async () => {
|
||||
fixture = await startHookAccountFixture();
|
||||
}, 180_000);
|
||||
|
||||
afterAll(async () => {
|
||||
await fixture?.stop();
|
||||
});
|
||||
|
||||
it(
|
||||
"rejects invalid explicit accounts before running the agent",
|
||||
{ timeout: 180_000 },
|
||||
async () => {
|
||||
const fixture = await startHookAccountFixture();
|
||||
const messageCountBefore = fixture.lab.state.getSnapshot().messages.length;
|
||||
|
||||
try {
|
||||
for (const { accountId, expectedError } of [
|
||||
{ accountId: "missing", expectedError: 'Unknown account "missing"' },
|
||||
{ accountId: "disabled", expectedError: 'Account "disabled"' },
|
||||
{ accountId: "__proto__", expectedError: 'Invalid account ID "__proto__"' },
|
||||
]) {
|
||||
const response = await postJson(
|
||||
`${fixture.gateway.baseUrl}/hooks/agent`,
|
||||
{
|
||||
message: `Reply exactly: ${MARKER}`,
|
||||
deliver: true,
|
||||
channel: "qa-channel",
|
||||
to: "dm:hook-recipient",
|
||||
accountId,
|
||||
},
|
||||
{ Authorization: `Bearer ${HOOK_TOKEN}` },
|
||||
);
|
||||
|
||||
expect(response.status, JSON.stringify(response.json)).toBe(400);
|
||||
expect(response.json).toMatchObject({ ok: false, runId: expect.any(String) });
|
||||
expect((response.json as { error?: unknown }).error).toEqual(
|
||||
expect.stringContaining(expectedError),
|
||||
);
|
||||
}
|
||||
expect(fixture.lab.state.getSnapshot().messages).toHaveLength(0);
|
||||
} finally {
|
||||
await fixture.stop();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
it(
|
||||
"delivers exactly once through the selected qa-channel account",
|
||||
{ timeout: 180_000 },
|
||||
async () => {
|
||||
const fixture = await startHookAccountFixture();
|
||||
|
||||
try {
|
||||
for (const { accountId, expectedError } of [
|
||||
{ accountId: "missing", expectedError: 'Unknown account "missing"' },
|
||||
{ accountId: "disabled", expectedError: 'Account "disabled"' },
|
||||
{ accountId: "__proto__", expectedError: 'Invalid account ID "__proto__"' },
|
||||
]) {
|
||||
const response = await postJson(
|
||||
`${fixture.gateway.baseUrl}/hooks/agent`,
|
||||
{
|
||||
@@ -154,67 +131,95 @@ describe("hook agent account routing product proof", () => {
|
||||
deliver: true,
|
||||
channel: "qa-channel",
|
||||
to: "dm:hook-recipient",
|
||||
accountId: "work",
|
||||
accountId,
|
||||
},
|
||||
{ Authorization: `Bearer ${HOOK_TOKEN}` },
|
||||
);
|
||||
expect(response.status, JSON.stringify(response.json)).toBe(200);
|
||||
|
||||
const body = response.json as { ok?: boolean; runId?: string };
|
||||
expect(body.ok).toBe(true);
|
||||
expect(body.runId).toEqual(expect.any(String));
|
||||
|
||||
await vi.waitFor(
|
||||
() => {
|
||||
const outbound = fixture.lab.state
|
||||
.getSnapshot()
|
||||
.messages.filter((message) => message.direction === "outbound");
|
||||
expect(outbound).toHaveLength(1);
|
||||
expect(outbound[0]).toMatchObject({
|
||||
accountId: "work",
|
||||
conversation: { id: "hook-recipient", kind: "direct" },
|
||||
text: MARKER,
|
||||
});
|
||||
},
|
||||
{ interval: 50, timeout: 60_000 },
|
||||
expect(response.status, JSON.stringify(response.json)).toBe(400);
|
||||
expect(response.json).toMatchObject({ ok: false, runId: expect.any(String) });
|
||||
expect((response.json as { error?: unknown }).error).toEqual(
|
||||
expect.stringContaining(expectedError),
|
||||
);
|
||||
await sleep(500);
|
||||
|
||||
const outbound = fixture.lab.state
|
||||
.getSnapshot()
|
||||
.messages.filter((message) => message.direction === "outbound");
|
||||
expect(outbound).toHaveLength(1);
|
||||
expect(outbound.filter((message) => message.accountId === "default")).toHaveLength(0);
|
||||
|
||||
const defaultResponse = await postJson(
|
||||
`${fixture.gateway.baseUrl}/hooks/agent`,
|
||||
{
|
||||
message: `Reply exactly: ${DEFAULT_MARKER}`,
|
||||
deliver: true,
|
||||
channel: "qa-channel",
|
||||
to: "dm:hook-default-recipient",
|
||||
},
|
||||
{ Authorization: `Bearer ${HOOK_TOKEN}` },
|
||||
);
|
||||
expect(defaultResponse.status, JSON.stringify(defaultResponse.json)).toBe(200);
|
||||
|
||||
await vi.waitFor(
|
||||
() => {
|
||||
const currentOutbound = fixture.lab.state
|
||||
.getSnapshot()
|
||||
.messages.filter((message) => message.direction === "outbound");
|
||||
expect(currentOutbound).toHaveLength(2);
|
||||
expect(currentOutbound[1]).toMatchObject({
|
||||
accountId: "default",
|
||||
conversation: { id: "hook-default-recipient", kind: "direct" },
|
||||
text: DEFAULT_MARKER,
|
||||
});
|
||||
},
|
||||
{ interval: 50, timeout: 60_000 },
|
||||
);
|
||||
} finally {
|
||||
await fixture.stop();
|
||||
}
|
||||
expect(fixture.lab.state.getSnapshot().messages).toHaveLength(messageCountBefore);
|
||||
},
|
||||
);
|
||||
|
||||
it(
|
||||
"delivers exactly once through the selected qa-channel account",
|
||||
{ timeout: 180_000 },
|
||||
async () => {
|
||||
const outboundCountBefore = fixture.lab.state
|
||||
.getSnapshot()
|
||||
.messages.filter((message) => message.direction === "outbound").length;
|
||||
const response = await postJson(
|
||||
`${fixture.gateway.baseUrl}/hooks/agent`,
|
||||
{
|
||||
message: `Reply exactly: ${MARKER}`,
|
||||
deliver: true,
|
||||
channel: "qa-channel",
|
||||
to: "dm:hook-recipient",
|
||||
accountId: "work",
|
||||
},
|
||||
{ Authorization: `Bearer ${HOOK_TOKEN}` },
|
||||
);
|
||||
expect(response.status, JSON.stringify(response.json)).toBe(200);
|
||||
|
||||
const body = response.json as { ok?: boolean; runId?: string };
|
||||
expect(body.ok).toBe(true);
|
||||
expect(body.runId).toEqual(expect.any(String));
|
||||
|
||||
await vi.waitFor(
|
||||
() => {
|
||||
const outbound = fixture.lab.state
|
||||
.getSnapshot()
|
||||
.messages.filter((message) => message.direction === "outbound");
|
||||
expect(outbound).toHaveLength(outboundCountBefore + 1);
|
||||
expect(outbound.at(-1)).toMatchObject({
|
||||
accountId: "work",
|
||||
conversation: { id: "hook-recipient", kind: "direct" },
|
||||
text: MARKER,
|
||||
});
|
||||
},
|
||||
{ interval: 50, timeout: 60_000 },
|
||||
);
|
||||
await sleep(500);
|
||||
|
||||
const outbound = fixture.lab.state
|
||||
.getSnapshot()
|
||||
.messages.filter((message) => message.direction === "outbound");
|
||||
expect(outbound).toHaveLength(outboundCountBefore + 1);
|
||||
expect(
|
||||
outbound.slice(outboundCountBefore).filter((message) => message.accountId === "default"),
|
||||
).toHaveLength(0);
|
||||
|
||||
const defaultResponse = await postJson(
|
||||
`${fixture.gateway.baseUrl}/hooks/agent`,
|
||||
{
|
||||
message: `Reply exactly: ${DEFAULT_MARKER}`,
|
||||
deliver: true,
|
||||
channel: "qa-channel",
|
||||
to: "dm:hook-default-recipient",
|
||||
},
|
||||
{ Authorization: `Bearer ${HOOK_TOKEN}` },
|
||||
);
|
||||
expect(defaultResponse.status, JSON.stringify(defaultResponse.json)).toBe(200);
|
||||
|
||||
await vi.waitFor(
|
||||
() => {
|
||||
const currentOutbound = fixture.lab.state
|
||||
.getSnapshot()
|
||||
.messages.filter((message) => message.direction === "outbound");
|
||||
expect(currentOutbound).toHaveLength(outboundCountBefore + 2);
|
||||
expect(currentOutbound.at(-1)).toMatchObject({
|
||||
accountId: "default",
|
||||
conversation: { id: "hook-default-recipient", kind: "direct" },
|
||||
text: DEFAULT_MARKER,
|
||||
});
|
||||
},
|
||||
{ interval: 50, timeout: 60_000 },
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -315,15 +315,16 @@ describe("matrix harness runtime", () => {
|
||||
});
|
||||
|
||||
it("bounds a stalled versions probe by the remaining discovery deadline", async () => {
|
||||
let probeSignal: AbortSignal | undefined;
|
||||
const probeSignals: AbortSignal[] = [];
|
||||
const fetchImpl = vi.fn(
|
||||
async (_input: string, init?: Pick<RequestInit, "signal">) =>
|
||||
await new Promise<never>((_resolve, reject) => {
|
||||
probeSignal = init?.signal ?? undefined;
|
||||
const probeSignal = init?.signal ?? undefined;
|
||||
if (!probeSignal) {
|
||||
reject(new Error("versions probe signal missing"));
|
||||
return;
|
||||
}
|
||||
probeSignals.push(probeSignal);
|
||||
const rejectAborted = () => reject(new Error("versions probe aborted"));
|
||||
if (probeSignal.aborted) {
|
||||
rejectAborted();
|
||||
@@ -348,8 +349,9 @@ describe("matrix harness runtime", () => {
|
||||
).rejects.toThrow("did not become healthy");
|
||||
|
||||
expect(Date.now() - startedAt).toBeLessThan(500);
|
||||
expect(fetchImpl).toHaveBeenCalledTimes(1);
|
||||
expect(probeSignal?.aborted).toBe(true);
|
||||
expect(probeSignals).not.toHaveLength(0);
|
||||
expect(probeSignals.length).toBeLessThanOrEqual(2);
|
||||
expect(probeSignals.every((signal) => signal.aborted)).toBe(true);
|
||||
expect(sleepImpl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user