mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-23 14:45:46 +00:00
test: streamline runtime wrapper test reloads
This commit is contained in:
@@ -30,7 +30,6 @@ describe("normalizeChatType", () => {
|
||||
describe("WA_WEB_AUTH_DIR", () => {
|
||||
afterEach(() => {
|
||||
vi.doUnmock("../plugins/runtime/runtime-whatsapp-boundary.js");
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
it("resolves lazily and caches across the legacy and channels/web entrypoints", async () => {
|
||||
|
||||
@@ -3,7 +3,6 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
afterEach(() => {
|
||||
vi.doUnmock("../../plugins/discovery.js");
|
||||
vi.doUnmock("../../plugins/manifest-registry.js");
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
describe("bundled channel entry shape guards", () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
describe("bundled channel config runtime", () => {
|
||||
beforeEach(() => {
|
||||
@@ -6,11 +6,6 @@ describe("bundled channel config runtime", () => {
|
||||
vi.doUnmock("../channels/plugins/bundled.js");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.resetModules();
|
||||
vi.doUnmock("../channels/plugins/bundled.js");
|
||||
});
|
||||
|
||||
it("tolerates an unavailable bundled channel list during import", async () => {
|
||||
vi.doMock("../channels/plugins/bundled.js", () => ({
|
||||
listBundledChannelPlugins: () => undefined,
|
||||
@@ -23,7 +18,6 @@ describe("bundled channel config runtime", () => {
|
||||
});
|
||||
|
||||
it("falls back to static channel schemas when bundled plugin access hits a TDZ-style ReferenceError", async () => {
|
||||
vi.resetModules();
|
||||
vi.doMock("../channels/plugins/bundled.js", () => {
|
||||
return {
|
||||
listBundledChannelPlugins() {
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
describe("session store module imports", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
it("does not load archive runtime on module import", async () => {
|
||||
vi.resetModules();
|
||||
const archiveRuntimeLoads = vi.fn();
|
||||
vi.doMock("../gateway/session-archive.runtime.js", async (importOriginal) => {
|
||||
archiveRuntimeLoads();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import process from "node:process";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { importFreshModule } from "../test/helpers/import-fresh.js";
|
||||
|
||||
const applyCliProfileEnvMock = vi.hoisted(() => vi.fn());
|
||||
const attachChildProcessBridgeMock = vi.hoisted(() => vi.fn());
|
||||
@@ -67,13 +68,19 @@ vi.mock("./version.js", () => ({
|
||||
VERSION: "9.9.9-test",
|
||||
}));
|
||||
|
||||
async function importEntry(scope: string) {
|
||||
return await importFreshModule<typeof import("./entry.js")>(
|
||||
import.meta.url,
|
||||
`./entry.js?scope=${scope}`,
|
||||
);
|
||||
}
|
||||
|
||||
describe("entry root version fast path", () => {
|
||||
let originalArgv: string[];
|
||||
let originalGatewayToken: string | undefined;
|
||||
let exitSpy: ReturnType<typeof vi.spyOn>;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
vi.clearAllMocks();
|
||||
originalArgv = [...process.argv];
|
||||
originalGatewayToken = process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
@@ -97,7 +104,7 @@ describe("entry root version fast path", () => {
|
||||
it("prints commit-tagged version output when commit metadata is available", async () => {
|
||||
const logSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
||||
|
||||
await import("./entry.js");
|
||||
await importEntry("commit-tagged");
|
||||
await vi.waitFor(() => {
|
||||
expect(logSpy).toHaveBeenCalledWith("OpenClaw 9.9.9-test (abc1234)");
|
||||
expect(exitSpy).toHaveBeenCalledWith(0);
|
||||
@@ -110,7 +117,7 @@ describe("entry root version fast path", () => {
|
||||
resolveCommitHashMock.mockReturnValueOnce(null);
|
||||
const logSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
||||
|
||||
await import("./entry.js");
|
||||
await importEntry("plain-version");
|
||||
await vi.waitFor(() => {
|
||||
expect(logSpy).toHaveBeenCalledWith("OpenClaw 9.9.9-test");
|
||||
expect(exitSpy).toHaveBeenCalledWith(0);
|
||||
@@ -123,7 +130,7 @@ describe("entry root version fast path", () => {
|
||||
resolveCliContainerTargetMock.mockReturnValue("demo");
|
||||
const logSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
||||
|
||||
await import("./entry.js");
|
||||
await importEntry("container-target");
|
||||
await vi.waitFor(() => {
|
||||
expect(runCliMock).toHaveBeenCalledWith(["node", "openclaw", "--version"]);
|
||||
});
|
||||
@@ -138,7 +145,7 @@ describe("entry root version fast path", () => {
|
||||
process.env.OPENCLAW_GATEWAY_TOKEN = "demo-token";
|
||||
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
|
||||
await import("./entry.js");
|
||||
await importEntry("gateway-override");
|
||||
await vi.waitFor(() => {
|
||||
expect(runCliMock).toHaveBeenCalledWith(["node", "openclaw", "--version"]);
|
||||
});
|
||||
|
||||
@@ -26,7 +26,6 @@ let enabledServer: Awaited<ReturnType<typeof startServer>>;
|
||||
let enabledPort: number;
|
||||
|
||||
beforeAll(async () => {
|
||||
vi.resetModules();
|
||||
({ clearMemoryEmbeddingProviders, registerMemoryEmbeddingProvider } =
|
||||
await import("../plugins/memory-embedding-providers.js"));
|
||||
createEmbeddingProviderMock = vi.fn(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { withEnv } from "../test-utils/env.js";
|
||||
|
||||
const loggerMocks = vi.hoisted(() => ({
|
||||
@@ -18,10 +18,13 @@ let logAcceptedEnvOption: EnvModule["logAcceptedEnvOption"];
|
||||
let normalizeEnv: EnvModule["normalizeEnv"];
|
||||
let normalizeZaiEnv: EnvModule["normalizeZaiEnv"];
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeAll(async () => {
|
||||
vi.resetModules();
|
||||
({ isTruthyEnvValue, logAcceptedEnvOption, normalizeEnv, normalizeZaiEnv } =
|
||||
await import("./env.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
loggerMocks.info.mockClear();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { GatewayClient } from "../gateway/client.js";
|
||||
import type { PluginApprovalRequest, PluginApprovalResolved } from "./plugin-approvals.js";
|
||||
|
||||
@@ -50,8 +50,7 @@ afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
beforeAll(async () => {
|
||||
({ createExecApprovalChannelRuntime } = await import("./exec-approval-channel-runtime.js"));
|
||||
});
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
withRealpathSymlinkRebindRace,
|
||||
} from "../test-utils/symlink-rebind-race.js";
|
||||
import { createTrackedTempDirs } from "../test-utils/tracked-temp-dirs.js";
|
||||
import * as pinnedPathHelperModule from "./fs-pinned-path-helper.js";
|
||||
import {
|
||||
appendFileWithinRoot,
|
||||
copyFileWithinRoot,
|
||||
@@ -349,65 +350,36 @@ describe("fs-safe", () => {
|
||||
it.runIf(process.platform !== "win32")(
|
||||
"falls back to legacy remove when the pinned helper cannot spawn",
|
||||
async () => {
|
||||
vi.resetModules();
|
||||
vi.doMock("./fs-pinned-path-helper.js", async () => {
|
||||
const actual = await vi.importActual<typeof import("./fs-pinned-path-helper.js")>(
|
||||
"./fs-pinned-path-helper.js",
|
||||
);
|
||||
const error = new Error("spawn missing python ENOENT") as NodeJS.ErrnoException;
|
||||
error.code = "ENOENT";
|
||||
error.syscall = "spawn python3";
|
||||
return {
|
||||
...actual,
|
||||
runPinnedPathHelper: vi.fn(async () => {
|
||||
throw error;
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
const { removePathWithinRoot: removePathWithinRootWithFallback } =
|
||||
await import("./fs-safe.js");
|
||||
const error = new Error("spawn missing python ENOENT") as NodeJS.ErrnoException;
|
||||
error.code = "ENOENT";
|
||||
error.syscall = "spawn python3";
|
||||
vi.spyOn(pinnedPathHelperModule, "runPinnedPathHelper").mockRejectedValue(error);
|
||||
|
||||
const root = await tempDirs.make("openclaw-fs-safe-root-");
|
||||
const targetPath = path.join(root, "nested", "out.txt");
|
||||
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
||||
await fs.writeFile(targetPath, "hello");
|
||||
|
||||
await removePathWithinRootWithFallback({
|
||||
await removePathWithinRoot({
|
||||
rootDir: root,
|
||||
relativePath: "nested/out.txt",
|
||||
});
|
||||
|
||||
await expect(fs.stat(targetPath)).rejects.toMatchObject({ code: "ENOENT" });
|
||||
vi.doUnmock("./fs-pinned-path-helper.js");
|
||||
vi.resetModules();
|
||||
},
|
||||
);
|
||||
|
||||
it.runIf(process.platform !== "win32")(
|
||||
"falls back to legacy mkdir when the pinned helper cannot spawn",
|
||||
async () => {
|
||||
vi.resetModules();
|
||||
vi.doMock("./fs-pinned-path-helper.js", async () => {
|
||||
const actual = await vi.importActual<typeof import("./fs-pinned-path-helper.js")>(
|
||||
"./fs-pinned-path-helper.js",
|
||||
);
|
||||
const error = new Error("spawn missing python ENOENT") as NodeJS.ErrnoException;
|
||||
error.code = "ENOENT";
|
||||
error.syscall = "spawn python3";
|
||||
return {
|
||||
...actual,
|
||||
runPinnedPathHelper: vi.fn(async () => {
|
||||
throw error;
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
const { mkdirPathWithinRoot: mkdirPathWithinRootWithFallback } = await import("./fs-safe.js");
|
||||
const error = new Error("spawn missing python ENOENT") as NodeJS.ErrnoException;
|
||||
error.code = "ENOENT";
|
||||
error.syscall = "spawn python3";
|
||||
vi.spyOn(pinnedPathHelperModule, "runPinnedPathHelper").mockRejectedValue(error);
|
||||
|
||||
const root = await tempDirs.make("openclaw-fs-safe-root-");
|
||||
|
||||
await mkdirPathWithinRootWithFallback({
|
||||
await mkdirPathWithinRoot({
|
||||
rootDir: root,
|
||||
relativePath: "nested/deeper",
|
||||
});
|
||||
@@ -415,8 +387,6 @@ describe("fs-safe", () => {
|
||||
await expect(fs.stat(path.join(root, "nested", "deeper"))).resolves.toMatchObject({
|
||||
isDirectory: expect.any(Function),
|
||||
});
|
||||
vi.doUnmock("./fs-pinned-path-helper.js");
|
||||
vi.resetModules();
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -209,7 +209,6 @@ function expectSuccessfulWhatsAppInternalHookPayload(
|
||||
|
||||
describe("deliverOutboundPayloads", () => {
|
||||
beforeAll(async () => {
|
||||
vi.resetModules();
|
||||
({ deliverOutboundPayloads, normalizeOutboundPayloads } = await import("./deliver.js"));
|
||||
});
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ describe("deliverSessionMaintenanceWarning", () => {
|
||||
let prevNodeEnv: string | undefined;
|
||||
|
||||
beforeAll(async () => {
|
||||
vi.resetModules();
|
||||
vi.doMock("../agents/agent-scope.js", () => ({
|
||||
resolveSessionAgentId: mocks.resolveSessionAgentId,
|
||||
}));
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import os from "node:os";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { importFreshModule } from "../../test/helpers/import-fresh.js";
|
||||
import { withEnvAsync } from "../test-utils/env.js";
|
||||
import { VERSION as runtimeVersion } from "../version.js";
|
||||
|
||||
vi.unmock("../version.js");
|
||||
|
||||
@@ -16,8 +18,10 @@ async function withPresenceModule<T>(
|
||||
...env,
|
||||
},
|
||||
async () => {
|
||||
vi.resetModules();
|
||||
const module = await import("./system-presence.js");
|
||||
const module = await importFreshModule<typeof import("./system-presence.js")>(
|
||||
import.meta.url,
|
||||
`./system-presence.js?scope=${JSON.stringify(env)}`,
|
||||
);
|
||||
return await run(module);
|
||||
},
|
||||
);
|
||||
@@ -46,7 +50,7 @@ describe("system-presence version fallback", () => {
|
||||
OPENCLAW_SERVICE_VERSION: "2.4.6-service",
|
||||
npm_package_version: "1.0.0-package",
|
||||
},
|
||||
async () => (await import("../version.js")).VERSION,
|
||||
runtimeVersion,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -68,7 +72,7 @@ describe("system-presence version fallback", () => {
|
||||
OPENCLAW_SERVICE_VERSION: "2.4.6-service",
|
||||
npm_package_version: "1.0.0-package",
|
||||
},
|
||||
async () => (await import("../version.js")).VERSION,
|
||||
runtimeVersion,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -79,7 +83,7 @@ describe("system-presence version fallback", () => {
|
||||
OPENCLAW_SERVICE_VERSION: "\t",
|
||||
npm_package_version: "1.0.0-package",
|
||||
},
|
||||
async () => (await import("../version.js")).VERSION,
|
||||
runtimeVersion,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -90,7 +94,7 @@ describe("system-presence version fallback", () => {
|
||||
OPENCLAW_SERVICE_VERSION: "\t",
|
||||
npm_package_version: "1.0.0-package",
|
||||
},
|
||||
async () => (await import("../version.js")).VERSION,
|
||||
runtimeVersion,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -100,8 +104,10 @@ describe("system-presence version fallback", () => {
|
||||
vi.spyOn(os, "networkInterfaces").mockImplementation(() => {
|
||||
throw new Error("uv_interface_addresses failed");
|
||||
});
|
||||
vi.resetModules();
|
||||
const module = await import("./system-presence.js");
|
||||
const module = await importFreshModule<typeof import("./system-presence.js")>(
|
||||
import.meta.url,
|
||||
"./system-presence.js?scope=hostname-fallback",
|
||||
);
|
||||
const selfEntry = module.listSystemPresence().find((entry) => entry.reason === "self");
|
||||
expect(selfEntry?.host).toBe("test-host");
|
||||
expect(selfEntry?.ip).toBe("test-host");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from "node:fs";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { importFreshModule } from "../../test/helpers/import-fresh.js";
|
||||
import { onDiagnosticEvent, resetDiagnosticEventsForTest } from "../infra/diagnostic-events.js";
|
||||
import {
|
||||
diagnosticSessionStates,
|
||||
@@ -72,11 +73,13 @@ describe("logger import side effects", () => {
|
||||
|
||||
it("does not mkdir at import time", async () => {
|
||||
vi.useRealTimers();
|
||||
vi.resetModules();
|
||||
|
||||
const mkdirSpy = vi.spyOn(fs, "mkdirSync");
|
||||
|
||||
await import("./logger.js");
|
||||
await importFreshModule<typeof import("./logger.js")>(
|
||||
import.meta.url,
|
||||
"./logger.js?scope=diagnostic-mkdir",
|
||||
);
|
||||
|
||||
expect(mkdirSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { importFreshModule } from "../../test/helpers/import-fresh.js";
|
||||
|
||||
type LoggerModule = typeof import("./logger.js");
|
||||
|
||||
@@ -12,7 +13,6 @@ async function importBrowserSafeLogger(params?: {
|
||||
module: LoggerModule;
|
||||
resolvePreferredOpenClawTmpDir: ReturnType<typeof vi.fn>;
|
||||
}> {
|
||||
vi.resetModules();
|
||||
const resolvePreferredOpenClawTmpDir =
|
||||
params?.resolvePreferredOpenClawTmpDir ??
|
||||
vi.fn(() => {
|
||||
@@ -34,13 +34,15 @@ async function importBrowserSafeLogger(params?: {
|
||||
value: undefined,
|
||||
});
|
||||
|
||||
const module = await import("./logger.js");
|
||||
const module = await importFreshModule<LoggerModule>(
|
||||
import.meta.url,
|
||||
"./logger.js?scope=browser-safe",
|
||||
);
|
||||
return { module, resolvePreferredOpenClawTmpDir };
|
||||
}
|
||||
|
||||
describe("logging/logger browser-safe import", () => {
|
||||
afterEach(() => {
|
||||
vi.resetModules();
|
||||
vi.doUnmock("../infra/tmp-openclaw-dir.js");
|
||||
Object.defineProperty(process, "getBuiltinModule", {
|
||||
configurable: true,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const runAudioTranscriptionMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
@@ -9,12 +9,14 @@ vi.mock("./audio-transcription-runner.js", () => ({
|
||||
let transcribeFirstAudio: typeof import("./audio-preflight.js").transcribeFirstAudio;
|
||||
|
||||
describe("transcribeFirstAudio", () => {
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
runAudioTranscriptionMock.mockReset();
|
||||
beforeAll(async () => {
|
||||
({ transcribeFirstAudio } = await import("./audio-preflight.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
runAudioTranscriptionMock.mockReset();
|
||||
});
|
||||
|
||||
it("runs audio preflight in auto mode when audio config is absent", async () => {
|
||||
runAudioTranscriptionMock.mockResolvedValueOnce({
|
||||
transcript: "voice note transcript",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { withAudioFixture, withVideoFixture } from "./runner.test-utils.js";
|
||||
import type { AudioTranscriptionRequest, VideoDescriptionRequest } from "./types.js";
|
||||
@@ -22,6 +22,7 @@ vi.mock("../infra/net/proxy-fetch.js", () => ({
|
||||
}));
|
||||
|
||||
let buildProviderRegistry: typeof import("./runner.js").buildProviderRegistry;
|
||||
let clearMediaUnderstandingBinaryCacheForTests: typeof import("./runner.js").clearMediaUnderstandingBinaryCacheForTests;
|
||||
let runCapability: typeof import("./runner.js").runCapability;
|
||||
|
||||
async function runAudioCapabilityWithFetchCapture(params: {
|
||||
@@ -75,11 +76,15 @@ async function runAudioCapabilityWithFetchCapture(params: {
|
||||
}
|
||||
|
||||
describe("runCapability proxy fetch passthrough", () => {
|
||||
beforeEach(async () => {
|
||||
beforeAll(async () => {
|
||||
({ buildProviderRegistry, clearMediaUnderstandingBinaryCacheForTests, runCapability } =
|
||||
await import("./runner.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
vi.useRealTimers();
|
||||
vi.resetModules();
|
||||
vi.clearAllMocks();
|
||||
({ buildProviderRegistry, runCapability } = await import("./runner.js"));
|
||||
clearMediaUnderstandingBinaryCacheForTests();
|
||||
});
|
||||
afterEach(() => vi.unstubAllEnvs());
|
||||
|
||||
|
||||
@@ -173,7 +173,6 @@ describe("fetchRemoteMedia", () => {
|
||||
const telegramFileUrl = `https://api.telegram.org/file/bot${telegramToken}/photos/1.jpg`;
|
||||
|
||||
beforeAll(async () => {
|
||||
vi.resetModules();
|
||||
({ fetchRemoteMedia } = await import("./fetch.js"));
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js";
|
||||
import { getImageMetadata } from "./image-ops.js";
|
||||
|
||||
describe("image-ops temp dir", () => {
|
||||
let createdTempDir = "";
|
||||
@@ -18,11 +19,9 @@ describe("image-ops temp dir", () => {
|
||||
afterEach(() => {
|
||||
delete process.env.OPENCLAW_IMAGE_BACKEND;
|
||||
vi.restoreAllMocks();
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
it("creates sips temp dirs under the secured OpenClaw tmp root", async () => {
|
||||
const { getImageMetadata } = await import("./image-ops.js");
|
||||
const secureRoot = resolvePreferredOpenClawTmpDir();
|
||||
|
||||
await getImageMetadata(Buffer.from("image"));
|
||||
|
||||
@@ -129,10 +129,14 @@ describe("plugin activation boundary", () => {
|
||||
const { isChannelConfigured, resolveEnvApiKey } = await importConfigHelpers();
|
||||
|
||||
expect(isChannelConfigured({}, "whatsapp", {})).toBe(false);
|
||||
// Anthropic Vertex auth depends on ambient ADC state on the current machine.
|
||||
expect([null, { apiKey: "gcp-vertex-credentials", source: "gcloud adc" }]).toContainEqual(
|
||||
resolveEnvApiKey("anthropic-vertex", {}),
|
||||
);
|
||||
expect(
|
||||
resolveEnvApiKey("anthropic-vertex", {
|
||||
ANTHROPIC_VERTEX_USE_GCP_METADATA: "true",
|
||||
}),
|
||||
).toEqual({
|
||||
apiKey: "gcp-vertex-credentials",
|
||||
source: "gcloud adc",
|
||||
});
|
||||
expect(loadBundledPluginPublicSurfaceModuleSync).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ async function expectGlobalRunnerState(expected: { hasRunner: boolean; registry?
|
||||
afterEach(async () => {
|
||||
const mod = await importHookRunnerGlobalModule();
|
||||
mod.resetGlobalHookRunner();
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
describe("hook-runner-global", () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
expectAugmentedCodexCatalog,
|
||||
expectCodexBuiltInSuppression,
|
||||
@@ -234,7 +234,7 @@ async function expectResolvedAsyncValues(
|
||||
}
|
||||
|
||||
describe("provider-runtime", () => {
|
||||
beforeEach(async () => {
|
||||
beforeAll(async () => {
|
||||
vi.resetModules();
|
||||
vi.doMock("./providers.js", () => ({
|
||||
resolveCatalogHookProviderPluginIds: (params: unknown) =>
|
||||
@@ -285,6 +285,9 @@ describe("provider-runtime", () => {
|
||||
validateProviderReplayTurnsWithPlugin,
|
||||
wrapProviderStreamFn,
|
||||
} = await import("./provider-runtime.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
resetProviderRuntimeHookCacheForTest();
|
||||
resolvePluginProvidersMock.mockReset();
|
||||
resolvePluginProvidersMock.mockReturnValue([]);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { PluginRuntimeGatewayRequestScope } from "./gateway-request-scope.js";
|
||||
|
||||
const TEST_SCOPE: PluginRuntimeGatewayRequestScope = {
|
||||
@@ -6,10 +6,6 @@ const TEST_SCOPE: PluginRuntimeGatewayRequestScope = {
|
||||
isWebchatConnect: (() => false) as PluginRuntimeGatewayRequestScope["isWebchatConnect"],
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
describe("gateway request scope", () => {
|
||||
async function importGatewayRequestScopeModule() {
|
||||
return await import("./gateway-request-scope.js");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
type MockRegistryToolEntry = {
|
||||
pluginId: string;
|
||||
@@ -193,8 +193,12 @@ function expectConflictingCoreNameResolution(params: {
|
||||
}
|
||||
|
||||
describe("resolvePluginTools optional tools", () => {
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
beforeAll(async () => {
|
||||
({ resolvePluginTools } = await import("./tools.js"));
|
||||
({ resetPluginRuntimeStateForTest, setActivePluginRegistry } = await import("./runtime.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
loadOpenClawPluginsMock.mockClear();
|
||||
resolveRuntimePluginRegistryMock.mockReset();
|
||||
resolveRuntimePluginRegistryMock.mockImplementation((params) =>
|
||||
@@ -205,11 +209,7 @@ describe("resolvePluginTools optional tools", () => {
|
||||
config,
|
||||
changes: [],
|
||||
}));
|
||||
({ resetPluginRuntimeStateForTest, setActivePluginRegistry } = await import("./runtime.js"));
|
||||
resetPluginRuntimeStateForTest();
|
||||
({ resolvePluginTools } = await import("./tools.js"));
|
||||
({ resetPluginRuntimeStateForTest, setActivePluginRegistry } = await import("./runtime.js"));
|
||||
resetPluginRuntimeStateForTest();
|
||||
resetPluginRuntimeStateForTest?.();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Test: before_compaction & after_compaction hook wiring
|
||||
*/
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { makeZeroUsageSnapshot } from "../agents/usage.js";
|
||||
|
||||
const hookMocks = vi.hoisted(() => ({
|
||||
@@ -17,8 +17,7 @@ describe("compaction hook wiring", () => {
|
||||
let handleAutoCompactionStart: typeof import("../agents/pi-embedded-subscribe.handlers.compaction.js").handleAutoCompactionStart;
|
||||
let handleAutoCompactionEnd: typeof import("../agents/pi-embedded-subscribe.handlers.compaction.js").handleAutoCompactionEnd;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
beforeAll(async () => {
|
||||
hookMocks.runner.hasHooks.mockClear();
|
||||
hookMocks.runner.hasHooks.mockReturnValue(false);
|
||||
hookMocks.runner.runBeforeCompaction.mockClear();
|
||||
@@ -36,6 +35,16 @@ describe("compaction hook wiring", () => {
|
||||
await import("../agents/pi-embedded-subscribe.handlers.compaction.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
hookMocks.runner.hasHooks.mockClear();
|
||||
hookMocks.runner.hasHooks.mockReturnValue(false);
|
||||
hookMocks.runner.runBeforeCompaction.mockClear();
|
||||
hookMocks.runner.runBeforeCompaction.mockResolvedValue(undefined);
|
||||
hookMocks.runner.runAfterCompaction.mockClear();
|
||||
hookMocks.runner.runAfterCompaction.mockResolvedValue(undefined);
|
||||
hookMocks.emitAgentEvent.mockClear();
|
||||
});
|
||||
|
||||
function createCompactionEndCtx(params: {
|
||||
runId: string;
|
||||
messages?: unknown[];
|
||||
|
||||
@@ -261,7 +261,6 @@ function expectInactiveWebFetchProviderSecretRef(params: {
|
||||
|
||||
describe("runtime web tools resolution", () => {
|
||||
beforeAll(async () => {
|
||||
vi.resetModules();
|
||||
bundledWebSearchProviders = await import("../plugins/web-search-providers.js");
|
||||
runtimeWebSearchProviders = await import("../plugins/web-search-providers.runtime.js");
|
||||
bundledWebFetchProviders = await import("../plugins/web-fetch-providers.js");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { AuthProfileStore } from "../agents/auth-profiles.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { PluginWebSearchProviderEntry } from "../plugins/types.js";
|
||||
@@ -242,15 +242,18 @@ function buildAuthStoreForTarget(entry: SecretRegistryEntry, envId: string): Aut
|
||||
}
|
||||
|
||||
describe("secrets runtime target coverage", () => {
|
||||
beforeAll(async () => {
|
||||
({ clearSecretsRuntimeSnapshot, prepareSecretsRuntimeSnapshot } = await import("./runtime.js"));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
clearSecretsRuntimeSnapshot();
|
||||
resolveBundledPluginWebSearchProvidersMock.mockReset();
|
||||
resolvePluginWebSearchProvidersMock.mockReset();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
({ clearSecretsRuntimeSnapshot, prepareSecretsRuntimeSnapshot } = await import("./runtime.js"));
|
||||
beforeEach(() => {
|
||||
clearSecretsRuntimeSnapshot();
|
||||
});
|
||||
|
||||
it("handles every openclaw.json registry target when configured as active", async () => {
|
||||
|
||||
@@ -85,7 +85,6 @@ describe("light background detection", () => {
|
||||
|
||||
afterEach(() => {
|
||||
process.env = { ...originalEnv };
|
||||
vi.resetModules();
|
||||
});
|
||||
|
||||
async function importThemeWithEnv(env: Record<string, string | undefined>) {
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createStorageMock } from "../../test-helpers/storage.ts";
|
||||
import * as translate from "../lib/translate.ts";
|
||||
import { pt_BR } from "../locales/pt-BR.ts";
|
||||
import { zh_CN } from "../locales/zh-CN.ts";
|
||||
import { zh_TW } from "../locales/zh-TW.ts";
|
||||
|
||||
type TranslateModule = typeof import("../lib/translate.ts");
|
||||
|
||||
describe("i18n", () => {
|
||||
let translate: TranslateModule;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
vi.stubGlobal("localStorage", createStorageMock());
|
||||
vi.stubGlobal("navigator", { language: "en-US" } as Navigator);
|
||||
translate = await import("../lib/translate.ts");
|
||||
localStorage.clear();
|
||||
// Reset to English
|
||||
await translate.i18n.setLocale("en");
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* @vitest-environment jsdom */
|
||||
|
||||
import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ChatHost } from "./app-chat.ts";
|
||||
|
||||
const { setLastActiveSessionKeyMock } = vi.hoisted(() => ({
|
||||
@@ -15,8 +15,10 @@ let handleSendChat: typeof import("./app-chat.ts").handleSendChat;
|
||||
let refreshChatAvatar: typeof import("./app-chat.ts").refreshChatAvatar;
|
||||
let clearPendingQueueItemsForRun: typeof import("./app-chat.ts").clearPendingQueueItemsForRun;
|
||||
|
||||
async function loadChatHelpers(): Promise<void> {
|
||||
vi.resetModules();
|
||||
async function loadChatHelpers(params?: { reload?: boolean }): Promise<void> {
|
||||
if (params?.reload) {
|
||||
vi.resetModules();
|
||||
}
|
||||
({ handleSendChat, refreshChatAvatar, clearPendingQueueItemsForRun } =
|
||||
await import("./app-chat.ts"));
|
||||
}
|
||||
@@ -47,7 +49,7 @@ function makeHost(overrides?: Partial<ChatHost>): ChatHost {
|
||||
}
|
||||
|
||||
describe("refreshChatAvatar", () => {
|
||||
beforeEach(async () => {
|
||||
beforeAll(async () => {
|
||||
await loadChatHelpers();
|
||||
});
|
||||
|
||||
@@ -91,11 +93,14 @@ describe("refreshChatAvatar", () => {
|
||||
});
|
||||
|
||||
describe("handleSendChat", () => {
|
||||
beforeEach(async () => {
|
||||
setLastActiveSessionKeyMock.mockReset();
|
||||
beforeAll(async () => {
|
||||
await loadChatHelpers();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
setLastActiveSessionKeyMock.mockReset();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
vi.doUnmock("./chat/slash-command-executor.ts");
|
||||
@@ -173,7 +178,7 @@ describe("handleSendChat", () => {
|
||||
})),
|
||||
};
|
||||
});
|
||||
await loadChatHelpers();
|
||||
await loadChatHelpers({ reload: true });
|
||||
|
||||
const host = makeHost({
|
||||
client: { request: vi.fn() } as unknown as ChatHost["client"],
|
||||
|
||||
@@ -1,24 +1,9 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createStorageMock } from "../test-helpers/storage.ts";
|
||||
|
||||
type NavigationModule = typeof import("./navigation.ts");
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { TAB_GROUPS, tabFromPath } from "./navigation.ts";
|
||||
|
||||
describe("TAB_GROUPS", () => {
|
||||
let navigation: NavigationModule;
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.resetModules();
|
||||
vi.stubGlobal("localStorage", createStorageMock());
|
||||
vi.stubGlobal("navigator", { language: "en-US" } as Navigator);
|
||||
navigation = await import("./navigation.ts");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it("does not expose unfinished settings slices in the sidebar", () => {
|
||||
const settings = navigation.TAB_GROUPS.find((group) => group.label === "settings");
|
||||
const settings = TAB_GROUPS.find((group) => group.label === "settings");
|
||||
expect(settings?.tabs).toEqual([
|
||||
"config",
|
||||
"communications",
|
||||
@@ -32,11 +17,11 @@ describe("TAB_GROUPS", () => {
|
||||
});
|
||||
|
||||
it("routes every published settings slice", () => {
|
||||
expect(navigation.tabFromPath("/communications")).toBe("communications");
|
||||
expect(navigation.tabFromPath("/appearance")).toBe("appearance");
|
||||
expect(navigation.tabFromPath("/automation")).toBe("automation");
|
||||
expect(navigation.tabFromPath("/infrastructure")).toBe("infrastructure");
|
||||
expect(navigation.tabFromPath("/ai-agents")).toBe("aiAgents");
|
||||
expect(navigation.tabFromPath("/config")).toBe("config");
|
||||
expect(tabFromPath("/communications")).toBe("communications");
|
||||
expect(tabFromPath("/appearance")).toBe("appearance");
|
||||
expect(tabFromPath("/automation")).toBe("automation");
|
||||
expect(tabFromPath("/infrastructure")).toBe("infrastructure");
|
||||
expect(tabFromPath("/ai-agents")).toBe("aiAgents");
|
||||
expect(tabFromPath("/config")).toBe("config");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createStorageMock } from "../test-helpers/storage.ts";
|
||||
import { loadSettings, saveSettings } from "./storage.ts";
|
||||
|
||||
function setTestLocation(params: { protocol: string; host: string; pathname: string }) {
|
||||
vi.stubGlobal("location", {
|
||||
@@ -38,7 +39,6 @@ function expectedGatewayUrl(basePath: string): string {
|
||||
|
||||
describe("loadSettings default gateway URL derivation", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
vi.stubGlobal("localStorage", createStorageMock());
|
||||
vi.stubGlobal("sessionStorage", createStorageMock());
|
||||
vi.stubGlobal("navigator", { language: "en-US" } as Navigator);
|
||||
@@ -61,7 +61,6 @@ describe("loadSettings default gateway URL derivation", () => {
|
||||
});
|
||||
setControlUiBasePath(" /openclaw/ ");
|
||||
|
||||
const { loadSettings } = await import("./storage.ts");
|
||||
expect(loadSettings().gatewayUrl).toBe(expectedGatewayUrl("/openclaw"));
|
||||
});
|
||||
|
||||
@@ -72,12 +71,10 @@ describe("loadSettings default gateway URL derivation", () => {
|
||||
pathname: "/apps/openclaw/chat",
|
||||
});
|
||||
|
||||
const { loadSettings } = await import("./storage.ts");
|
||||
expect(loadSettings().gatewayUrl).toBe(expectedGatewayUrl("/apps/openclaw"));
|
||||
});
|
||||
|
||||
it("skips node sessionStorage accessors that warn without a storage file", async () => {
|
||||
vi.resetModules();
|
||||
vi.unstubAllGlobals();
|
||||
vi.stubGlobal("localStorage", createStorageMock());
|
||||
vi.stubGlobal("navigator", { language: "en-US" } as Navigator);
|
||||
@@ -89,8 +86,6 @@ describe("loadSettings default gateway URL derivation", () => {
|
||||
setControlUiBasePath(undefined);
|
||||
const warningSpy = vi.spyOn(process, "emitWarning").mockImplementation(() => undefined);
|
||||
|
||||
const { loadSettings } = await import("./storage.ts");
|
||||
|
||||
expect(loadSettings()).toMatchObject({
|
||||
gatewayUrl: expectedGatewayUrl(""),
|
||||
token: "",
|
||||
@@ -118,7 +113,6 @@ describe("loadSettings default gateway URL derivation", () => {
|
||||
}),
|
||||
);
|
||||
|
||||
const { loadSettings } = await import("./storage.ts");
|
||||
expect(loadSettings()).toMatchObject({
|
||||
gatewayUrl: "wss://gateway.example:8443/openclaw",
|
||||
token: "",
|
||||
@@ -155,7 +149,6 @@ describe("loadSettings default gateway URL derivation", () => {
|
||||
});
|
||||
|
||||
const gwUrl = expectedGatewayUrl("");
|
||||
const { loadSettings, saveSettings } = await import("./storage.ts");
|
||||
saveSettings({
|
||||
gatewayUrl: gwUrl,
|
||||
token: "session-token",
|
||||
@@ -188,7 +181,6 @@ describe("loadSettings default gateway URL derivation", () => {
|
||||
|
||||
const gwUrl = expectedGatewayUrl("");
|
||||
const otherUrl = "wss://other-gateway.example:8443";
|
||||
const { loadSettings, saveSettings } = await import("./storage.ts");
|
||||
saveSettings({
|
||||
gatewayUrl: gwUrl,
|
||||
token: "gateway-a-token",
|
||||
@@ -237,7 +229,6 @@ describe("loadSettings default gateway URL derivation", () => {
|
||||
});
|
||||
|
||||
const gwUrl = expectedGatewayUrl("");
|
||||
const { loadSettings, saveSettings } = await import("./storage.ts");
|
||||
saveSettings({
|
||||
gatewayUrl: gwUrl,
|
||||
token: "memory-only-token",
|
||||
@@ -290,7 +281,6 @@ describe("loadSettings default gateway URL derivation", () => {
|
||||
});
|
||||
|
||||
const gwUrl = expectedGatewayUrl("");
|
||||
const { loadSettings, saveSettings } = await import("./storage.ts");
|
||||
saveSettings({
|
||||
gatewayUrl: gwUrl,
|
||||
token: "stale-token",
|
||||
@@ -336,7 +326,6 @@ describe("loadSettings default gateway URL derivation", () => {
|
||||
});
|
||||
|
||||
const gwUrl = expectedGatewayUrl("");
|
||||
const { saveSettings } = await import("./storage.ts");
|
||||
saveSettings({
|
||||
gatewayUrl: gwUrl,
|
||||
token: "",
|
||||
@@ -370,8 +359,6 @@ describe("loadSettings default gateway URL derivation", () => {
|
||||
});
|
||||
|
||||
const gwUrl = expectedGatewayUrl("");
|
||||
const { loadSettings, saveSettings } = await import("./storage.ts");
|
||||
|
||||
saveSettings({
|
||||
gatewayUrl: gwUrl,
|
||||
token: "",
|
||||
@@ -403,7 +390,6 @@ describe("loadSettings default gateway URL derivation", () => {
|
||||
pathname: "/",
|
||||
});
|
||||
|
||||
const { saveSettings } = await import("./storage.ts");
|
||||
const gwUrl = expectedGatewayUrl("");
|
||||
const scopedKey = `openclaw.control.settings.v1:wss://gateway.example:8443`;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user