





















@@ -9,6 +9,12 @@ const ALLOWED_EXTENSION_PUBLIC_SURFACE_BASENAMES = new Set(
99GUARDED_EXTENSION_PUBLIC_SURFACE_BASENAMES,
1010);
1111const CHANNEL_CONTRACT_TEST_HELPERS_PREFIX = "src/channels/plugins/contracts/test-helpers/";
12+const BUNDLED_PLUGIN_RESOLVER_TEST_FILES = [
13+"src/plugin-sdk/facade-loader.test.ts",
14+"src/plugins/public-surface-loader.test.ts",
15+"src/plugins/public-surface-runtime.test.ts",
16+] as const;
17+const BROAD_PUBLIC_SOURCE_ARTIFACT_BASENAMES = new Set(["api.js", "runtime-api.js"]);
1218const ROOTDIR_BOUNDARY_CANARY_RE =
1319/(^|\/)__rootdir_boundary_canary__\.(?:[cm]?ts|[cm]?js|tsx|jsx)$/u;
1420@@ -93,6 +99,41 @@ function getImportBasename(importPath: string): string {
9399return importPath.split("/").at(-1) ?? importPath;
94100}
95101102+function collectBundledPluginIds(): Set<string> {
103+return new Set(
104+fs
105+.readdirSync(path.join(repoRoot, "extensions"), { withFileTypes: true })
106+.filter((entry) => entry.isDirectory())
107+.map((entry) => entry.name),
108+);
109+}
110+111+function getLineNumber(source: string, index: number): number {
112+return source.slice(0, index).split("\n").length;
113+}
114+115+function findRealBroadSourceApiResolverReferences(
116+source: string,
117+pluginIds: Set<string>,
118+): string[] {
119+const offenders: string[] = [];
120+for (const match of source.matchAll(/\{[^{}]*\bdirName:\s*["'][^"']+["'][^{}]*\}/g)) {
121+const objectLiteral = match[0];
122+const dirName = objectLiteral.match(/\bdirName:\s*["']([^"']+)["']/)?.[1];
123+const artifactBasename = objectLiteral.match(/\bartifactBasename:\s*["']([^"']+)["']/)?.[1];
124+if (
125+dirName &&
126+artifactBasename &&
127+pluginIds.has(dirName) &&
128+BROAD_PUBLIC_SOURCE_ARTIFACT_BASENAMES.has(artifactBasename)
129+) {
130+offenders.push(`${dirName}/${artifactBasename}:${getLineNumber(source, match.index ?? 0)}`);
131+}
132+}
133+134+return offenders;
135+}
136+96137function isAllowedCoreContractSuite(file: string, imports: readonly string[]): boolean {
97138return (
98139file.startsWith("src/channels/plugins/contracts/") &&
@@ -190,6 +231,18 @@ describe("non-extension test boundaries", () => {
190231expect(offenders).toEqual([]);
191232});
192233234+it("keeps resolver tests on generated fixtures for broad bundled plugin source APIs", () => {
235+const bundledPluginIds = collectBundledPluginIds();
236+const offenders = BUNDLED_PLUGIN_RESOLVER_TEST_FILES.flatMap((file) => {
237+const source = fs.readFileSync(path.join(repoRoot, file), "utf8");
238+return findRealBroadSourceApiResolverReferences(source, bundledPluginIds).map(
239+(reference) => `${file}: ${reference}`,
240+);
241+});
242+243+expect(offenders).toEqual([]);
244+});
245+193246it("keeps bundled channel security collector coverage under extension tests", () => {
194247const files = [...walk(path.join(repoRoot, "src")), ...walk(path.join(repoRoot, "test"))]
195248.filter((file) => !file.startsWith(BUNDLED_PLUGIN_PATH_PREFIX))
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。