test: tighten assertions and harness coverage

This commit is contained in:
Peter Steinberger
2026-05-08 05:27:57 +01:00
parent f62618f805
commit 9ef37d1907
822 changed files with 8918 additions and 6533 deletions

View File

@@ -236,7 +236,7 @@ describe("barnacle-auto-response", () => {
expect(managedLabelSpecs[PROOF_SUFFICIENT_LABEL].color).toBe("0E8A16");
for (const label of Object.values(candidateLabels)) {
expect(managedLabelSpecs[label]).toBeDefined();
expect(managedLabelSpecs).toHaveProperty(label);
expect(managedLabelSpecs[label].description).toMatch(/^Candidate:/);
}
});

View File

@@ -12,6 +12,14 @@ import {
writeBuildAllStepCacheStamp,
} from "../../scripts/build-all.mjs";
function getBuildAllStep(label: string) {
const step = BUILD_ALL_STEPS.find((entry) => entry.label === label);
if (!step) {
throw new Error(`Missing build-all step ${label}`);
}
return step;
}
function withBuildCacheFixture(
run: (fixture: {
rootDir: string;
@@ -53,8 +61,7 @@ function withBuildCacheFixture(
describe("resolveBuildAllStep", () => {
it("routes pnpm steps through the npm_execpath pnpm runner on Windows", () => {
const step = BUILD_ALL_STEPS.find((entry) => entry.label === "plugins:assets:build");
expect(step).toBeTruthy();
const step = getBuildAllStep("plugins:assets:build");
const result = resolveBuildAllStep(step, {
platform: "win32",
@@ -76,8 +83,7 @@ describe("resolveBuildAllStep", () => {
});
it("keeps node steps on the current node binary", () => {
const step = BUILD_ALL_STEPS.find((entry) => entry.label === "runtime-postbuild");
expect(step).toBeTruthy();
const step = getBuildAllStep("runtime-postbuild");
const result = resolveBuildAllStep(step, {
nodeExecPath: "/custom/node",
@@ -95,8 +101,7 @@ describe("resolveBuildAllStep", () => {
});
it("adds heap headroom for plugin-sdk dts on Windows", () => {
const step = BUILD_ALL_STEPS.find((entry) => entry.label === "build:plugin-sdk:dts");
expect(step).toBeTruthy();
const step = getBuildAllStep("build:plugin-sdk:dts");
const result = resolveBuildAllStep(step, {
platform: "win32",
@@ -168,15 +173,13 @@ describe("resolveBuildAllSteps", () => {
});
it("does not cache plugin-sdk entry shims over compiled JS", () => {
const step = BUILD_ALL_STEPS.find((entry) => entry.label === "write-plugin-sdk-entry-dts");
expect(step).toBeTruthy();
expect(step?.cache).toBeUndefined();
const step = getBuildAllStep("write-plugin-sdk-entry-dts");
expect(step.cache).toBeUndefined();
});
it("does not cache hook metadata over compiled hook handlers", () => {
const step = BUILD_ALL_STEPS.find((entry) => entry.label === "copy-hook-metadata");
expect(step).toBeTruthy();
expect(step?.cache).toBeUndefined();
const step = getBuildAllStep("copy-hook-metadata");
expect(step.cache).toBeUndefined();
});
it("rejects unknown build profiles", () => {

View File

@@ -12,8 +12,10 @@ function extractFunctionBody(source: string, name: string): string {
const match = source.match(
new RegExp(`^function ${name} \\{\\r?\\n([\\s\\S]*?)^\\}\\r?\\n`, "m"),
);
expect(match?.[1]).toBeDefined();
return match![1];
if (match?.[1] === undefined) {
throw new Error(`Missing PowerShell function body ${name}`);
}
return match[1];
}
function findPowerShell(): string | undefined {

View File

@@ -215,13 +215,13 @@ printf 'BBBBB22222\\t0\\tBeta Team\\r\\n'`,
expect(fallback).toBe("BBBBB22222");
});
it("resolves a fallback team ID from Xcode team listings (smoke)", async () => {
it("resolves a fallback team ID from Xcode team listings (smoke)", () => {
const fallbackResult = runScript(sharedHomeDir, { IOS_PYTHON_BIN: sharedFakePythonPath });
expect(fallbackResult.ok).toBe(true);
expect(fallbackResult.stdout).toBe("AAAAA11111");
});
it("prints actionable guidance when Xcode account exists but no Team ID is resolvable", async () => {
it("prints actionable guidance when Xcode account exists but no Team ID is resolvable", () => {
const result = runScript(sharedHomeDir);
expect(result.ok).toBe(false);
expect(

View File

@@ -39,18 +39,24 @@ function readWorkflow(path: string): Workflow {
function workflowJob(path: string, jobName: string): WorkflowJob {
const job = readWorkflow(path).jobs?.[jobName];
expect(job, `expected workflow job ${jobName}`).toBeDefined();
return job!;
if (!job) {
throw new Error(`Expected workflow job ${jobName} in ${path}`);
}
return job;
}
function workflowStep(job: WorkflowJob, stepName: string): WorkflowStep {
const step = job.steps?.find((candidate) => candidate.name === stepName);
expect(step, `expected workflow step ${stepName}`).toBeDefined();
return step!;
if (!step) {
throw new Error(`Expected workflow step ${stepName}`);
}
return step;
}
function expectTextToIncludeAll(text: string | undefined, snippets: string[]): void {
expect(text).toBeDefined();
if (text === undefined) {
throw new Error("Expected text to be defined before checking snippets");
}
for (const snippet of snippets) {
expect(text).toContain(snippet);
}

View File

@@ -22,6 +22,14 @@ function readPluginPrereleaseWorkflow() {
return parse(readFileSync(".github/workflows/plugin-prerelease.yml", "utf8"));
}
function getDockerLane(name: string) {
const lane = findLaneByName(name);
if (!lane) {
throw new Error(`Missing Docker E2E lane ${name}`);
}
return lane;
}
describe("scripts/lib/plugin-prerelease-test-plan.mjs", () => {
it("covers every pre-release plugin skill surface in the plugin prerelease plan", () => {
const plan = assertPluginPrereleaseTestPlanComplete();
@@ -55,7 +63,7 @@ describe("scripts/lib/plugin-prerelease-test-plan.mjs", () => {
]);
for (const lane of plan.dockerLanes) {
expect(findLaneByName(lane), lane).toBeTruthy();
expect(getDockerLane(lane).name).toBe(lane);
}
});
@@ -83,7 +91,7 @@ describe("scripts/lib/plugin-prerelease-test-plan.mjs", () => {
});
it("uses kitchen-sink npm and ClawHub scenarios as the registry install canary", () => {
const lane = findLaneByName("kitchen-sink-plugin");
const lane = getDockerLane("kitchen-sink-plugin");
const script = readFileSync("scripts/e2e/kitchen-sink-plugin-docker.sh", "utf8");
const sweepScript = readFileSync("scripts/e2e/lib/kitchen-sink-plugin/sweep.sh", "utf8");
const assertionsScript = readFileSync(
@@ -153,7 +161,7 @@ describe("scripts/lib/plugin-prerelease-test-plan.mjs", () => {
});
it("keeps the generic plugin Docker lane as an external install contract canary", () => {
const lane = findLaneByName("plugins");
const lane = getDockerLane("plugins");
const sweepScript = readFileSync("scripts/e2e/lib/plugins/sweep.sh", "utf8");
const clawhubScript = readFileSync("scripts/e2e/lib/plugins/clawhub.sh", "utf8");
const assertionsScript = readFileSync("scripts/e2e/lib/plugins/assertions.mjs", "utf8");

View File

@@ -26,6 +26,10 @@ async function createExtensionsDir() {
return extensionsDir;
}
async function expectPathExists(filePath: string) {
await expect(fs.access(filePath)).resolves.toBeUndefined();
}
async function writePluginPackage(
extensionsDir: string,
pluginId: string,
@@ -284,7 +288,7 @@ describe("bundled plugin postinstall", () => {
log: { log: vi.fn(), warn: vi.fn() },
});
await expect(fs.stat(legacyRuntimeRoot)).resolves.toBeTruthy();
await expectPathExists(legacyRuntimeRoot);
});
it("honors disable env before source-checkout pruning", async () => {
@@ -301,7 +305,7 @@ describe("bundled plugin postinstall", () => {
log: { log: vi.fn(), warn: vi.fn() },
});
await expect(fs.stat(path.join(extensionsDir, "acpx", "node_modules"))).resolves.toBeTruthy();
await expectPathExists(path.join(extensionsDir, "acpx", "node_modules"));
});
it("migrates the plugin registry during postinstall from built dist contracts", async () => {
@@ -448,7 +452,7 @@ describe("bundled plugin postinstall", () => {
}),
).toEqual(["dist/channel-CJUAgRQR.js"]);
await expect(fs.stat(currentFile)).resolves.toBeTruthy();
await expectPathExists(currentFile);
await expect(fs.stat(staleFile)).rejects.toMatchObject({ code: "ENOENT" });
});
@@ -515,7 +519,7 @@ describe("bundled plugin postinstall", () => {
await expect(fs.stat(overrideLegacyRoot)).rejects.toMatchObject({ code: "ENOENT" });
await expect(fs.stat(systemLegacyRoot)).rejects.toMatchObject({ code: "ENOENT" });
await expect(fs.lstat(legacySymlink)).rejects.toMatchObject({ code: "ENOENT" });
await expect(fs.stat(thirdPartyNodeModules)).resolves.toBeTruthy();
await expectPathExists(thirdPartyNodeModules);
expect(log.warn).not.toHaveBeenCalled();
expect(log.log).toHaveBeenCalledWith(
expect.stringContaining("[postinstall] pruned legacy plugin runtime deps:"),
@@ -620,7 +624,7 @@ describe("bundled plugin postinstall", () => {
}),
).toEqual(["dist/memory-state-old.js"]);
await expect(fs.stat(importedChunk)).resolves.toBeTruthy();
await expectPathExists(importedChunk);
await expect(fs.stat(staleFile)).rejects.toMatchObject({ code: "ENOENT" });
});
@@ -704,7 +708,7 @@ describe("bundled plugin postinstall", () => {
}),
).not.toThrow();
await expect(fs.stat(staleFile)).resolves.toBeTruthy();
await expectPathExists(staleFile);
expect(warn).toHaveBeenCalledWith(
"[postinstall] skipping dist prune: missing dist inventory: dist/postinstall-inventory.json",
);
@@ -726,7 +730,7 @@ describe("bundled plugin postinstall", () => {
}),
).not.toThrow();
await expect(fs.stat(currentFile)).resolves.toBeTruthy();
await expectPathExists(currentFile);
expect(warn).toHaveBeenCalledWith(
"[postinstall] skipping dist prune: invalid dist inventory: dist/postinstall-inventory.json",
);
@@ -898,9 +902,7 @@ describe("bundled plugin postinstall", () => {
await expect(fs.stat(path.join(extensionsDir, "acpx", "node_modules"))).rejects.toMatchObject({
code: "ENOENT",
});
await expect(
fs.stat(path.join(extensionsDir, "fixtures", "node_modules")),
).resolves.toBeTruthy();
await expectPathExists(path.join(extensionsDir, "fixtures", "node_modules"));
});
it("skips symlink entries when pruning source-checkout bundled plugin node_modules", () => {

View File

@@ -23,7 +23,7 @@ describe("root package override guardrails", () => {
const pnpmOverride = manifest.pnpm?.overrides?.["@aws-sdk/client-bedrock-runtime"];
expect(pnpmOverride).toBe("3.1024.0");
expect(manifest.dependencies?.[packageName]).toBeDefined();
expect(manifest.dependencies).toHaveProperty(packageName);
expect(npmOverride).toBe(`$${packageName}`);
});

View File

@@ -74,7 +74,7 @@ describe("runtime postbuild static assets", () => {
expect(await fs.readFile(destPath, "utf8")).toBe("proxy-data\n");
});
it("warns when a declared static asset is missing", async () => {
it("warns when a declared static asset is missing", () => {
const rootDir = createTempDir("openclaw-runtime-postbuild-");
const warn = vi.fn();

View File

@@ -32,8 +32,10 @@ function findExtensionWithoutTests() {
(candidate) => !resolveExtensionTestPlan({ targetArg: candidate, cwd: process.cwd() }).hasTests,
);
expect(extensionId).toBeDefined();
return extensionId ?? "missing-no-test-extension";
if (!extensionId) {
throw new Error("Expected at least one extension without tests");
}
return extensionId;
}
describe("scripts/test-extension.mjs", () => {

View File

@@ -5,6 +5,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
import {
collectVitestFileDurations,
normalizeTrackedRepoPath,
runVitestJsonReport,
tryReadJsonFile,
} from "../../scripts/test-report-utils.mjs";
@@ -84,14 +85,12 @@ describe("scripts/test-report-utils tryReadJsonFile", () => {
describe("scripts/test-report-utils runVitestJsonReport", () => {
beforeEach(() => {
vi.resetModules();
spawnSyncMock.mockReset();
});
it("launches Vitest through pnpm exec", async () => {
spawnSyncMock.mockReturnValue({ status: 0 });
const reportPath = path.join(os.tmpdir(), `openclaw-vitest-json-${Date.now()}.json`);
const { runVitestJsonReport } = await import("../../scripts/test-report-utils.mjs");
expect(
runVitestJsonReport({

View File

@@ -29,9 +29,9 @@ describe("scripts/ui windows spawn behavior", () => {
});
it("allows safe forwarded args when shell mode is required on Windows", () => {
expect(() =>
expect(
assertSafeWindowsShellArgs(["run", "build", "--filter", "@openclaw/ui"], "win32"),
).not.toThrow();
).toBeUndefined();
});
it("rejects dangerous forwarded args when shell mode is required on Windows", () => {
@@ -44,6 +44,6 @@ describe("scripts/ui windows spawn behavior", () => {
});
it("does not reject args on non-windows platforms", () => {
expect(() => assertSafeWindowsShellArgs(["contains&metacharacters"], "linux")).not.toThrow();
expect(assertSafeWindowsShellArgs(["contains&metacharacters"], "linux")).toBeUndefined();
});
});