diff --git a/scripts/check-extension-plugin-sdk-boundary.mjs b/scripts/check-extension-plugin-sdk-boundary.mjs index 90933218501..43046d8ab5f 100644 --- a/scripts/check-extension-plugin-sdk-boundary.mjs +++ b/scripts/check-extension-plugin-sdk-boundary.mjs @@ -43,6 +43,7 @@ function isCodeFile(fileName) { function isTestLikeFile(relativePath) { return ( /(^|\/)(__tests__|fixtures)\//.test(relativePath) || + /(^|\/)[^/]*test-support\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/.test(relativePath) || /\.(test|spec)\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/.test(relativePath) ); } @@ -190,7 +191,20 @@ export async function collectExtensionPluginSdkBoundaryInventory(mode) { } export async function readExpectedInventory(mode) { - return JSON.parse(await fs.readFile(baselinePathByMode[mode], "utf8")); + try { + return JSON.parse(await fs.readFile(baselinePathByMode[mode], "utf8")); + } catch (error) { + if ( + (mode === "plugin-sdk-internal" || mode === "src-outside-plugin-sdk") && + error && + typeof error === "object" && + "code" in error && + error.code === "ENOENT" + ) { + return []; + } + throw error; + } } export function diffInventory(expected, actual) { diff --git a/scripts/check-web-search-provider-boundaries.mjs b/scripts/check-web-search-provider-boundaries.mjs index ae680bc4124..2ba31b465c0 100644 --- a/scripts/check-web-search-provider-boundaries.mjs +++ b/scripts/check-web-search-provider-boundaries.mjs @@ -214,7 +214,14 @@ export async function collectWebSearchProviderBoundaryInventory() { } export async function readExpectedInventory() { - return JSON.parse(await fs.readFile(baselinePath, "utf8")); + try { + return JSON.parse(await fs.readFile(baselinePath, "utf8")); + } catch (error) { + if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") { + return []; + } + throw error; + } } export function diffInventory(expected, actual) { diff --git a/test/extension-plugin-sdk-boundary.test.ts b/test/extension-plugin-sdk-boundary.test.ts index 90372348a95..ea421d2708f 100644 --- a/test/extension-plugin-sdk-boundary.test.ts +++ b/test/extension-plugin-sdk-boundary.test.ts @@ -1,20 +1,18 @@ import { execFileSync } from "node:child_process"; -import { readFileSync } from "node:fs"; import path from "node:path"; import { describe, expect, it } from "vitest"; -import { - collectExtensionPluginSdkBoundaryInventory, - diffInventory, -} from "../scripts/check-extension-plugin-sdk-boundary.mjs"; +import { collectExtensionPluginSdkBoundaryInventory } from "../scripts/check-extension-plugin-sdk-boundary.mjs"; const repoRoot = process.cwd(); const scriptPath = path.join(repoRoot, "scripts", "check-extension-plugin-sdk-boundary.mjs"); -function readBaseline(fileName: string) { - return JSON.parse(readFileSync(path.join(repoRoot, "test", "fixtures", fileName), "utf8")); -} - describe("extension src outside plugin-sdk boundary inventory", () => { + it("is currently empty", async () => { + const inventory = await collectExtensionPluginSdkBoundaryInventory("src-outside-plugin-sdk"); + + expect(inventory).toEqual([]); + }); + it("produces stable sorted output", async () => { const first = await collectExtensionPluginSdkBoundaryInventory("src-outside-plugin-sdk"); const second = await collectExtensionPluginSdkBoundaryInventory("src-outside-plugin-sdk"); @@ -33,31 +31,7 @@ describe("extension src outside plugin-sdk boundary inventory", () => { ).toEqual(first); }); - it("captures known current production violations", async () => { - const inventory = await collectExtensionPluginSdkBoundaryInventory("src-outside-plugin-sdk"); - - expect(inventory).toContainEqual( - expect.objectContaining({ - file: "extensions/brave/src/brave-web-search-provider.ts", - resolvedPath: "src/agents/tools/common.js", - }), - ); - expect(inventory).toContainEqual( - expect.objectContaining({ - file: "extensions/discord/src/runtime-api.ts", - resolvedPath: "src/config/types.secrets.js", - }), - ); - }); - - it("matches the checked-in baseline", async () => { - const expected = readBaseline("extension-src-outside-plugin-sdk-inventory.json"); - const actual = await collectExtensionPluginSdkBoundaryInventory("src-outside-plugin-sdk"); - - expect(diffInventory(expected, actual)).toEqual({ missing: [], unexpected: [] }); - }); - - it("script json output matches the baseline exactly", () => { + it("script json output is empty", () => { const stdout = execFileSync( process.execPath, [scriptPath, "--mode=src-outside-plugin-sdk", "--json"], @@ -67,9 +41,7 @@ describe("extension src outside plugin-sdk boundary inventory", () => { }, ); - expect(JSON.parse(stdout)).toEqual( - readBaseline("extension-src-outside-plugin-sdk-inventory.json"), - ); + expect(JSON.parse(stdout)).toEqual([]); }); }); @@ -80,14 +52,7 @@ describe("extension plugin-sdk-internal boundary inventory", () => { expect(inventory).toEqual([]); }); - it("matches the checked-in empty baseline", async () => { - const expected = readBaseline("extension-plugin-sdk-internal-inventory.json"); - const actual = await collectExtensionPluginSdkBoundaryInventory("plugin-sdk-internal"); - - expect(diffInventory(expected, actual)).toEqual({ missing: [], unexpected: [] }); - }); - - it("script json output matches the empty baseline exactly", () => { + it("script json output is empty", () => { const stdout = execFileSync( process.execPath, [scriptPath, "--mode=plugin-sdk-internal", "--json"], @@ -97,8 +62,6 @@ describe("extension plugin-sdk-internal boundary inventory", () => { }, ); - expect(JSON.parse(stdout)).toEqual( - readBaseline("extension-plugin-sdk-internal-inventory.json"), - ); + expect(JSON.parse(stdout)).toEqual([]); }); }); diff --git a/test/fixtures/extension-plugin-sdk-internal-inventory.json b/test/fixtures/extension-plugin-sdk-internal-inventory.json deleted file mode 100644 index fe51488c706..00000000000 --- a/test/fixtures/extension-plugin-sdk-internal-inventory.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/test/fixtures/extension-src-outside-plugin-sdk-inventory.json b/test/fixtures/extension-src-outside-plugin-sdk-inventory.json deleted file mode 100644 index 3c5aff2a370..00000000000 --- a/test/fixtures/extension-src-outside-plugin-sdk-inventory.json +++ /dev/null @@ -1,418 +0,0 @@ -[ - { - "file": "extensions/discord/src/directory-config.ts", - "line": 7, - "kind": "import", - "specifier": "../../../src/channels/read-only-account-inspect.discord.runtime.js", - "resolvedPath": "src/channels/read-only-account-inspect.discord.runtime.js", - "reason": "imports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/discord/src/directory-config.ts", - "line": 8, - "kind": "import", - "specifier": "../../../src/channels/read-only-account-inspect.js", - "resolvedPath": "src/channels/read-only-account-inspect.js", - "reason": "imports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 10, - "kind": "export", - "specifier": "../../src/agents/tools/common.js", - "resolvedPath": "src/agents/tools/common.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 23, - "kind": "export", - "specifier": "../../src/channels/mention-gating.js", - "resolvedPath": "src/channels/mention-gating.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 30, - "kind": "export", - "specifier": "../../src/channels/plugins/config-schema.js", - "resolvedPath": "src/channels/plugins/config-schema.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 34, - "kind": "export", - "specifier": "../../src/channels/plugins/config-helpers.js", - "resolvedPath": "src/channels/plugins/config-helpers.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 38, - "kind": "export", - "specifier": "../../src/channels/plugins/directory-config-helpers.js", - "resolvedPath": "src/channels/plugins/directory-config-helpers.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 39, - "kind": "export", - "specifier": "../../src/channels/plugins/helpers.js", - "resolvedPath": "src/channels/plugins/helpers.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 40, - "kind": "export", - "specifier": "../../src/channels/plugins/media-limits.js", - "resolvedPath": "src/channels/plugins/media-limits.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 46, - "kind": "export", - "specifier": "../../src/channels/plugins/setup-wizard-helpers.js", - "resolvedPath": "src/channels/plugins/setup-wizard-helpers.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 47, - "kind": "export", - "specifier": "../../src/channels/plugins/pairing-message.js", - "resolvedPath": "src/channels/plugins/pairing-message.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 52, - "kind": "export", - "specifier": "../../src/channels/plugins/setup-helpers.js", - "resolvedPath": "src/channels/plugins/setup-helpers.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 53, - "kind": "export", - "specifier": "../../src/channels/plugins/account-helpers.js", - "resolvedPath": "src/channels/plugins/account-helpers.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 59, - "kind": "export", - "specifier": "../../src/channels/plugins/types.js", - "resolvedPath": "src/channels/plugins/types.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 60, - "kind": "export", - "specifier": "../../src/channels/plugins/types.plugin.js", - "resolvedPath": "src/channels/plugins/types.plugin.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 61, - "kind": "export", - "specifier": "../../src/channels/registry.js", - "resolvedPath": "src/channels/registry.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 62, - "kind": "export", - "specifier": "../../src/channels/reply-prefix.js", - "resolvedPath": "src/channels/reply-prefix.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 63, - "kind": "export", - "specifier": "../../src/config/config.js", - "resolvedPath": "src/config/config.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 64, - "kind": "export", - "specifier": "../../src/config/dangerous-name-matching.js", - "resolvedPath": "src/config/dangerous-name-matching.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 70, - "kind": "export", - "specifier": "../../src/config/runtime-group-policy.js", - "resolvedPath": "src/config/runtime-group-policy.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 75, - "kind": "export", - "specifier": "../../src/config/types.js", - "resolvedPath": "src/config/types.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 76, - "kind": "export", - "specifier": "../../src/config/types.secrets.js", - "resolvedPath": "src/config/types.secrets.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 77, - "kind": "export", - "specifier": "../../src/config/zod-schema.providers-core.js", - "resolvedPath": "src/config/zod-schema.providers-core.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 78, - "kind": "export", - "specifier": "../../src/infra/net/fetch-guard.js", - "resolvedPath": "src/infra/net/fetch-guard.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 79, - "kind": "export", - "specifier": "../../src/infra/outbound/target-errors.js", - "resolvedPath": "src/infra/outbound/target-errors.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 80, - "kind": "export", - "specifier": "../../src/plugins/config-schema.js", - "resolvedPath": "src/plugins/config-schema.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 81, - "kind": "export", - "specifier": "../../src/plugins/runtime/types.js", - "resolvedPath": "src/plugins/runtime/types.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 82, - "kind": "export", - "specifier": "../../src/plugins/types.js", - "resolvedPath": "src/plugins/types.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 83, - "kind": "export", - "specifier": "../../src/routing/session-key.js", - "resolvedPath": "src/routing/session-key.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 84, - "kind": "export", - "specifier": "../../src/security/dm-policy-shared.js", - "resolvedPath": "src/security/dm-policy-shared.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 85, - "kind": "export", - "specifier": "../../src/terminal/links.js", - "resolvedPath": "src/terminal/links.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 86, - "kind": "export", - "specifier": "../../src/wizard/prompts.js", - "resolvedPath": "src/wizard/prompts.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/googlechat/runtime-api.ts", - "line": 89, - "kind": "export", - "specifier": "../../src/pairing/pairing-challenge.js", - "resolvedPath": "src/pairing/pairing-challenge.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/imessage/runtime-api.ts", - "line": 1, - "kind": "export", - "specifier": "../../src/config/types.imessage.js", - "resolvedPath": "src/config/types.imessage.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/imessage/runtime-api.ts", - "line": 2, - "kind": "export", - "specifier": "../../src/channels/plugins/types.plugin.js", - "resolvedPath": "src/channels/plugins/types.plugin.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/imessage/runtime-api.ts", - "line": 15, - "kind": "export", - "specifier": "../../src/channels/plugins/media-limits.js", - "resolvedPath": "src/channels/plugins/media-limits.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/imessage/runtime-api.ts", - "line": 19, - "kind": "export", - "specifier": "../../src/channels/plugins/normalize/imessage.js", - "resolvedPath": "src/channels/plugins/normalize/imessage.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/imessage/runtime-api.ts", - "line": 20, - "kind": "export", - "specifier": "../../src/config/zod-schema.providers-core.js", - "resolvedPath": "src/config/zod-schema.providers-core.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/slack/src/directory-config.ts", - "line": 8, - "kind": "import", - "specifier": "../../../src/channels/plugins/normalize/slack.js", - "resolvedPath": "src/channels/plugins/normalize/slack.js", - "reason": "imports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/slack/src/directory-config.ts", - "line": 9, - "kind": "import", - "specifier": "../../../src/channels/read-only-account-inspect.js", - "resolvedPath": "src/channels/read-only-account-inspect.js", - "reason": "imports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/slack/src/directory-config.ts", - "line": 10, - "kind": "import", - "specifier": "../../../src/channels/read-only-account-inspect.slack.runtime.js", - "resolvedPath": "src/channels/read-only-account-inspect.slack.runtime.js", - "reason": "imports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/slack/src/runtime-api.ts", - "line": 1, - "kind": "export", - "specifier": "../../../src/config/config.js", - "resolvedPath": "src/config/config.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/slack/src/runtime-api.ts", - "line": 2, - "kind": "export", - "specifier": "../../../src/config/types.slack.js", - "resolvedPath": "src/config/types.slack.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/slack/src/runtime-api.ts", - "line": 3, - "kind": "export", - "specifier": "../../../src/channels/plugins/types.js", - "resolvedPath": "src/channels/plugins/types.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/slack/src/runtime-api.ts", - "line": 19, - "kind": "export", - "specifier": "../../../src/channels/plugins/normalize/slack.js", - "resolvedPath": "src/channels/plugins/normalize/slack.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/slack/src/runtime-api.ts", - "line": 23, - "kind": "export", - "specifier": "../../../src/channels/account-snapshot-fields.js", - "resolvedPath": "src/channels/account-snapshot-fields.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/slack/src/runtime-api.ts", - "line": 24, - "kind": "export", - "specifier": "../../../src/config/zod-schema.providers-core.js", - "resolvedPath": "src/config/zod-schema.providers-core.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/slack/src/runtime-api.ts", - "line": 32, - "kind": "export", - "specifier": "../../../src/agents/tools/common.js", - "resolvedPath": "src/agents/tools/common.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/slack/src/runtime-api.ts", - "line": 33, - "kind": "export", - "specifier": "../../../src/agents/date-time.js", - "resolvedPath": "src/agents/date-time.js", - "reason": "re-exports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/telegram/src/directory-config.ts", - "line": 9, - "kind": "import", - "specifier": "../../../src/channels/read-only-account-inspect.js", - "resolvedPath": "src/channels/read-only-account-inspect.js", - "reason": "imports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/telegram/src/directory-config.ts", - "line": 10, - "kind": "import", - "specifier": "../../../src/channels/read-only-account-inspect.telegram.runtime.js", - "resolvedPath": "src/channels/read-only-account-inspect.telegram.runtime.js", - "reason": "imports core src path outside plugin-sdk from an extension" - }, - { - "file": "extensions/whatsapp/src/directory-config.ts", - "line": 6, - "kind": "import", - "specifier": "../../../src/whatsapp/normalize.js", - "resolvedPath": "src/whatsapp/normalize.js", - "reason": "imports core src path outside plugin-sdk from an extension" - } -] diff --git a/test/fixtures/web-search-provider-boundary-inventory.json b/test/fixtures/web-search-provider-boundary-inventory.json deleted file mode 100644 index fe51488c706..00000000000 --- a/test/fixtures/web-search-provider-boundary-inventory.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/test/web-search-provider-boundary.test.ts b/test/web-search-provider-boundary.test.ts index b75c137ca98..f211a262ca3 100644 --- a/test/web-search-provider-boundary.test.ts +++ b/test/web-search-provider-boundary.test.ts @@ -1,24 +1,10 @@ import { execFileSync } from "node:child_process"; -import { readFileSync } from "node:fs"; import path from "node:path"; import { describe, expect, it } from "vitest"; -import { - collectWebSearchProviderBoundaryInventory, - diffInventory, -} from "../scripts/check-web-search-provider-boundaries.mjs"; +import { collectWebSearchProviderBoundaryInventory } from "../scripts/check-web-search-provider-boundaries.mjs"; const repoRoot = process.cwd(); const scriptPath = path.join(repoRoot, "scripts", "check-web-search-provider-boundaries.mjs"); -const baselinePath = path.join( - repoRoot, - "test", - "fixtures", - "web-search-provider-boundary-inventory.json", -); - -function readBaseline() { - return JSON.parse(readFileSync(baselinePath, "utf8")); -} describe("web search provider boundary inventory", () => { it("has no remaining production inventory in core", async () => { @@ -49,20 +35,12 @@ describe("web search provider boundary inventory", () => { ).toEqual(first); }); - it("matches the checked-in baseline", async () => { - const expected = readBaseline(); - const actual = await collectWebSearchProviderBoundaryInventory(); - - expect(diffInventory(expected, actual)).toEqual({ missing: [], unexpected: [] }); - expect(actual).toEqual([]); - }); - - it("script json output matches the baseline exactly", () => { + it("script json output is empty", () => { const stdout = execFileSync(process.execPath, [scriptPath, "--json"], { cwd: repoRoot, encoding: "utf8", }); - expect(JSON.parse(stdout)).toEqual(readBaseline()); + expect(JSON.parse(stdout)).toEqual([]); }); });