























@@ -1,4 +1,4 @@
1-import { execFileSync } from "node:child_process";
1+import { execFileSync, spawnSync } from "node:child_process";
22import path from "node:path";
33import { bundledPluginFile, bundledPluginRoot } from "openclaw/plugin-sdk/test-fixtures";
44import { beforeAll, describe, expect, it, vi } from "vitest";
@@ -38,6 +38,13 @@ function runScript(args: string[], cwd = process.cwd()) {
3838});
3939}
404041+function runScriptResult(args: string[], cwd = process.cwd()) {
42+return spawnSync(process.execPath, [scriptPath, ...args], {
43+ cwd,
44+encoding: "utf8",
45+});
46+}
47+4148function requireFirstMockArg<T>(mock: { mock: { calls: Array<[T, ...unknown[]]> } }): T {
4249const [call] = mock.mock.calls;
4350if (!call) {
@@ -461,6 +468,21 @@ describe("scripts/test-extension.mjs", () => {
461468]);
462469});
463470471+it("keeps explicitly requested extensions without tests in batch plans", () => {
472+const extensionId = findExtensionWithoutTests();
473+const batch = resolveExtensionBatchPlan({
474+cwd: process.cwd(),
475+extensionIds: [extensionId, "firecrawl"],
476+});
477+478+expect(batch.extensionIds).toEqual([extensionId, "firecrawl"].toSorted());
479+expect(batch.extensionCount).toBe(2);
480+expect(batch.noTestExtensionIds).toEqual([extensionId]);
481+expect(batch.hasTests).toBe(true);
482+expect(batch.testFileCount).toBe(1);
483+expect(batch.planGroups.flatMap((group) => group.extensionIds)).toEqual(["firecrawl"]);
484+});
485+464486it("counts tracked extension tests without walking extension directories", () => {
465487const payload = expectNoNodeFsScans<{
466488batchTests: number;
@@ -657,6 +679,35 @@ describe("scripts/test-extension.mjs", () => {
657679expect(runParams.targets).toContain("extensions/codex/src/app-server/client.test.ts");
658680});
659681682+it("fails extension batch groups when exact excludes remove every test", async () => {
683+const runGroup = vi.fn<() => Promise<number>>().mockResolvedValue(0);
684+const result = await runExtensionBatchPlan(
685+resolveExtensionBatchPlan({ cwd: process.cwd(), extensionIds: ["firecrawl"] }),
686+{
687+ runGroup,
688+vitestArgs: ["--exclude", bundledPluginFile("firecrawl", "src/firecrawl-tools.test.ts")],
689+},
690+);
691+692+expect(result).toBe(1);
693+expect(runGroup).not.toHaveBeenCalled();
694+});
695+696+it("allows extension batch groups to opt into empty exact excludes", async () => {
697+const runGroup = vi.fn<() => Promise<number>>().mockResolvedValue(0);
698+const result = await runExtensionBatchPlan(
699+resolveExtensionBatchPlan({ cwd: process.cwd(), extensionIds: ["firecrawl"] }),
700+{
701+allowEmptyAfterExclude: true,
702+ runGroup,
703+vitestArgs: ["--exclude", bundledPluginFile("firecrawl", "src/firecrawl-tools.test.ts")],
704+},
705+);
706+707+expect(result).toBe(0);
708+expect(runGroup).not.toHaveBeenCalled();
709+});
710+660711it("detects exact Vitest excludes in extension batch args", () => {
661712expect([
662713 ...parseExactVitestExcludePaths([
@@ -667,11 +718,19 @@ describe("scripts/test-extension.mjs", () => {
667718expect([...parseExactVitestExcludePaths(["--exclude=extensions/**/*.test.ts"])]).toEqual([]);
668719});
669720670-it("treats extensions without tests as a no-op by default", () => {
721+it("fails explicitly requested extensions without tests by default", () => {
722+const extensionId = findExtensionWithoutTests();
723+const result = runScriptResult([extensionId]);
724+725+expect(result.status).toBe(1);
726+expect(result.stderr).toContain(`No tests found for ${bundledPluginRoot(extensionId)}.`);
727+});
728+729+it("allows explicitly requested extensions without tests when requested", () => {
671730const extensionId = findExtensionWithoutTests();
672-const stdout = runScript([extensionId]);
731+const result = runScriptResult([extensionId, "--allow-no-tests"]);
673732674-expect(stdout).toContain(`No tests found for ${bundledPluginRoot(extensionId)}.`);
675-expect(stdout).toContain("Skipping.");
733+expect(result.status).toBe(0);
734+expect(result.stderr).toContain(`No tests found for ${bundledPluginRoot(extensionId)}.`);
676735});
677736});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。