Download src/plugins/contracts/extension-test-api-consumption.test.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 6.83 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/plugins/contracts/extension-test-api-consumption.test.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/plugins/contracts/extension-test-api-consumption.test.ts
-
curl -L -o extension-test-api-consumption.test.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/plugins/contracts/extension-test-api-consumption.test.ts
6.83 kB
| import fs from "node:fs"; | |
| import { dirname, resolve } from "node:path"; | |
| import { fileURLToPath } from "node:url"; | |
| import ts from "typescript"; | |
| import { describe, expect, it } from "vitest"; | |
| import { listGitTrackedFiles } from "../../test-utils/repo-files.js"; | |
| const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../../.."); | |
| const THIS_TEST_FILE = "src/plugins/contracts/extension-test-api-consumption.test.ts"; | |
| type ExtensionTestApi = { | |
| absoluteStem: string; | |
| packageName?: string; | |
| packageExportsTestApi: boolean; | |
| pluginId: string; | |
| repoPath: string; | |
| }; | |
| function listTrackedFiles(pathspecs: string | readonly string[]): string[] { | |
| const files = listGitTrackedFiles({ pathspecs, repoRoot: REPO_ROOT }); | |
| if (!files) { | |
| throw new Error(`failed to list tracked files for ${JSON.stringify(pathspecs)}`); | |
| } | |
| return files; | |
| } | |
| function stripModuleExtension(value: string): string { | |
| return value.replace(/\.(?:[cm]?[jt]sx?)$/u, ""); | |
| } | |
| function listExtensionTestApis(): ExtensionTestApi[] { | |
| return listTrackedFiles("extensions/*/test-api.ts").map((repoPath) => { | |
| const pluginId = repoPath.split("/")[1]; | |
| if (!pluginId) { | |
| throw new Error(`invalid extension test API path: ${repoPath}`); | |
| } | |
| const packageJsonPath = resolve(REPO_ROOT, "extensions", pluginId, "package.json"); | |
| const parsed = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")) as { | |
| exports?: Record<string, unknown>; | |
| name?: unknown; | |
| }; | |
| const packageName = typeof parsed.name === "string" ? parsed.name : undefined; | |
| const packageExportsTestApi = Object.keys(parsed.exports ?? {}).some( | |
| (key) => stripModuleExtension(key) === "./test-api", | |
| ); | |
| return { | |
| absoluteStem: stripModuleExtension(resolve(REPO_ROOT, repoPath)), | |
| packageName, | |
| packageExportsTestApi, | |
| pluginId, | |
| repoPath, | |
| }; | |
| }); | |
| } | |
| function objectStringProperty(node: ts.ObjectLiteralExpression, name: string): string | undefined { | |
| for (const property of node.properties) { | |
| if (!ts.isPropertyAssignment(property)) { | |
| continue; | |
| } | |
| const propertyName = ts.isIdentifier(property.name) | |
| ? property.name.text | |
| : ts.isStringLiteralLike(property.name) | |
| ? property.name.text | |
| : undefined; | |
| if (propertyName === name && ts.isStringLiteralLike(property.initializer)) { | |
| return property.initializer.text; | |
| } | |
| } | |
| return undefined; | |
| } | |
| function collectTestApiSourceReferences(source: string, fileName = "source.ts") { | |
| const moduleSpecifiers = ts | |
| .preProcessFile(source, true, true) | |
| .importedFiles.map((entry) => entry.fileName) | |
| .toSorted(); | |
| const pluginIds = new Set<string>(); | |
| const sourceFile = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true); | |
| function visit(node: ts.Node): void { | |
| if (ts.isCallExpression(node)) { | |
| const name = ts.isIdentifier(node.expression) | |
| ? node.expression.text | |
| : ts.isPropertyAccessExpression(node.expression) | |
| ? node.expression.name.text | |
| : undefined; | |
| const pluginId = node.arguments[0]; | |
| if ( | |
| name === "loadQaRunnerBundledPluginTestApi" && | |
| pluginId && | |
| ts.isStringLiteralLike(pluginId) | |
| ) { | |
| pluginIds.add(pluginId.text); | |
| } | |
| } else if (ts.isObjectLiteralExpression(node)) { | |
| const pluginId = objectStringProperty(node, "pluginId"); | |
| if (pluginId && objectStringProperty(node, "artifactBasename") === "test-api.js") { | |
| pluginIds.add(pluginId); | |
| } | |
| } | |
| ts.forEachChild(node, visit); | |
| } | |
| visit(sourceFile); | |
| return { moduleSpecifiers, pluginIds: [...pluginIds].toSorted() }; | |
| } | |
| function resolveTestApiPluginId( | |
| specifier: string, | |
| importerFile: string, | |
| testApis: readonly ExtensionTestApi[], | |
| ): string | undefined { | |
| if (specifier.startsWith(".") || specifier.startsWith("/")) { | |
| const resolvedStem = stripModuleExtension(resolve(dirname(importerFile), specifier)); | |
| return testApis.find((testApi) => testApi.absoluteStem === resolvedStem)?.pluginId; | |
| } | |
| const bareSpecifier = stripModuleExtension(specifier); | |
| return testApis.find( | |
| (testApi) => testApi.packageName && `${testApi.packageName}/test-api` === bareSpecifier, | |
| )?.pluginId; | |
| } | |
| function collectOrphanExtensionTestApiFiles(): string[] { | |
| const testApis = listExtensionTestApis(); | |
| const consumed = new Set( | |
| testApis.filter((testApi) => testApi.packageExportsTestApi).map((testApi) => testApi.pluginId), | |
| ); | |
| const testApiFiles = new Set(testApis.map((testApi) => testApi.repoPath)); | |
| for (const repoPath of listTrackedFiles(["src", "test", "extensions", "packages", "scripts"])) { | |
| if ( | |
| repoPath === THIS_TEST_FILE || | |
| testApiFiles.has(repoPath) || | |
| !/\.(?:[cm]?[jt]sx?)$/u.test(repoPath) | |
| ) { | |
| continue; | |
| } | |
| const absolutePath = resolve(REPO_ROOT, repoPath); | |
| const source = fs.readFileSync(absolutePath, "utf8"); | |
| if (!source.includes("test-api") && !source.includes("loadQaRunnerBundledPluginTestApi")) { | |
| continue; | |
| } | |
| const references = collectTestApiSourceReferences(source, absolutePath); | |
| for (const pluginId of references.pluginIds) { | |
| if (testApis.some((testApi) => testApi.pluginId === pluginId)) { | |
| consumed.add(pluginId); | |
| } | |
| } | |
| for (const specifier of references.moduleSpecifiers) { | |
| const pluginId = resolveTestApiPluginId(specifier, absolutePath, testApis); | |
| if (pluginId) { | |
| consumed.add(pluginId); | |
| } | |
| } | |
| } | |
| return testApis | |
| .filter((testApi) => !consumed.has(testApi.pluginId)) | |
| .map((testApi) => testApi.repoPath) | |
| .toSorted(); | |
| } | |
| describe("extension test API consumption", () => { | |
| it("ignores identifier text and generic loader implementations", () => { | |
| expect( | |
| collectTestApiSourceReferences(` | |
| const testing = {}; | |
| function loadQaRunnerBundledPluginTestApi(pluginId: string) { | |
| return load({ pluginId, artifactBasename: "test-api.js" }); | |
| } | |
| `), | |
| ).toStrictEqual({ moduleSpecifiers: [], pluginIds: [] }); | |
| }); | |
| it("collects real module edges and literal plugin loaders", () => { | |
| expect( | |
| collectTestApiSourceReferences(` | |
| import { testing } from "@openclaw/example/test-api.js"; | |
| export { helper } from "../test-api.js"; | |
| type TestApi = typeof import("./test-api.js"); | |
| loadQaRunnerBundledPluginTestApi("matrix"); | |
| loadBundledPluginFacade({ pluginId: "codex", artifactBasename: "test-api.js" }); | |
| `), | |
| ).toStrictEqual({ | |
| moduleSpecifiers: ["../test-api.js", "./test-api.js", "@openclaw/example/test-api.js"], | |
| pluginIds: ["codex", "matrix"], | |
| }); | |
| }); | |
| it( | |
| "keeps only consumed extension test APIs", | |
| () => expect(collectOrphanExtensionTestApiFiles()).toStrictEqual([]), | |
| 240_000, | |
| ); | |
| }); | |