Tests: fix full-suite regressions

This commit is contained in:
Peter Steinberger
2026-04-07 18:34:34 +01:00
parent 12331f0463
commit d855f5f505
6 changed files with 51 additions and 23 deletions

View File

@@ -1,5 +1,5 @@
export { buildChannelConfigSchema, formatPairingApproveHint } from "openclaw/plugin-sdk/core";
export type { ChannelPlugin } from "openclaw/plugin-sdk/core";
export type { ChannelOutboundAdapter, ChannelPlugin } from "openclaw/plugin-sdk/core";
export { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/core";
export {
collectStatusIssuesFromLastError,

View File

@@ -64,7 +64,7 @@ describe("nostr outbound cfg threading", () => {
)) as { stop: () => void };
const cfg = createCfg();
await nostrOutboundAdapter.sendText!({
await nostrOutboundAdapter.sendText({
cfg: cfg as OpenClawConfig,
to: "NPUB123",
text: "|a|b|",
@@ -121,7 +121,7 @@ describe("nostr outbound cfg threading", () => {
},
};
await nostrOutboundAdapter.sendText!({
await nostrOutboundAdapter.sendText({
cfg: cfg as OpenClawConfig,
to: "NPUB123",
text: "hello",

View File

@@ -5,6 +5,7 @@ import {
createPreCryptoDirectDmAuthorizer,
DEFAULT_ACCOUNT_ID,
dispatchInboundDirectDmWithRuntime,
type ChannelOutboundAdapter,
resolveInboundDirectDmAccessWithRuntime,
type ChannelPlugin,
} from "./channel-api.js";
@@ -16,7 +17,12 @@ import { resolveDefaultNostrAccountId, type ResolvedNostrAccount } from "./types
type NostrGatewayStart = NonNullable<
NonNullable<ChannelPlugin<ResolvedNostrAccount>["gateway"]>["startAccount"]
>;
type NostrOutbound = NonNullable<ChannelPlugin<ResolvedNostrAccount>["outbound"]>;
type NostrOutboundAdapter = Pick<
ChannelOutboundAdapter,
"deliveryMode" | "textChunkLimit" | "sendText"
> & {
sendText: NonNullable<ChannelOutboundAdapter["sendText"]>;
};
const activeBuses = new Map<string, NostrBusHandle>();
const metricsSnapshots = new Map<string, MetricsSnapshot>();
@@ -266,10 +272,7 @@ export const nostrPairingTextAdapter = {
},
};
export const nostrOutboundAdapter: Pick<
NostrOutbound,
"deliveryMode" | "textChunkLimit" | "sendText"
> = {
export const nostrOutboundAdapter: NostrOutboundAdapter = {
deliveryMode: "direct",
textChunkLimit: 4000,
sendText: async ({ cfg, to, text, accountId }) => {

View File

@@ -1,12 +1,12 @@
import { createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import {
createEmptyChannelResult,
createRawChannelSendResultAdapter,
} from "openclaw/plugin-sdk/channel-send-result";
import { createStaticReplyToModeResolver } from "openclaw/plugin-sdk/conversation-runtime";
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import {
checkZcaAuthenticated,
@@ -327,8 +327,7 @@ export const zalouserSecurityAdapter = {
account: ResolvedZalouserAccount;
orderedAccountIds: string[];
hasExplicitAccountPath: boolean;
}) =>
(await loadZalouserChannelRuntime()).collectZalouserSecurityAuditFindings(params),
}) => (await loadZalouserChannelRuntime()).collectZalouserSecurityAuditFindings(params),
};
export const zalouserThreadingAdapter = {
@@ -356,13 +355,13 @@ export const zalouserOutboundAdapter = {
deliveryMode: "direct" as const,
chunker: chunkTextForOutbound,
chunkerMode: "markdown" as const,
sendPayload: async (ctx: { payload: object } & Parameters<
NonNullable<typeof zalouserRawSendResultAdapter.sendText>
>[0]) =>
sendPayload: async (
ctx: { payload: object } & Parameters<
NonNullable<typeof zalouserRawSendResultAdapter.sendText>
>[0],
) =>
await sendPayloadWithChunkedTextAndMedia({
ctx,
textChunkLimit: resolveZalouserOutboundTextChunkLimit(ctx.cfg, ctx.accountId ?? undefined),
chunker: chunkTextForOutbound,
sendText: (nextCtx) => zalouserRawSendResultAdapter.sendText!(nextCtx),
sendMedia: (nextCtx) => zalouserRawSendResultAdapter.sendMedia!(nextCtx),
emptyResult: createEmptyChannelResult("zalouser"),

View File

@@ -1,6 +1,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { WebSocket } from "ws";
import { resolveMainSessionKeyFromConfig } from "../config/sessions.js";
import { drainSystemEvents } from "../infra/system-events.js";
import {
@@ -8,6 +9,7 @@ import {
TALK_TEST_PROVIDER_ID,
} from "../test-utils/talk-test-provider.js";
import { openTrackedWs } from "./device-authz.test-helpers.js";
import { ConnectErrorDetailCodes } from "./protocol/connect-error-details.js";
import {
connectReq,
connectOk,
@@ -222,6 +224,17 @@ vi.mock("./config-reload.js", () => ({
installGatewayTestHooks({ scope: "suite" });
async function waitForGatewayAuthChangedClose(ws: WebSocket): Promise<{
code: number;
reason: string;
}> {
return await new Promise((resolve) => {
ws.once("close", (code, reason) => {
resolve({ code, reason: reason.toString() });
});
});
}
describe("gateway hot reload", () => {
let prevSkipChannels: string | undefined;
let prevSkipGmail: string | undefined;
@@ -1048,8 +1061,17 @@ process.stdin.on("end", () => {
await connectOk(ws, { token: "token-before-reload" });
await fs.writeFile(tokenPath, "token-after-reload\n", "utf8");
const reload = await rpcReq<{ warningCount?: number }>(ws, "secrets.reload", {});
expect(reload.ok).toBe(true);
const closed = waitForGatewayAuthChangedClose(ws);
const reload = await rpcReq<{ warningCount?: number }>(ws, "secrets.reload", {}).catch(
(err: unknown) => (err instanceof Error ? err : new Error(String(err))),
);
await expect(closed).resolves.toEqual({
code: 4001,
reason: "gateway auth changed",
});
if (!(reload instanceof Error)) {
expect(reload.ok).toBe(true);
}
const staleWs = await openTrackedWs(port);
try {
@@ -1059,6 +1081,9 @@ process.stdin.on("end", () => {
});
expect(staleConnect.ok).toBe(false);
expect(staleConnect.error?.message ?? "").toContain("gateway token mismatch");
expect((staleConnect.error?.details as { code?: unknown } | undefined)?.code).toBe(
ConnectErrorDetailCodes.AUTH_TOKEN_MISMATCH,
);
} finally {
staleWs.close();
}

View File

@@ -213,15 +213,16 @@ describe("gateway shared auth rotation with unchanged SecretRefs", () => {
return ws;
}
it("keeps shared-auth websocket sessions connected when config.apply reapplies an unchanged SecretRef token", async () => {
it("disconnects shared-auth websocket sessions when config.apply rewrites a SecretRef token", async () => {
const ws = await openSecretRefAuthenticatedWs();
try {
const closed = waitForClose(ws);
const res = await applyCurrentConfig(ws);
expect(res.ok).toBe(true);
const followUp = await rpcReq<{ hash?: string }>(ws, "config.get", {});
expect(followUp.ok).toBe(true);
expect(typeof followUp.payload?.hash).toBe("string");
await expect(closed).resolves.toEqual({
code: 4001,
reason: "gateway auth changed",
});
} finally {
ws.close();
}