test: tighten gateway array assertions

This commit is contained in:
Shakker
2026-05-09 05:54:10 +01:00
parent 4962620a4b
commit 0924eb0731
17 changed files with 47 additions and 45 deletions

View File

@@ -576,7 +576,7 @@ describe("callGateway url resolution", () => {
expect(lastClientOptions?.scopes).toEqual(["operator.read"]);
await callGatewayScoped({ method: "health", scopes: [] });
expect(lastClientOptions?.scopes).toEqual([]);
expect(lastClientOptions?.scopes).toStrictEqual([]);
});
it("uses backend client metadata for explicit scoped default calls", async () => {

View File

@@ -394,7 +394,7 @@ describe("parseMessageWithAttachments validation errors", () => {
try {
expect(parsed.images).toHaveLength(0);
expect(parsed.imageOrder).toEqual([]);
expect(parsed.imageOrder).toStrictEqual([]);
expect(parsed.offloadedRefs).toHaveLength(1);
expect(parsed.offloadedRefs[0]).toMatchObject({
mimeType: "application/pdf",

View File

@@ -64,7 +64,7 @@ describe("diffConfigPaths", () => {
},
},
};
expect(diffConfigPaths(prev, next)).toEqual([]);
expect(diffConfigPaths(prev, next)).toStrictEqual([]);
});
it("reports changed arrays of objects", () => {
@@ -190,7 +190,7 @@ describe("buildGatewayReloadPlan", () => {
const plan = buildGatewayReloadPlan(["browser.enabled"]);
expect(plan.restartGateway).toBe(true);
expect(plan.restartReasons).toContain("browser.enabled");
expect(plan.hotReasons).toEqual([]);
expect(plan.hotReasons).toStrictEqual([]);
});
it("restarts the Gmail watcher for hooks.gmail changes", () => {
@@ -270,7 +270,7 @@ describe("buildGatewayReloadPlan", () => {
expect(plan.restartGateway).toBe(true);
expect(plan.restartReasons).toContain("models.pricing.enabled");
expect(plan.restartHeartbeat).toBe(false);
expect(plan.hotReasons).toEqual([]);
expect(plan.hotReasons).toStrictEqual([]);
});
it("restarts heartbeat when agents.defaults.models allowlist changes", () => {
@@ -278,7 +278,7 @@ describe("buildGatewayReloadPlan", () => {
expect(plan.restartGateway).toBe(false);
expect(plan.restartHeartbeat).toBe(true);
expect(plan.hotReasons).toContain("agents.defaults.models");
expect(plan.noopPaths).toEqual([]);
expect(plan.noopPaths).toStrictEqual([]);
});
it("restarts heartbeat when agents.list entries change", () => {
@@ -286,7 +286,7 @@ describe("buildGatewayReloadPlan", () => {
expect(plan.restartGateway).toBe(false);
expect(plan.restartHeartbeat).toBe(true);
expect(plan.hotReasons).toContain("agents.list");
expect(plan.noopPaths).toEqual([]);
expect(plan.noopPaths).toStrictEqual([]);
});
it("treats plugin install timestamp-only changes as no-op", () => {
@@ -317,7 +317,7 @@ describe("buildGatewayReloadPlan", () => {
"plugins.installs.lossless.resolvedAt",
"plugins.installs.lossless.resolvedAt",
]);
expect(plan.noopPaths).toEqual([]);
expect(plan.noopPaths).toStrictEqual([]);
});
it("requires restart when plugin load paths change", () => {
@@ -722,14 +722,14 @@ describe("startGatewayConfigReloader", () => {
expect(onHotReload).not.toHaveBeenCalled();
expect(onRestart).toHaveBeenCalledTimes(1);
expect(log.error).toHaveBeenCalledWith("config restart failed: Error: restart-check failed");
expect(unhandled).toEqual([]);
expect(unhandled).toStrictEqual([]);
watcher.emit("change");
await vi.runOnlyPendingTimersAsync();
await Promise.resolve();
expect(onRestart).toHaveBeenCalledTimes(2);
expect(unhandled).toEqual([]);
expect(unhandled).toStrictEqual([]);
} finally {
process.off("unhandledRejection", onUnhandled);
await reloader.stop();

View File

@@ -63,7 +63,7 @@ describe("resolveTrustedHttpOperatorScopes", () => {
tokenAuth,
);
expect(scopes).toEqual([]);
expect(scopes).toStrictEqual([]);
});
it("keeps declared scopes for non-bearer HTTP requests", () => {
@@ -98,7 +98,7 @@ describe("resolveTrustedHttpOperatorScopes", () => {
{ trustDeclaredOperatorScopes: false },
);
expect(scopes).toEqual([]);
expect(scopes).toStrictEqual([]);
});
});

View File

@@ -62,11 +62,13 @@ describe("method scope resolution", () => {
});
it("leaves node-only pending drain outside operator scopes", () => {
expect(resolveLeastPrivilegeOperatorScopesForMethod("node.pending.drain")).toEqual([]);
expect(resolveLeastPrivilegeOperatorScopesForMethod("node.pending.drain")).toStrictEqual([]);
});
it("returns empty scopes for unknown methods", () => {
expect(resolveLeastPrivilegeOperatorScopesForMethod("totally.unknown.method")).toEqual([]);
expect(resolveLeastPrivilegeOperatorScopesForMethod("totally.unknown.method")).toStrictEqual(
[],
);
});
it("reads plugin-registered gateway method scopes from the active plugin registry", () => {
@@ -228,14 +230,14 @@ describe("core gateway method classification", () => {
const unclassified = Object.keys(coreGatewayHandlers).filter(
(method) => !isGatewayMethodClassified(method),
);
expect(unclassified).toEqual([]);
expect(unclassified).toStrictEqual([]);
});
it("classifies every listed gateway method name", () => {
const unclassified = listGatewayMethods().filter(
(method) => !isGatewayMethodClassified(method),
);
expect(unclassified).toEqual([]);
expect(unclassified).toStrictEqual([]);
});
});

View File

@@ -1151,7 +1151,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
completion_tokens: 5,
total_tokens: 20,
});
expect(usageChunk?.choices).toEqual([]);
expect(usageChunk?.choices).toStrictEqual([]);
});
it("keeps aggregate-only usage total in final stream usage chunk", async () => {

View File

@@ -1217,7 +1217,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
await vi.waitFor(() => {
expect(agentCommand.mock.calls).toHaveLength(1);
});
expect(openResponsesTesting.getResponseSessionIds()).toEqual([]);
expect(openResponsesTesting.getResponseSessionIds()).toStrictEqual([]);
release?.({ payloads: [{ text: "hello" }] });

View File

@@ -791,14 +791,14 @@ describe("chat directive tag stripping for non-streaming final payloads", () =>
);
// Agent-run delivery is a live projection; Pi message_end owns persisted
// assistant transcript entries, including stale media/text final payloads.
expect(assistantUpdates).toEqual([]);
expect(assistantUpdates).toStrictEqual([]);
const transcriptLines = readTranscriptJsonLines(mockState.transcriptPath);
const assistantEntries = transcriptLines.filter(
(entry) =>
(entry as { message?: { role?: string } }).message?.role === "assistant" ||
(entry as { role?: string }).role === "assistant",
);
expect(assistantEntries).toEqual([]);
expect(assistantEntries).toStrictEqual([]);
});
it("does not mirror normal agent-run final text from live delivery", async () => {
@@ -838,14 +838,14 @@ describe("chat directive tag stripping for non-streaming final payloads", () =>
);
// Normal agent-run final text must not be mirrored into JSONL by WebChat;
// Pi persists the model-visible assistant turn from message_end.
expect(assistantUpdates).toEqual([]);
expect(assistantUpdates).toStrictEqual([]);
const transcriptLines = readTranscriptJsonLines(mockState.transcriptPath);
const assistantEntries = transcriptLines.filter(
(entry) =>
(entry as { message?: { role?: string } }).message?.role === "assistant" ||
(entry as { role?: string }).role === "assistant",
);
expect(assistantEntries).toEqual([]);
expect(assistantEntries).toStrictEqual([]);
});
it("keeps visible text on non-agent TTS final media because no model transcript exists", async () => {
@@ -2002,7 +2002,7 @@ describe("chat directive tag stripping for non-streaming final payloads", () =>
expectBroadcast: false,
});
expect(mockState.lastDispatchCtx?.GatewayClientScopes).toEqual([]);
expect(mockState.lastDispatchCtx?.GatewayClientScopes).toStrictEqual([]);
expect(mockState.lastDispatchCtx?.CommandBody).toBe("/scopecheck");
});
@@ -2425,7 +2425,7 @@ describe("chat directive tag stripping for non-streaming final payloads", () =>
update.message !== null &&
(update.message as { role?: unknown }).role === "user",
);
expect(mockState.savedMediaCalls).toEqual([]);
expect(mockState.savedMediaCalls).toStrictEqual([]);
expect(userUpdate).toMatchObject({
message: {
role: "user",
@@ -3361,7 +3361,7 @@ describe("chat directive tag stripping for non-streaming final payloads", () =>
waitFor: "none",
});
expect(mockState.savedMediaCalls).toEqual([]);
expect(mockState.savedMediaCalls).toStrictEqual([]);
expect(mockState.lastDispatchImages).toBeUndefined();
expect(respond).toHaveBeenCalledWith(true, {
ok: true,

View File

@@ -88,7 +88,7 @@ describe("gateway restart deferral", () => {
expect(getTotalPendingReplies()).toBe(0);
expect(restartTriggered).toBe(false);
expect(replyErrors).toEqual([]);
expect(replyErrors).toStrictEqual([]);
expect(deliveredReplies).toEqual(["Configuration updated!"]);
});

View File

@@ -328,7 +328,7 @@ describe("gateway server hooks", () => {
expect(targetEvents).toEqual(
expect.arrayContaining([expect.stringContaining("Hook Email: done")]),
);
expect(peekSystemEventEntries(resolveMainKey())).toEqual([]);
expect(peekSystemEventEntries(resolveMainKey())).toStrictEqual([]);
drainSystemEvents(HOOKS_MAIN_SESSION_KEY);
});
});
@@ -362,7 +362,7 @@ describe("gateway server hooks", () => {
});
expect(directSilent.status).toBe(200);
await waitForCronIsolatedRuns(1);
expect(peekSystemEventEntries(resolveMainKey())).toEqual([]);
expect(peekSystemEventEntries(resolveMainKey())).toStrictEqual([]);
cronIsolatedRun.mockResolvedValueOnce({
status: "ok",
@@ -372,7 +372,7 @@ describe("gateway server hooks", () => {
const mappedSilent = await postHook(port, "/hooks/mapped-silent", { subject: "Email" });
expect(mappedSilent.status).toBe(200);
await waitForCronIsolatedRuns(2);
expect(peekSystemEventEntries(resolveMainKey())).toEqual([]);
expect(peekSystemEventEntries(resolveMainKey())).toStrictEqual([]);
cronIsolatedRun.mockResolvedValueOnce({
status: "error",
@@ -409,7 +409,7 @@ describe("gateway server hooks", () => {
});
expect(response.status).toBe(200);
await waitForCronIsolatedRuns(1);
expect(peekSystemEventEntries(resolveMainKey())).toEqual([]);
expect(peekSystemEventEntries(resolveMainKey())).toStrictEqual([]);
});
});

View File

@@ -322,7 +322,7 @@ describe("gateway server models + voicewake", () => {
expect(initial.ok).toBe(true);
expect(initial.payload?.config?.version).toBe(1);
expect(initial.payload?.config?.defaultTarget).toEqual({ mode: "current" });
expect(initial.payload?.config?.routes).toEqual([]);
expect(initial.payload?.config?.routes).toStrictEqual([]);
const changedP = onceMessage<{
type: "event";
@@ -444,7 +444,7 @@ describe("gateway server models + voicewake", () => {
expect(first.event).toBe("voicewake.routing.changed");
expect(
(first.payload as { config?: { routes?: unknown[] } } | undefined)?.config?.routes,
).toEqual([]);
).toStrictEqual([]);
const broadcastP = onceMessage<{
type: "event";
@@ -528,7 +528,7 @@ describe("gateway server models + voicewake", () => {
const discoverCallsBefore = piSdkMock.discoverCalls;
const res = await listModels({ view: "configured" });
expect(res.ok).toBe(true);
expect(res.payload?.models).toEqual([]);
expect(res.payload?.models).toStrictEqual([]);
expect(piSdkMock.discoverCalls).toBe(discoverCallsBefore);
});
},

View File

@@ -154,7 +154,7 @@ describe("gateway trusted CIDR node pairing auto-approve", () => {
expect(pending).toHaveLength(0);
const paired = await getPairedDevice(loaded.identity.deviceId);
expect(paired?.role).toBe("node");
expect(paired?.approvedScopes ?? []).toEqual([]);
expect(paired?.approvedScopes ?? []).toStrictEqual([]);
} finally {
ws?.close();
await started.server.close();

View File

@@ -435,7 +435,7 @@ describe("gateway hot reload", () => {
);
await expect(params.applyReload()).rejects.toThrow(params.expectedError);
expect(drainSystemEvents(params.sessionKey)).toEqual([]);
expect(drainSystemEvents(params.sessionKey)).toStrictEqual([]);
}
async function expectSecretReloadRecovered(params: {

View File

@@ -37,7 +37,7 @@ describe("gateway tools.catalog", () => {
expect(noPlugins.ok).toBe(true);
expect(
(noPlugins.payload?.groups ?? []).filter((group) => group.source === "plugin"),
).toEqual([]);
).toStrictEqual([]);
const unknownAgent = await rpcReq(ws, "tools.catalog", { agentId: "does-not-exist" });
expect(unknownAgent.ok).toBe(false);

View File

@@ -164,7 +164,7 @@ describe("createGatewayPluginRequestHandler", () => {
expect(handled).toBe(true);
expect(res.statusCode).toBe(200);
expect(observedScopes).toEqual([]);
expect(observedScopes).toStrictEqual([]);
});
it("preserves gateway-authenticated plugin route runtime scopes from request auth", async () => {
@@ -478,7 +478,7 @@ describe("createGatewayPluginUpgradeHandler", () => {
expect(handled).toBe(true);
expect(routeUpgradeHandler).toHaveBeenCalledTimes(1);
expect(socket.destroyed).toBe(false);
expect(socket.chunks).toEqual([]);
expect(socket.chunks).toStrictEqual([]);
});
});

View File

@@ -1793,7 +1793,7 @@ describe("resolveSessionTranscriptCandidates safety", () => {
"/tmp/openclaw/agents/main/sessions/sessions.json",
);
expect(candidates).toEqual([]);
expect(candidates).toStrictEqual([]);
});
test("drops unsafe sessionFile candidates and keeps safe fallbacks", () => {
@@ -1937,7 +1937,7 @@ describe("archiveSessionTranscripts", () => {
reason: "reset",
});
expect(archived).toEqual([]);
expect(archived).toStrictEqual([]);
});
test("skips files that do not exist and archives only existing ones", () => {

View File

@@ -506,7 +506,7 @@ describe("listSessionsFromStore subagent metadata", () => {
},
});
expect(result.sessions.map((session) => session.key)).toEqual([]);
expect(result.sessions.map((session) => session.key)).toStrictEqual([]);
});
test("reports the newest run owner for moved child session rows", () => {
@@ -904,7 +904,7 @@ describe("listSessionsFromStore subagent metadata", () => {
}),
);
expect(result.sessions).toEqual([]);
expect(result.sessions).toStrictEqual([]);
const registryStatCount = statSpy.mock.calls.filter(
([pathname]) => path.normalize(String(pathname)) === path.normalize(registryPath),
).length;
@@ -1005,7 +1005,7 @@ describe("listSessionsFromStore subagent metadata", () => {
spawnedBy: "agent:main:main",
},
});
expect(filtered.sessions.map((session) => session.key)).toEqual([]);
expect(filtered.sessions.map((session) => session.key)).toStrictEqual([]);
});
test("does not reattach stale orphan store-only child links without lifecycle fields", () => {
@@ -1041,7 +1041,7 @@ describe("listSessionsFromStore subagent metadata", () => {
spawnedBy: "agent:main:main",
},
});
expect(filtered.sessions.map((session) => session.key)).toEqual([]);
expect(filtered.sessions.map((session) => session.key)).toStrictEqual([]);
});
test("does not keep old ended registry runs attached as child sessions", () => {
@@ -1089,7 +1089,7 @@ describe("listSessionsFromStore subagent metadata", () => {
spawnedBy: "agent:main:main",
},
});
expect(filtered.sessions.map((session) => session.key)).toEqual([]);
expect(filtered.sessions.map((session) => session.key)).toStrictEqual([]);
});
test("keeps ended parents attached while live descendants are still running", () => {