test: share qa runtime fixtures

This commit is contained in:
Peter Steinberger
2026-04-20 19:38:30 +01:00
parent b3a0da7c5e
commit 905d2d8062
3 changed files with 117 additions and 105 deletions

View File

@@ -1,8 +1,13 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import type { Command } from "commander";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
cleanupTempDirs,
expectPrivateQaLabRuntimeSurfaceLoad,
expectQaLabRuntimeSurfaceLoad,
makePrivateQaSourceRoot,
restorePrivateQaCliEnv,
} from "./qa-runtime.test-helpers.js";
const loadPluginManifestRegistry = vi.hoisted(() => vi.fn());
const loadBundledPluginPublicSurfaceModuleSync = vi.hoisted(() => vi.fn());
@@ -38,14 +43,8 @@ describe("plugin-sdk qa-runner-runtime", () => {
});
afterEach(() => {
for (const dir of tempDirs.splice(0)) {
fs.rmSync(dir, { recursive: true, force: true });
}
if (originalPrivateQaCli === undefined) {
delete process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI;
} else {
process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI = originalPrivateQaCli;
}
cleanupTempDirs(tempDirs);
restorePrivateQaCliEnv(originalPrivateQaCli);
});
it("stays cold until runner discovery is requested", async () => {
@@ -57,56 +56,23 @@ describe("plugin-sdk qa-runner-runtime", () => {
});
it("loads the qa-lab runtime public surface through the public runner seam", async () => {
const runtimeSurface = {
defaultQaRuntimeModelForMode: vi.fn(),
startQaLiveLaneGateway: vi.fn(),
};
loadBundledPluginPublicSurfaceModuleSync.mockReturnValue(runtimeSurface);
const module = await import("./qa-runner-runtime.js");
expect(module.loadQaRuntimeModule()).toBe(runtimeSurface);
expect(loadBundledPluginPublicSurfaceModuleSync).toHaveBeenCalledWith({
dirName: "qa-lab",
artifactBasename: "runtime-api.js",
await expectQaLabRuntimeSurfaceLoad({
importRuntime: () => import("./qa-runner-runtime.js"),
loadBundledPluginPublicSurfaceModuleSync,
});
});
it("uses the source bundled tree for qa-lab runtime loading in private qa mode", async () => {
const sourceRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-qa-runtime-root-"));
tempDirs.push(sourceRoot);
fs.mkdirSync(path.join(sourceRoot, "src"), { recursive: true });
fs.mkdirSync(path.join(sourceRoot, "extensions"), { recursive: true });
fs.writeFileSync(path.join(sourceRoot, ".git"), "gitdir: /tmp/mock\n", "utf8");
process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI = "1";
resolveOpenClawPackageRootSync.mockReturnValue(sourceRoot);
const runtimeSurface = {
defaultQaRuntimeModelForMode: vi.fn(),
startQaLiveLaneGateway: vi.fn(),
};
loadBundledPluginPublicSurfaceModuleSync.mockReturnValue(runtimeSurface);
const module = await import("./qa-runner-runtime.js");
expect(module.loadQaRuntimeModule()).toBe(runtimeSurface);
expect(loadBundledPluginPublicSurfaceModuleSync).toHaveBeenCalledWith({
dirName: "qa-lab",
artifactBasename: "runtime-api.js",
env: expect.objectContaining({
OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1",
OPENCLAW_BUNDLED_PLUGINS_DIR: path.join(sourceRoot, "extensions"),
}),
await expectPrivateQaLabRuntimeSurfaceLoad({
tempDirs,
importRuntime: () => import("./qa-runner-runtime.js"),
loadBundledPluginPublicSurfaceModuleSync,
resolveOpenClawPackageRootSync,
});
});
it("loads bundled plugin test APIs with the private QA source tree override", async () => {
const sourceRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-qa-test-api-root-"));
tempDirs.push(sourceRoot);
fs.mkdirSync(path.join(sourceRoot, "src"), { recursive: true });
fs.mkdirSync(path.join(sourceRoot, "extensions"), { recursive: true });
fs.writeFileSync(path.join(sourceRoot, ".git"), "gitdir: /tmp/mock\n", "utf8");
process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI = "1";
const sourceRoot = makePrivateQaSourceRoot(tempDirs, "openclaw-qa-test-api-root-");
resolveOpenClawPackageRootSync.mockReturnValue(sourceRoot);
const testApi = { marker: "matrix-test-api" };
@@ -203,12 +169,7 @@ describe("plugin-sdk qa-runner-runtime", () => {
});
it("prefers the source bundled tree for private qa discovery in repo checkouts", async () => {
const sourceRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-qa-runner-root-"));
tempDirs.push(sourceRoot);
fs.mkdirSync(path.join(sourceRoot, "src"), { recursive: true });
fs.mkdirSync(path.join(sourceRoot, "extensions"), { recursive: true });
fs.writeFileSync(path.join(sourceRoot, ".git"), "gitdir: /tmp/mock\n", "utf8");
process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI = "1";
const sourceRoot = makePrivateQaSourceRoot(tempDirs, "openclaw-qa-runner-root-");
resolveOpenClawPackageRootSync.mockReturnValue(sourceRoot);
const register = vi.fn((qa: Command) => qa);

View File

@@ -0,0 +1,82 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { expect, vi } from "vitest";
type QaRuntimeModule = {
loadQaRuntimeModule: () => unknown;
};
type SurfaceLoaderMock = ReturnType<typeof vi.fn>;
export function cleanupTempDirs(tempDirs: string[]): void {
for (const dir of tempDirs.splice(0)) {
fs.rmSync(dir, { recursive: true, force: true });
}
}
export function restorePrivateQaCliEnv(originalPrivateQaCli: string | undefined): void {
if (originalPrivateQaCli === undefined) {
delete process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI;
} else {
process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI = originalPrivateQaCli;
}
}
export function makePrivateQaSourceRoot(tempDirs: string[], prefix: string): string {
const sourceRoot = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
tempDirs.push(sourceRoot);
fs.mkdirSync(path.join(sourceRoot, "src"), { recursive: true });
fs.mkdirSync(path.join(sourceRoot, "extensions"), { recursive: true });
fs.writeFileSync(path.join(sourceRoot, ".git"), "gitdir: /tmp/mock\n", "utf8");
process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI = "1";
return sourceRoot;
}
export function makeQaRuntimeSurface() {
return {
defaultQaRuntimeModelForMode: vi.fn(),
startQaLiveLaneGateway: vi.fn(),
};
}
export async function expectQaLabRuntimeSurfaceLoad(params: {
importRuntime: () => Promise<QaRuntimeModule>;
loadBundledPluginPublicSurfaceModuleSync: SurfaceLoaderMock;
}) {
const runtimeSurface = makeQaRuntimeSurface();
params.loadBundledPluginPublicSurfaceModuleSync.mockReturnValue(runtimeSurface);
const module = await params.importRuntime();
expect(module.loadQaRuntimeModule()).toBe(runtimeSurface);
expect(params.loadBundledPluginPublicSurfaceModuleSync).toHaveBeenCalledWith({
dirName: "qa-lab",
artifactBasename: "runtime-api.js",
});
}
export async function expectPrivateQaLabRuntimeSurfaceLoad(params: {
tempDirs: string[];
importRuntime: () => Promise<QaRuntimeModule>;
loadBundledPluginPublicSurfaceModuleSync: SurfaceLoaderMock;
resolveOpenClawPackageRootSync: SurfaceLoaderMock;
}) {
const sourceRoot = makePrivateQaSourceRoot(params.tempDirs, "openclaw-qa-runtime-root-");
params.resolveOpenClawPackageRootSync.mockReturnValue(sourceRoot);
const runtimeSurface = makeQaRuntimeSurface();
params.loadBundledPluginPublicSurfaceModuleSync.mockReturnValue(runtimeSurface);
const module = await params.importRuntime();
expect(module.loadQaRuntimeModule()).toBe(runtimeSurface);
expect(params.loadBundledPluginPublicSurfaceModuleSync).toHaveBeenCalledWith({
dirName: "qa-lab",
artifactBasename: "runtime-api.js",
env: expect.objectContaining({
OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1",
OPENCLAW_BUNDLED_PLUGINS_DIR: path.join(sourceRoot, "extensions"),
}),
});
}

View File

@@ -1,7 +1,10 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
cleanupTempDirs,
expectPrivateQaLabRuntimeSurfaceLoad,
expectQaLabRuntimeSurfaceLoad,
restorePrivateQaCliEnv,
} from "./qa-runtime.test-helpers.js";
const loadBundledPluginPublicSurfaceModuleSync = vi.hoisted(() => vi.fn());
const resolveOpenClawPackageRootSync = vi.hoisted(() => vi.fn());
@@ -25,14 +28,8 @@ describe("plugin-sdk qa-runtime", () => {
});
afterEach(() => {
for (const dir of tempDirs.splice(0)) {
fs.rmSync(dir, { recursive: true, force: true });
}
if (originalPrivateQaCli === undefined) {
delete process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI;
} else {
process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI = originalPrivateQaCli;
}
cleanupTempDirs(tempDirs);
restorePrivateQaCliEnv(originalPrivateQaCli);
});
it("stays cold until the runtime seam is used", async () => {
@@ -44,46 +41,18 @@ describe("plugin-sdk qa-runtime", () => {
});
it("loads the qa-lab runtime public surface through the generic seam", async () => {
const runtimeSurface = {
defaultQaRuntimeModelForMode: vi.fn(),
startQaLiveLaneGateway: vi.fn(),
};
loadBundledPluginPublicSurfaceModuleSync.mockReturnValue(runtimeSurface);
const module = await import("./qa-runtime.js");
expect(module.loadQaRuntimeModule()).toBe(runtimeSurface);
expect(loadBundledPluginPublicSurfaceModuleSync).toHaveBeenCalledWith({
dirName: "qa-lab",
artifactBasename: "runtime-api.js",
await expectQaLabRuntimeSurfaceLoad({
importRuntime: () => import("./qa-runtime.js"),
loadBundledPluginPublicSurfaceModuleSync,
});
});
it("uses the source bundled tree for qa-lab runtime loading in private qa mode", async () => {
const sourceRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-qa-runtime-root-"));
tempDirs.push(sourceRoot);
fs.mkdirSync(path.join(sourceRoot, "src"), { recursive: true });
fs.mkdirSync(path.join(sourceRoot, "extensions"), { recursive: true });
fs.writeFileSync(path.join(sourceRoot, ".git"), "gitdir: /tmp/mock\n", "utf8");
process.env.OPENCLAW_ENABLE_PRIVATE_QA_CLI = "1";
resolveOpenClawPackageRootSync.mockReturnValue(sourceRoot);
const runtimeSurface = {
defaultQaRuntimeModelForMode: vi.fn(),
startQaLiveLaneGateway: vi.fn(),
};
loadBundledPluginPublicSurfaceModuleSync.mockReturnValue(runtimeSurface);
const module = await import("./qa-runtime.js");
expect(module.loadQaRuntimeModule()).toBe(runtimeSurface);
expect(loadBundledPluginPublicSurfaceModuleSync).toHaveBeenCalledWith({
dirName: "qa-lab",
artifactBasename: "runtime-api.js",
env: expect.objectContaining({
OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1",
OPENCLAW_BUNDLED_PLUGINS_DIR: path.join(sourceRoot, "extensions"),
}),
await expectPrivateQaLabRuntimeSurfaceLoad({
tempDirs,
importRuntime: () => import("./qa-runtime.js"),
loadBundledPluginPublicSurfaceModuleSync,
resolveOpenClawPackageRootSync,
});
});