Skip to content

Commit 590ba12

Browse files
authored
test(browser): type port availability mock
1 parent 617f9ef commit 590ba12

19 files changed

Lines changed: 339 additions & 638 deletions

extensions/browser/src/browser/chrome.internal.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ vi.mock("openclaw/plugin-sdk/ssrf-runtime-internal", () => ({
3030
registerManagedProxyBrowserCdpBypass: registerManagedProxyBrowserCdpBypassMock,
3131
}));
3232

33-
const ensurePortAvailableMock = vi.hoisted(() => vi.fn(async () => {}));
33+
const ensurePortAvailableMock = vi.hoisted(() =>
34+
vi.fn<(port: number, host?: string) => Promise<void>>(async () => {}),
35+
);
3436

3537
vi.mock("../infra/ports.js", () => ({
3638
ensurePortAvailable: ensurePortAvailableMock,

src/agents/embedded-agent-runner.run-embedded-agent.auth-profile-rotation.e2e.test.ts

Lines changed: 4 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ import type { OpenClawConfig } from "../config/config.js";
88
import { redactIdentifier } from "../logging/redact-identifier.js";
99
import type { AuthProfileFailureReason } from "./auth-profiles.js";
1010
import { ensureAuthProfileStore, saveAuthProfileStore } from "./auth-profiles/store.js";
11-
import { buildAttemptReplayMetadata } from "./embedded-agent-runner/run/incomplete-turn.js";
1211
import type { EmbeddedRunAttemptResult } from "./embedded-agent-runner/run/types.js";
12+
import {
13+
buildEmbeddedRunnerAssistant as buildAssistant,
14+
makeEmbeddedRunnerAttempt as makeAttempt,
15+
} from "./test-helpers/embedded-agent-runner-e2e-fixtures.js";
1316
import {
1417
installEmbeddedRunnerBackoffE2eMocks,
1518
installEmbeddedRunnerBaseE2eMocks,
@@ -141,69 +144,6 @@ afterEach(() => {
141144
resetLoggerFn();
142145
});
143146

144-
const baseUsage = {
145-
input: 0,
146-
output: 0,
147-
cacheRead: 0,
148-
cacheWrite: 0,
149-
totalTokens: 0,
150-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
151-
};
152-
153-
const buildAssistant = (overrides: Partial<AssistantMessage>): AssistantMessage => ({
154-
role: "assistant",
155-
content: [],
156-
api: "openai-responses",
157-
provider: "openai",
158-
model: "mock-1",
159-
usage: baseUsage,
160-
stopReason: "stop",
161-
timestamp: Date.now(),
162-
...overrides,
163-
});
164-
165-
const makeAttempt = (overrides: Partial<EmbeddedRunAttemptResult>): EmbeddedRunAttemptResult => {
166-
const toolMetas = overrides.toolMetas ?? [];
167-
const didSendViaMessagingTool = overrides.didSendViaMessagingTool ?? false;
168-
const messagingToolSentTexts = overrides.messagingToolSentTexts ?? [];
169-
const messagingToolSentMediaUrls = overrides.messagingToolSentMediaUrls ?? [];
170-
const messagingToolSentTargets = overrides.messagingToolSentTargets ?? [];
171-
const successfulCronAdds = overrides.successfulCronAdds;
172-
return {
173-
aborted: false,
174-
externalAbort: false,
175-
timedOut: false,
176-
idleTimedOut: false,
177-
timedOutDuringCompaction: false,
178-
timedOutDuringToolExecution: false,
179-
promptError: null,
180-
promptErrorSource: null,
181-
sessionIdUsed: "session:test",
182-
systemPromptReport: undefined,
183-
messagesSnapshot: [],
184-
assistantTexts: [],
185-
toolMetas,
186-
lastAssistant: undefined,
187-
replayMetadata:
188-
overrides.replayMetadata ??
189-
buildAttemptReplayMetadata({
190-
toolMetas,
191-
didSendViaMessagingTool,
192-
messagingToolSentTexts,
193-
messagingToolSentMediaUrls,
194-
messagingToolSentTargets,
195-
successfulCronAdds,
196-
}),
197-
didSendViaMessagingTool,
198-
messagingToolSentTexts,
199-
messagingToolSentMediaUrls,
200-
messagingToolSentTargets,
201-
cloudCodeAssistFormatError: false,
202-
itemLifecycle: { startedCount: 0, completedCount: 0, activeCount: 0 },
203-
...overrides,
204-
};
205-
};
206-
207147
const makeConfig = (opts?: {
208148
fallbacks?: string[];
209149
apiKey?: string;

src/config/plugin-auto-enable.core.test.ts

Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@ import path from "node:path";
44
import { afterAll, afterEach, describe, expect, it, vi } from "vitest";
55
import { setCurrentPluginMetadataSnapshot } from "../plugins/current-plugin-metadata-snapshot.js";
66
import type { PluginCandidate, PluginDiscoveryResult } from "../plugins/discovery.js";
7-
import { resolveInstalledPluginIndexPolicyHash } from "../plugins/installed-plugin-index-policy.js";
8-
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
9-
import type { PluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
107
import {
118
applyPluginAutoEnable,
129
detectPluginAutoEnableCandidates,
1310
materializePluginAutoEnableCandidates,
1411
resolvePluginAutoEnableCandidateReason,
1512
} from "./plugin-auto-enable.js";
1613
import {
14+
createPluginMetadataSnapshot,
1715
makeIsolatedEnv,
1816
makeRegistry,
1917
resetPluginAutoEnableTestState,
@@ -81,53 +79,6 @@ function makeBundledChannelCandidate(params: {
8179
};
8280
}
8381

84-
function createPluginMetadataSnapshot(params: {
85-
config?: OpenClawConfig;
86-
manifestRegistry: PluginManifestRegistry;
87-
workspaceDir?: string;
88-
}): PluginMetadataSnapshot {
89-
const policyHash = resolveInstalledPluginIndexPolicyHash(params.config);
90-
return {
91-
policyHash,
92-
...(params.workspaceDir ? { workspaceDir: params.workspaceDir } : {}),
93-
index: {
94-
version: 1,
95-
hostContractVersion: "test",
96-
compatRegistryVersion: "test",
97-
migrationVersion: 1,
98-
policyHash,
99-
generatedAtMs: 1,
100-
installRecords: {},
101-
plugins: [],
102-
diagnostics: [],
103-
},
104-
registryDiagnostics: [],
105-
manifestRegistry: params.manifestRegistry,
106-
plugins: params.manifestRegistry.plugins,
107-
diagnostics: params.manifestRegistry.diagnostics,
108-
byPluginId: new Map(params.manifestRegistry.plugins.map((plugin) => [plugin.id, plugin])),
109-
normalizePluginId: (pluginId) => pluginId,
110-
owners: {
111-
channels: new Map(),
112-
channelConfigs: new Map(),
113-
providers: new Map(),
114-
modelCatalogProviders: new Map(),
115-
cliBackends: new Map(),
116-
setupProviders: new Map(),
117-
commandAliases: new Map(),
118-
contracts: new Map(),
119-
},
120-
metrics: {
121-
registrySnapshotMs: 0,
122-
manifestRegistryMs: 0,
123-
ownerMapsMs: 0,
124-
totalMs: 0,
125-
indexPluginCount: 0,
126-
manifestPluginCount: params.manifestRegistry.plugins.length,
127-
},
128-
};
129-
}
130-
13182
afterAll(() => {
13283
resetPluginAutoEnableTestState();
13384
});

src/config/plugin-auto-enable.test-helpers.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
// Provides fixtures for plugin auto-enable config tests.
22
import path from "node:path";
33
import { clearCurrentPluginMetadataSnapshot } from "../plugins/current-plugin-metadata-snapshot.js";
4+
import { resolveInstalledPluginIndexPolicyHash } from "../plugins/installed-plugin-index-policy.js";
45
import type { PluginManifestRegistry } from "../plugins/manifest-registry.js";
6+
import type { PluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js";
57
import type { PluginOrigin } from "../plugins/plugin-origin.types.js";
68
import { clearPluginSetupRegistryCache } from "../plugins/setup-registry.js";
79
import { cleanupTrackedTempDirs, makeTrackedTempDir } from "../plugins/test-helpers/fs-fixtures.js";
10+
import type { OpenClawConfig } from "./types.openclaw.js";
811

912
const tempDirs: string[] = [];
1013

@@ -71,6 +74,53 @@ export function makeRegistry(
7174
};
7275
}
7376

77+
export function createPluginMetadataSnapshot(params: {
78+
config?: OpenClawConfig;
79+
manifestRegistry: PluginManifestRegistry;
80+
workspaceDir?: string;
81+
}): PluginMetadataSnapshot {
82+
const policyHash = resolveInstalledPluginIndexPolicyHash(params.config);
83+
return {
84+
policyHash,
85+
...(params.workspaceDir ? { workspaceDir: params.workspaceDir } : {}),
86+
index: {
87+
version: 1,
88+
hostContractVersion: "test",
89+
compatRegistryVersion: "test",
90+
migrationVersion: 1,
91+
policyHash,
92+
generatedAtMs: 1,
93+
installRecords: {},
94+
plugins: [],
95+
diagnostics: [],
96+
},
97+
registryDiagnostics: [],
98+
manifestRegistry: params.manifestRegistry,
99+
plugins: params.manifestRegistry.plugins,
100+
diagnostics: params.manifestRegistry.diagnostics,
101+
byPluginId: new Map(params.manifestRegistry.plugins.map((plugin) => [plugin.id, plugin])),
102+
normalizePluginId: (pluginId) => pluginId,
103+
owners: {
104+
channels: new Map(),
105+
channelConfigs: new Map(),
106+
providers: new Map(),
107+
modelCatalogProviders: new Map(),
108+
cliBackends: new Map(),
109+
setupProviders: new Map(),
110+
commandAliases: new Map(),
111+
contracts: new Map(),
112+
},
113+
metrics: {
114+
registrySnapshotMs: 0,
115+
manifestRegistryMs: 0,
116+
ownerMapsMs: 0,
117+
totalMs: 0,
118+
indexPluginCount: 0,
119+
manifestPluginCount: params.manifestRegistry.plugins.length,
120+
},
121+
};
122+
}
123+
74124
export function makeApnChannelConfig() {
75125
return { channels: { apn: { someKey: "value" } } };
76126
}

src/cron/service.test-harness.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export async function withCronServiceForTest(
176176

177177
export function createRunningCronServiceState(params: {
178178
storePath: string;
179-
log: ReturnType<typeof createNoopLogger>;
179+
log: CronServiceDeps["log"];
180180
nowMs: () => number;
181181
jobs: CronJob[];
182182
}) {

src/gateway/call.test.ts

Lines changed: 44 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,48 @@ let closeReason = "";
107107
let helloMethods: string[] | undefined = ["health", "secrets.resolve"];
108108
let connectError: Error | null = null;
109109

110+
function startStubGatewayClient() {
111+
startCalls += 1;
112+
if (startMode === "hello") {
113+
void lastClientOptions?.onHelloOk?.({
114+
features: {
115+
methods: helloMethods,
116+
},
117+
});
118+
} else if (startMode === "startup-retry-then-hello") {
119+
void lastClientOptions?.onHelloOk?.({
120+
features: {
121+
methods: helloMethods,
122+
},
123+
});
124+
} else if (startMode === "clean-prehello-close-then-hello") {
125+
lastClientOptions?.onClose?.(1000, "", {
126+
phase: "pre-hello",
127+
transientPreHelloCleanClose: true,
128+
});
129+
void lastClientOptions?.onHelloOk?.({
130+
features: {
131+
methods: helloMethods,
132+
},
133+
});
134+
} else if (startMode === "repeated-clean-prehello-close") {
135+
lastClientOptions?.onClose?.(1000, "", {
136+
phase: "pre-hello",
137+
transientPreHelloCleanClose: true,
138+
});
139+
lastClientOptions?.onClose?.(1000, "", {
140+
phase: "pre-hello",
141+
transientPreHelloCleanClose: true,
142+
});
143+
} else if (startMode === "connect-error") {
144+
lastClientOptions?.onConnectError?.(
145+
connectError ?? connectAssemblyErrorState.create("device private key invalid"),
146+
);
147+
} else if (startMode === "close") {
148+
lastClientOptions?.onClose?.(closeCode, closeReason);
149+
}
150+
}
151+
110152
vi.mock("./client.js", () => ({
111153
describeGatewayCloseCode: (code: number) => {
112154
if (code === 1000) {
@@ -144,45 +186,7 @@ vi.mock("./client.js", () => ({
144186
return { ok: true };
145187
}
146188
start() {
147-
startCalls += 1;
148-
if (startMode === "hello") {
149-
void lastClientOptions?.onHelloOk?.({
150-
features: {
151-
methods: helloMethods,
152-
},
153-
});
154-
} else if (startMode === "startup-retry-then-hello") {
155-
void lastClientOptions?.onHelloOk?.({
156-
features: {
157-
methods: helloMethods,
158-
},
159-
});
160-
} else if (startMode === "clean-prehello-close-then-hello") {
161-
lastClientOptions?.onClose?.(1000, "", {
162-
phase: "pre-hello",
163-
transientPreHelloCleanClose: true,
164-
});
165-
void lastClientOptions?.onHelloOk?.({
166-
features: {
167-
methods: helloMethods,
168-
},
169-
});
170-
} else if (startMode === "repeated-clean-prehello-close") {
171-
lastClientOptions?.onClose?.(1000, "", {
172-
phase: "pre-hello",
173-
transientPreHelloCleanClose: true,
174-
});
175-
lastClientOptions?.onClose?.(1000, "", {
176-
phase: "pre-hello",
177-
transientPreHelloCleanClose: true,
178-
});
179-
} else if (startMode === "connect-error") {
180-
lastClientOptions?.onConnectError?.(
181-
connectError ?? connectAssemblyErrorState.create("device private key invalid"),
182-
);
183-
} else if (startMode === "close") {
184-
lastClientOptions?.onClose?.(closeCode, closeReason);
185-
}
189+
startStubGatewayClient();
186190
}
187191
stop() {}
188192
},
@@ -240,45 +244,7 @@ class StubGatewayClient {
240244
return { ok: true };
241245
}
242246
start() {
243-
startCalls += 1;
244-
if (startMode === "hello") {
245-
void lastClientOptions?.onHelloOk?.({
246-
features: {
247-
methods: helloMethods,
248-
},
249-
});
250-
} else if (startMode === "startup-retry-then-hello") {
251-
void lastClientOptions?.onHelloOk?.({
252-
features: {
253-
methods: helloMethods,
254-
},
255-
});
256-
} else if (startMode === "clean-prehello-close-then-hello") {
257-
lastClientOptions?.onClose?.(1000, "", {
258-
phase: "pre-hello",
259-
transientPreHelloCleanClose: true,
260-
});
261-
void lastClientOptions?.onHelloOk?.({
262-
features: {
263-
methods: helloMethods,
264-
},
265-
});
266-
} else if (startMode === "repeated-clean-prehello-close") {
267-
lastClientOptions?.onClose?.(1000, "", {
268-
phase: "pre-hello",
269-
transientPreHelloCleanClose: true,
270-
});
271-
lastClientOptions?.onClose?.(1000, "", {
272-
phase: "pre-hello",
273-
transientPreHelloCleanClose: true,
274-
});
275-
} else if (startMode === "connect-error") {
276-
lastClientOptions?.onConnectError?.(
277-
connectError ?? connectAssemblyErrorState.create("device private key invalid"),
278-
);
279-
} else if (startMode === "close") {
280-
lastClientOptions?.onClose?.(closeCode, closeReason);
281-
}
247+
startStubGatewayClient();
282248
}
283249
stop() {}
284250
async stopAndWait() {}

src/gateway/server-methods/update.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,9 @@ describe("update.run post-core plugin finalize", () => {
806806
detectRespawnSupervisorMock.mockReturnValueOnce("launchd");
807807
mockGlobalInstallSurface();
808808

809-
await captureUpdateRunPayload();
809+
await withProcessEnv({ OPENCLAW_LAUNCHD_LABEL: "ai.openclaw.gateway" }, () =>
810+
captureUpdateRunPayload(),
811+
);
810812

811813
expect(runGatewayUpdateMock).not.toHaveBeenCalled();
812814
expect(runPostCoreFinalizeAfterGatewayUpdateMock).not.toHaveBeenCalled();

0 commit comments

Comments
 (0)