Files
openclaw/test/extension-test-boundary.test.ts
2026-03-27 23:47:29 +00:00

69 lines
2.1 KiB
TypeScript

import fs from "node:fs";
import path from "node:path";
import { describe, expect, it } from "vitest";
const repoRoot = path.resolve(import.meta.dirname, "..");
const allowedNonExtensionTests = new Set<string>([
"src/plugins/contracts/discovery.contract.test.ts",
]);
function walk(dir: string, entries: string[] = []): string[] {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") {
continue;
}
walk(fullPath, entries);
continue;
}
if (!entry.name.endsWith(".test.ts") && !entry.name.endsWith(".test.tsx")) {
continue;
}
entries.push(path.relative(repoRoot, fullPath).replaceAll(path.sep, "/"));
}
return entries;
}
function findExtensionImports(source: string): string[] {
return [
...source.matchAll(/from\s+["']((?:\.\.\/)+extensions\/[^"']+)["']/g),
...source.matchAll(/import\(\s*["']((?:\.\.\/)+extensions\/[^"']+)["']\s*\)/g),
].map((match) => match[1]);
}
describe("non-extension test boundaries", () => {
it("keeps extension-owned behavior suites under extensions/", () => {
const testFiles = [
...walk(path.join(repoRoot, "src")),
...walk(path.join(repoRoot, "test")),
...walk(path.join(repoRoot, "packages")),
].filter(
(file) =>
!file.startsWith("extensions/") &&
!file.startsWith("test/helpers/") &&
!file.startsWith("ui/"),
);
const offenders = testFiles
.map((file) => {
const source = fs.readFileSync(path.join(repoRoot, file), "utf8");
const imports = findExtensionImports(source);
if (imports.length === 0) {
return null;
}
if (allowedNonExtensionTests.has(file)) {
return null;
}
return {
file,
imports,
};
})
.filter((value): value is { file: string; imports: string[] } => value !== null);
expect(offenders).toEqual([]);
});
});