diff --git a/scripts/lib/extension-test-plan.mjs b/scripts/lib/extension-test-plan.mjs index 93f7ee67fe4..fd4fe636c46 100644 --- a/scripts/lib/extension-test-plan.mjs +++ b/scripts/lib/extension-test-plan.mjs @@ -4,9 +4,11 @@ import { channelTestRoots } from "../../vitest.channel-paths.mjs"; import { isAcpxExtensionRoot } from "../../vitest.extension-acpx-paths.mjs"; import { isBlueBubblesExtensionRoot } from "../../vitest.extension-bluebubbles-paths.mjs"; import { isDiffsExtensionRoot } from "../../vitest.extension-diffs-paths.mjs"; +import { isFeishuExtensionRoot } from "../../vitest.extension-feishu-paths.mjs"; import { isMatrixExtensionRoot } from "../../vitest.extension-matrix-paths.mjs"; import { isMemoryExtensionRoot } from "../../vitest.extension-memory-paths.mjs"; import { isMessagingExtensionRoot } from "../../vitest.extension-messaging-paths.mjs"; +import { isMsTeamsExtensionRoot } from "../../vitest.extension-msteams-paths.mjs"; import { isProviderExtensionRoot } from "../../vitest.extension-provider-paths.mjs"; import { isTelegramExtensionRoot } from "../../vitest.extension-telegram-paths.mjs"; import { BUNDLED_PLUGIN_PATH_PREFIX, BUNDLED_PLUGIN_ROOT_DIR } from "./bundled-plugin-paths.mjs"; @@ -100,9 +102,11 @@ export function resolveExtensionTestPlan(params = {}) { const usesAcpxConfig = roots.some((root) => isAcpxExtensionRoot(root)); const usesDiffsConfig = roots.some((root) => isDiffsExtensionRoot(root)); const usesBlueBubblesConfig = roots.some((root) => isBlueBubblesExtensionRoot(root)); + const usesFeishuConfig = roots.some((root) => isFeishuExtensionRoot(root)); const usesTelegramConfig = roots.some((root) => isTelegramExtensionRoot(root)); const usesMatrixConfig = roots.some((root) => isMatrixExtensionRoot(root)); const usesMemoryConfig = roots.some((root) => isMemoryExtensionRoot(root)); + const usesMsTeamsConfig = roots.some((root) => isMsTeamsExtensionRoot(root)); const usesMessagingConfig = roots.some((root) => isMessagingExtensionRoot(root)); const usesProviderConfig = roots.some((root) => isProviderExtensionRoot(root)); const config = usesChannelConfig @@ -113,17 +117,21 @@ export function resolveExtensionTestPlan(params = {}) { ? "vitest.extension-diffs.config.ts" : usesBlueBubblesConfig ? "vitest.extension-bluebubbles.config.ts" - : usesMatrixConfig - ? "vitest.extension-matrix.config.ts" - : usesTelegramConfig - ? "vitest.extension-telegram.config.ts" - : usesMemoryConfig - ? "vitest.extension-memory.config.ts" - : usesMessagingConfig - ? "vitest.extension-messaging.config.ts" - : usesProviderConfig - ? "vitest.extension-providers.config.ts" - : "vitest.extensions.config.ts"; + : usesFeishuConfig + ? "vitest.extension-feishu.config.ts" + : usesMatrixConfig + ? "vitest.extension-matrix.config.ts" + : usesTelegramConfig + ? "vitest.extension-telegram.config.ts" + : usesMemoryConfig + ? "vitest.extension-memory.config.ts" + : usesMsTeamsConfig + ? "vitest.extension-msteams.config.ts" + : usesMessagingConfig + ? "vitest.extension-messaging.config.ts" + : usesProviderConfig + ? "vitest.extension-providers.config.ts" + : "vitest.extensions.config.ts"; const testFileCount = roots.reduce( (sum, root) => sum + countTestFiles(path.join(repoRoot, root)), 0, diff --git a/scripts/test-projects.test-support.mjs b/scripts/test-projects.test-support.mjs index f2445073a68..dc4b05f2fc8 100644 --- a/scripts/test-projects.test-support.mjs +++ b/scripts/test-projects.test-support.mjs @@ -5,9 +5,11 @@ import { isChannelSurfaceTestFile } from "../vitest.channel-paths.mjs"; import { isAcpxExtensionRoot } from "../vitest.extension-acpx-paths.mjs"; import { isBlueBubblesExtensionRoot } from "../vitest.extension-bluebubbles-paths.mjs"; import { isDiffsExtensionRoot } from "../vitest.extension-diffs-paths.mjs"; +import { isFeishuExtensionRoot } from "../vitest.extension-feishu-paths.mjs"; import { isMatrixExtensionRoot } from "../vitest.extension-matrix-paths.mjs"; import { isMemoryExtensionRoot } from "../vitest.extension-memory-paths.mjs"; import { isMessagingExtensionRoot } from "../vitest.extension-messaging-paths.mjs"; +import { isMsTeamsExtensionRoot } from "../vitest.extension-msteams-paths.mjs"; import { isProviderExtensionRoot } from "../vitest.extension-provider-paths.mjs"; import { isTelegramExtensionRoot } from "../vitest.extension-telegram-paths.mjs"; import { isBoundaryTestFile, isBundledPluginDependentUnitTestFile } from "../vitest.unit-paths.mjs"; @@ -29,13 +31,16 @@ const EXTENSION_ACPX_VITEST_CONFIG = "vitest.extension-acpx.config.ts"; const EXTENSION_BLUEBUBBLES_VITEST_CONFIG = "vitest.extension-bluebubbles.config.ts"; const EXTENSION_CHANNELS_VITEST_CONFIG = "vitest.extension-channels.config.ts"; const EXTENSION_DIFFS_VITEST_CONFIG = "vitest.extension-diffs.config.ts"; +const EXTENSION_FEISHU_VITEST_CONFIG = "vitest.extension-feishu.config.ts"; const EXTENSION_MATRIX_VITEST_CONFIG = "vitest.extension-matrix.config.ts"; const EXTENSION_MEMORY_VITEST_CONFIG = "vitest.extension-memory.config.ts"; +const EXTENSION_MSTEAMS_VITEST_CONFIG = "vitest.extension-msteams.config.ts"; const EXTENSION_MESSAGING_VITEST_CONFIG = "vitest.extension-messaging.config.ts"; const EXTENSION_PROVIDERS_VITEST_CONFIG = "vitest.extension-providers.config.ts"; const EXTENSION_TELEGRAM_VITEST_CONFIG = "vitest.extension-telegram.config.ts"; const EXTENSIONS_VITEST_CONFIG = "vitest.extensions.config.ts"; const GATEWAY_VITEST_CONFIG = "vitest.gateway.config.ts"; +const HOOKS_VITEST_CONFIG = "vitest.hooks.config.ts"; const INFRA_VITEST_CONFIG = "vitest.infra.config.ts"; const MEDIA_VITEST_CONFIG = "vitest.media.config.ts"; const MEDIA_UNDERSTANDING_VITEST_CONFIG = "vitest.media-understanding.config.ts"; @@ -45,6 +50,7 @@ const RUNTIME_CONFIG_VITEST_CONFIG = "vitest.runtime-config.config.ts"; const SECRETS_VITEST_CONFIG = "vitest.secrets.config.ts"; const SHARED_CORE_VITEST_CONFIG = "vitest.shared-core.config.ts"; const TOOLING_VITEST_CONFIG = "vitest.tooling.config.ts"; +const TUI_VITEST_CONFIG = "vitest.tui.config.ts"; const UI_VITEST_CONFIG = "vitest.ui.config.ts"; const INCLUDE_FILE_ENV_KEY = "OPENCLAW_VITEST_INCLUDE_FILE"; @@ -118,6 +124,9 @@ function classifyTarget(arg, cwd) { if (isBlueBubblesExtensionRoot(extensionRoot)) { return "extensionBlueBubbles"; } + if (isFeishuExtensionRoot(extensionRoot)) { + return "extensionFeishu"; + } if (isTelegramExtensionRoot(extensionRoot)) { return "extensionTelegram"; } @@ -127,6 +136,9 @@ function classifyTarget(arg, cwd) { if (isMemoryExtensionRoot(extensionRoot)) { return "extensionMemory"; } + if (isMsTeamsExtensionRoot(extensionRoot)) { + return "extensionMsTeams"; + } if (isMessagingExtensionRoot(extensionRoot)) { return "extensionMessaging"; } @@ -161,6 +173,9 @@ function classifyTarget(arg, cwd) { if (relative.startsWith("src/gateway/")) { return "gateway"; } + if (relative.startsWith("src/hooks/")) { + return "hooks"; + } if (relative.startsWith("src/infra/")) { return "infra"; } @@ -188,6 +203,9 @@ function classifyTarget(arg, cwd) { if (relative.startsWith("src/shared/")) { return "sharedCore"; } + if (relative.startsWith("src/tui/")) { + return "tui"; + } if (relative.startsWith("src/acp/")) { return "acp"; } @@ -280,6 +298,7 @@ export function buildVitestRunPlans(args, cwd = process.cwd()) { "contracts", "bundled", "gateway", + "hooks", "infra", "runtimeConfig", "cron", @@ -288,6 +307,7 @@ export function buildVitestRunPlans(args, cwd = process.cwd()) { "pluginSdk", "secrets", "sharedCore", + "tui", "mediaUnderstanding", "acp", "cli", @@ -300,10 +320,12 @@ export function buildVitestRunPlans(args, cwd = process.cwd()) { "extensionAcpx", "extensionDiffs", "extensionBlueBubbles", + "extensionFeishu", "extensionChannel", "extensionTelegram", "extensionMatrix", "extensionMemory", + "extensionMsTeams", "extensionMessaging", "extensionProvider", "channel", @@ -326,63 +348,73 @@ export function buildVitestRunPlans(args, cwd = process.cwd()) { ? BUNDLED_VITEST_CONFIG : kind === "gateway" ? GATEWAY_VITEST_CONFIG - : kind === "infra" - ? INFRA_VITEST_CONFIG - : kind === "runtimeConfig" - ? RUNTIME_CONFIG_VITEST_CONFIG - : kind === "cron" - ? CRON_VITEST_CONFIG - : kind === "daemon" - ? DAEMON_VITEST_CONFIG - : kind === "media" - ? MEDIA_VITEST_CONFIG - : kind === "pluginSdk" - ? PLUGIN_SDK_VITEST_CONFIG - : kind === "secrets" - ? SECRETS_VITEST_CONFIG - : kind === "sharedCore" - ? SHARED_CORE_VITEST_CONFIG - : kind === "mediaUnderstanding" - ? MEDIA_UNDERSTANDING_VITEST_CONFIG - : kind === "acp" - ? ACP_VITEST_CONFIG - : kind === "cli" - ? CLI_VITEST_CONFIG - : kind === "command" - ? COMMANDS_VITEST_CONFIG - : kind === "autoReply" - ? AUTO_REPLY_VITEST_CONFIG - : kind === "agent" - ? AGENTS_VITEST_CONFIG - : kind === "plugin" - ? PLUGINS_VITEST_CONFIG - : kind === "ui" - ? UI_VITEST_CONFIG - : kind === "e2e" - ? E2E_VITEST_CONFIG - : kind === "extensionAcpx" - ? EXTENSION_ACPX_VITEST_CONFIG - : kind === "extensionDiffs" - ? EXTENSION_DIFFS_VITEST_CONFIG - : kind === "extensionBlueBubbles" - ? EXTENSION_BLUEBUBBLES_VITEST_CONFIG - : kind === "extensionChannel" - ? EXTENSION_CHANNELS_VITEST_CONFIG - : kind === "extensionTelegram" - ? EXTENSION_TELEGRAM_VITEST_CONFIG - : kind === "extensionMatrix" - ? EXTENSION_MATRIX_VITEST_CONFIG - : kind === "extensionMemory" - ? EXTENSION_MEMORY_VITEST_CONFIG - : kind === "extensionMessaging" - ? EXTENSION_MESSAGING_VITEST_CONFIG - : kind === "extensionProvider" - ? EXTENSION_PROVIDERS_VITEST_CONFIG - : kind === "channel" - ? CHANNEL_VITEST_CONFIG - : kind === "extension" - ? EXTENSIONS_VITEST_CONFIG - : DEFAULT_VITEST_CONFIG; + : kind === "hooks" + ? HOOKS_VITEST_CONFIG + : kind === "infra" + ? INFRA_VITEST_CONFIG + : kind === "runtimeConfig" + ? RUNTIME_CONFIG_VITEST_CONFIG + : kind === "cron" + ? CRON_VITEST_CONFIG + : kind === "daemon" + ? DAEMON_VITEST_CONFIG + : kind === "media" + ? MEDIA_VITEST_CONFIG + : kind === "pluginSdk" + ? PLUGIN_SDK_VITEST_CONFIG + : kind === "secrets" + ? SECRETS_VITEST_CONFIG + : kind === "sharedCore" + ? SHARED_CORE_VITEST_CONFIG + : kind === "tui" + ? TUI_VITEST_CONFIG + : kind === "mediaUnderstanding" + ? MEDIA_UNDERSTANDING_VITEST_CONFIG + : kind === "acp" + ? ACP_VITEST_CONFIG + : kind === "cli" + ? CLI_VITEST_CONFIG + : kind === "command" + ? COMMANDS_VITEST_CONFIG + : kind === "autoReply" + ? AUTO_REPLY_VITEST_CONFIG + : kind === "agent" + ? AGENTS_VITEST_CONFIG + : kind === "plugin" + ? PLUGINS_VITEST_CONFIG + : kind === "ui" + ? UI_VITEST_CONFIG + : kind === "e2e" + ? E2E_VITEST_CONFIG + : kind === "extensionAcpx" + ? EXTENSION_ACPX_VITEST_CONFIG + : kind === "extensionDiffs" + ? EXTENSION_DIFFS_VITEST_CONFIG + : kind === "extensionBlueBubbles" + ? EXTENSION_BLUEBUBBLES_VITEST_CONFIG + : kind === "extensionFeishu" + ? EXTENSION_FEISHU_VITEST_CONFIG + : kind === "extensionChannel" + ? EXTENSION_CHANNELS_VITEST_CONFIG + : kind === "extensionTelegram" + ? EXTENSION_TELEGRAM_VITEST_CONFIG + : kind === "extensionMatrix" + ? EXTENSION_MATRIX_VITEST_CONFIG + : kind === "extensionMemory" + ? EXTENSION_MEMORY_VITEST_CONFIG + : kind === "extensionMsTeams" + ? EXTENSION_MSTEAMS_VITEST_CONFIG + : kind === + "extensionMessaging" + ? EXTENSION_MESSAGING_VITEST_CONFIG + : kind === + "extensionProvider" + ? EXTENSION_PROVIDERS_VITEST_CONFIG + : kind === "channel" + ? CHANNEL_VITEST_CONFIG + : kind === "extension" + ? EXTENSIONS_VITEST_CONFIG + : DEFAULT_VITEST_CONFIG; const includePatterns = kind === "default" || kind === "e2e" ? null diff --git a/src/scripts/test-projects.test.ts b/src/scripts/test-projects.test.ts index 24864863e91..aaa294adb96 100644 --- a/src/scripts/test-projects.test.ts +++ b/src/scripts/test-projects.test.ts @@ -212,6 +212,17 @@ describe("test-projects args", () => { ]); }); + it("routes tui targets to the tui config", () => { + expect(buildVitestRunPlans(["src/tui/tui.test.ts"])).toEqual([ + { + config: "vitest.tui.config.ts", + forwardedArgs: [], + includePatterns: ["src/tui/tui.test.ts"], + watchMode: false, + }, + ]); + }); + it("routes media-understanding targets to the media-understanding config", () => { expect(buildVitestRunPlans(["src/media-understanding/runtime.test.ts"])).toEqual([ { @@ -267,6 +278,17 @@ describe("test-projects args", () => { ]); }); + it("routes hooks targets to the hooks config", () => { + expect(buildVitestRunPlans(["src/hooks/install.test.ts"])).toEqual([ + { + config: "vitest.hooks.config.ts", + forwardedArgs: [], + includePatterns: ["src/hooks/install.test.ts"], + watchMode: false, + }, + ]); + }); + it("routes channel targets to the channels config", () => { expect(buildVitestRunPlans(["src/channels/ids.test.ts"])).toEqual([ { @@ -364,6 +386,17 @@ describe("test-projects args", () => { ]); }); + it("routes msteams extension tests to the msteams config", () => { + expect(buildVitestRunPlans(["extensions/msteams/src/config.test.ts"])).toEqual([ + { + config: "vitest.extension-msteams.config.ts", + forwardedArgs: [], + includePatterns: ["extensions/msteams/src/config.test.ts"], + watchMode: false, + }, + ]); + }); + it("routes telegram extension tests to the telegram config", () => { expect(buildVitestRunPlans(["extensions/telegram/src/fetch.test.ts"])).toEqual([ { @@ -397,6 +430,17 @@ describe("test-projects args", () => { ]); }); + it("routes feishu extension tests to the feishu config", () => { + expect(buildVitestRunPlans(["extensions/feishu/src/channel.test.ts"])).toEqual([ + { + config: "vitest.extension-feishu.config.ts", + forwardedArgs: [], + includePatterns: ["extensions/feishu/src/channel.test.ts"], + watchMode: false, + }, + ]); + }); + it("routes acpx extension tests to the acpx config", () => { expect(buildVitestRunPlans(["extensions/acpx/src/runtime.test.ts"])).toEqual([ { diff --git a/test/scripts/test-extension.test.ts b/test/scripts/test-extension.test.ts index 7300a3094fd..f718a94baa2 100644 --- a/test/scripts/test-extension.test.ts +++ b/test/scripts/test-extension.test.ts @@ -70,6 +70,15 @@ describe("scripts/test-extension.mjs", () => { expect(plan.hasTests).toBe(true); }); + it("resolves feishu onto the feishu vitest config", () => { + const plan = resolveExtensionTestPlan({ targetArg: "feishu", cwd: process.cwd() }); + + expect(plan.extensionId).toBe("feishu"); + expect(plan.config).toBe("vitest.extension-feishu.config.ts"); + expect(plan.roots).toContain(bundledPluginRoot("feishu")); + expect(plan.hasTests).toBe(true); + }); + it("resolves provider extensions onto the provider vitest config", () => { const plan = resolveExtensionTestPlan({ targetArg: "openai", cwd: process.cwd() }); @@ -106,6 +115,15 @@ describe("scripts/test-extension.mjs", () => { expect(plan.hasTests).toBe(true); }); + it("resolves msteams onto the msteams vitest config", () => { + const plan = resolveExtensionTestPlan({ targetArg: "msteams", cwd: process.cwd() }); + + expect(plan.extensionId).toBe("msteams"); + expect(plan.config).toBe("vitest.extension-msteams.config.ts"); + expect(plan.roots).toContain(bundledPluginRoot("msteams")); + expect(plan.hasTests).toBe(true); + }); + it("keeps non-provider extensions on the shared extensions vitest config", () => { const plan = resolveExtensionTestPlan({ targetArg: "firecrawl", cwd: process.cwd() }); @@ -182,6 +200,8 @@ describe("scripts/test-extension.mjs", () => { "matrix", "telegram", "memory-core", + "msteams", + "feishu", "bluebubbles", "acpx", "diffs", @@ -192,10 +212,12 @@ describe("scripts/test-extension.mjs", () => { "acpx", "bluebubbles", "diffs", + "feishu", "firecrawl", "line", "matrix", "memory-core", + "msteams", "openai", "slack", "telegram", @@ -225,6 +247,12 @@ describe("scripts/test-extension.mjs", () => { roots: [bundledPluginRoot("diffs")], testFileCount: expect.any(Number), }, + { + config: "vitest.extension-feishu.config.ts", + extensionIds: ["feishu"], + roots: [bundledPluginRoot("feishu")], + testFileCount: expect.any(Number), + }, { config: "vitest.extension-matrix.config.ts", extensionIds: ["matrix"], @@ -237,6 +265,12 @@ describe("scripts/test-extension.mjs", () => { roots: [bundledPluginRoot("memory-core")], testFileCount: expect.any(Number), }, + { + config: "vitest.extension-msteams.config.ts", + extensionIds: ["msteams"], + roots: [bundledPluginRoot("msteams")], + testFileCount: expect.any(Number), + }, { config: "vitest.extension-providers.config.ts", extensionIds: ["openai"], diff --git a/test/vitest-scoped-config.test.ts b/test/vitest-scoped-config.test.ts index 20c6b75c5c9..1692eb05219 100644 --- a/test/vitest-scoped-config.test.ts +++ b/test/vitest-scoped-config.test.ts @@ -14,13 +14,16 @@ import { createExtensionAcpxVitestConfig } from "../vitest.extension-acpx.config import { createExtensionBlueBubblesVitestConfig } from "../vitest.extension-bluebubbles.config.ts"; import { createExtensionChannelsVitestConfig } from "../vitest.extension-channels.config.ts"; import { createExtensionDiffsVitestConfig } from "../vitest.extension-diffs.config.ts"; +import { createExtensionFeishuVitestConfig } from "../vitest.extension-feishu.config.ts"; import { createExtensionMatrixVitestConfig } from "../vitest.extension-matrix.config.ts"; import { createExtensionMemoryVitestConfig } from "../vitest.extension-memory.config.ts"; import { createExtensionMessagingVitestConfig } from "../vitest.extension-messaging.config.ts"; +import { createExtensionMsTeamsVitestConfig } from "../vitest.extension-msteams.config.ts"; import { createExtensionProvidersVitestConfig } from "../vitest.extension-providers.config.ts"; import { createExtensionTelegramVitestConfig } from "../vitest.extension-telegram.config.ts"; import { createExtensionsVitestConfig } from "../vitest.extensions.config.ts"; import { createGatewayVitestConfig } from "../vitest.gateway.config.ts"; +import { createHooksVitestConfig } from "../vitest.hooks.config.ts"; import { createInfraVitestConfig } from "../vitest.infra.config.ts"; import { createMediaUnderstandingVitestConfig } from "../vitest.media-understanding.config.ts"; import { createMediaVitestConfig } from "../vitest.media.config.ts"; @@ -31,6 +34,7 @@ import { createScopedVitestConfig, resolveVitestIsolation } from "../vitest.scop import { createSecretsVitestConfig } from "../vitest.secrets.config.ts"; import { createSharedCoreVitestConfig } from "../vitest.shared-core.config.ts"; import { createToolingVitestConfig } from "../vitest.tooling.config.ts"; +import { createTuiVitestConfig } from "../vitest.tui.config.ts"; import { createUiVitestConfig } from "../vitest.ui.config.ts"; import { BUNDLED_PLUGIN_TEST_GLOB, bundledPluginFile } from "./helpers/bundled-plugin-paths.js"; @@ -99,12 +103,15 @@ describe("scoped vitest configs", () => { const defaultExtensionBlueBubblesConfig = createExtensionBlueBubblesVitestConfig({}); const defaultExtensionChannelsConfig = createExtensionChannelsVitestConfig({}); const defaultExtensionDiffsConfig = createExtensionDiffsVitestConfig({}); + const defaultExtensionFeishuConfig = createExtensionFeishuVitestConfig({}); const defaultExtensionMatrixConfig = createExtensionMatrixVitestConfig({}); const defaultExtensionMemoryConfig = createExtensionMemoryVitestConfig({}); + const defaultExtensionMsTeamsConfig = createExtensionMsTeamsVitestConfig({}); const defaultExtensionMessagingConfig = createExtensionMessagingVitestConfig({}); const defaultExtensionProvidersConfig = createExtensionProvidersVitestConfig({}); const defaultExtensionTelegramConfig = createExtensionTelegramVitestConfig({}); const defaultGatewayConfig = createGatewayVitestConfig({}); + const defaultHooksConfig = createHooksVitestConfig({}); const defaultInfraConfig = createInfraVitestConfig({}); const defaultPluginSdkConfig = createPluginSdkVitestConfig({}); const defaultSecretsConfig = createSecretsVitestConfig({}); @@ -119,6 +126,7 @@ describe("scoped vitest configs", () => { const defaultAgentsConfig = createAgentsVitestConfig({}); const defaultPluginsConfig = createPluginsVitestConfig({}); const defaultToolingConfig = createToolingVitestConfig({}); + const defaultTuiConfig = createTuiVitestConfig({}); const defaultUiConfig = createUiVitestConfig({}); it("defaults channel tests to non-isolated mode", () => { @@ -192,6 +200,11 @@ describe("scoped vitest configs", () => { expect(defaultExtensionDiffsConfig.test?.include).toEqual(["diffs/**/*.test.ts"]); }); + it("normalizes feishu extension include patterns relative to the scoped dir", () => { + expect(defaultExtensionFeishuConfig.test?.dir).toBe("extensions"); + expect(defaultExtensionFeishuConfig.test?.include).toEqual(["feishu/**/*.test.ts"]); + }); + it("normalizes extension include patterns relative to the scoped dir", () => { expect(defaultExtensionsConfig.test?.dir).toBe("extensions"); expect(defaultExtensionsConfig.test?.include).toEqual(["**/*.test.ts"]); @@ -207,7 +220,7 @@ describe("scoped vitest configs", () => { it("normalizes extension messaging include patterns relative to the scoped dir", () => { expect(defaultExtensionMessagingConfig.test?.dir).toBe("extensions"); expect(defaultExtensionMessagingConfig.test?.include).toEqual( - expect.arrayContaining(["feishu/**/*.test.ts"]), + expect.arrayContaining(["googlechat/**/*.test.ts"]), ); }); @@ -216,6 +229,11 @@ describe("scoped vitest configs", () => { expect(defaultExtensionMatrixConfig.test?.include).toEqual(["matrix/**/*.test.ts"]); }); + it("normalizes msteams extension include patterns relative to the scoped dir", () => { + expect(defaultExtensionMsTeamsConfig.test?.dir).toBe("extensions"); + expect(defaultExtensionMsTeamsConfig.test?.include).toEqual(["msteams/**/*.test.ts"]); + }); + it("normalizes telegram extension include patterns relative to the scoped dir", () => { expect(defaultExtensionTelegramConfig.test?.dir).toBe("extensions"); expect(defaultExtensionTelegramConfig.test?.include).toEqual(["telegram/**/*.test.ts"]); @@ -275,6 +293,11 @@ describe("scoped vitest configs", () => { expect(defaultSecretsConfig.test?.include).toEqual(["**/*.test.ts"]); }); + it("normalizes hooks include patterns relative to the scoped dir", () => { + expect(defaultHooksConfig.test?.dir).toBe("src/hooks"); + expect(defaultHooksConfig.test?.include).toEqual(["**/*.test.ts"]); + }); + it("keeps memory plugin tests out of the shared extensions lane", () => { const extensionExcludes = defaultExtensionsConfig.test?.exclude ?? []; expect( @@ -293,6 +316,13 @@ describe("scoped vitest configs", () => { ).toBe(true); }); + it("keeps feishu tests out of the shared extensions lane", () => { + const extensionExcludes = defaultExtensionsConfig.test?.exclude ?? []; + expect( + extensionExcludes.some((pattern) => path.matchesGlob("feishu/src/channel.test.ts", pattern)), + ).toBe(true); + }); + it("keeps acpx tests out of the shared extensions lane", () => { const extensionExcludes = defaultExtensionsConfig.test?.exclude ?? []; expect( @@ -347,6 +377,11 @@ describe("scoped vitest configs", () => { expect(defaultSharedCoreConfig.test?.include).toEqual(["shared/**/*.test.ts"]); }); + it("normalizes tui include patterns relative to the scoped dir", () => { + expect(defaultTuiConfig.test?.dir).toBe("src"); + expect(defaultTuiConfig.test?.include).toEqual(["tui/**/*.test.ts"]); + }); + it("normalizes media-understanding include patterns relative to the scoped dir", () => { expect(defaultMediaUnderstandingConfig.test?.dir).toBe("src"); expect(defaultMediaUnderstandingConfig.test?.include).toEqual([ diff --git a/vitest.config.ts b/vitest.config.ts index 5e0d7c96a55..88e66992bff 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -14,6 +14,7 @@ export const rootVitestProjects = [ "vitest.contracts.config.ts", "vitest.bundled.config.ts", "vitest.gateway.config.ts", + "vitest.hooks.config.ts", "vitest.acp.config.ts", "vitest.runtime-config.config.ts", "vitest.secrets.config.ts", @@ -29,14 +30,17 @@ export const rootVitestProjects = [ "vitest.media-understanding.config.ts", "vitest.shared-core.config.ts", "vitest.tooling.config.ts", + "vitest.tui.config.ts", "vitest.ui.config.ts", "vitest.channels.config.ts", "vitest.extension-acpx.config.ts", "vitest.extension-bluebubbles.config.ts", "vitest.extension-channels.config.ts", "vitest.extension-diffs.config.ts", + "vitest.extension-feishu.config.ts", "vitest.extension-matrix.config.ts", "vitest.extension-memory.config.ts", + "vitest.extension-msteams.config.ts", "vitest.extension-messaging.config.ts", "vitest.extension-providers.config.ts", "vitest.extension-telegram.config.ts", diff --git a/vitest.extension-feishu-paths.mjs b/vitest.extension-feishu-paths.mjs new file mode 100644 index 00000000000..f7cfd5c25cb --- /dev/null +++ b/vitest.extension-feishu-paths.mjs @@ -0,0 +1,9 @@ +import { bundledPluginRoot } from "./scripts/lib/bundled-plugin-paths.mjs"; + +export const feishuExtensionIds = ["feishu"]; + +export const feishuExtensionTestRoots = feishuExtensionIds.map((id) => bundledPluginRoot(id)); + +export function isFeishuExtensionRoot(root) { + return feishuExtensionTestRoots.includes(root); +} diff --git a/vitest.extension-feishu.config.ts b/vitest.extension-feishu.config.ts new file mode 100644 index 00000000000..fa26c25cc4b --- /dev/null +++ b/vitest.extension-feishu.config.ts @@ -0,0 +1,27 @@ +import { feishuExtensionTestRoots } from "./vitest.extension-feishu-paths.mjs"; +import { loadPatternListFromEnv } from "./vitest.pattern-file.ts"; +import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; + +export function loadIncludePatternsFromEnv( + env: Record = process.env, +): string[] | null { + return loadPatternListFromEnv("OPENCLAW_VITEST_INCLUDE_FILE", env); +} + +export function createExtensionFeishuVitestConfig( + env: Record = process.env, +) { + return createScopedVitestConfig( + loadIncludePatternsFromEnv(env) ?? + feishuExtensionTestRoots.map((root) => `${root}/**/*.test.ts`), + { + dir: "extensions", + env, + name: "extension-feishu", + passWithNoTests: true, + setupFiles: ["test/setup.extensions.ts"], + }, + ); +} + +export default createExtensionFeishuVitestConfig(); diff --git a/vitest.extension-messaging-paths.mjs b/vitest.extension-messaging-paths.mjs index bc920bfc927..6099b1b6061 100644 --- a/vitest.extension-messaging-paths.mjs +++ b/vitest.extension-messaging-paths.mjs @@ -2,11 +2,9 @@ import { bundledPluginRoot } from "./scripts/lib/bundled-plugin-paths.mjs"; export const messagingExtensionIds = [ "bluebubbles", - "feishu", "googlechat", "irc", "mattermost", - "msteams", "nextcloud-talk", "nostr", "qqbot", diff --git a/vitest.extension-msteams-paths.mjs b/vitest.extension-msteams-paths.mjs new file mode 100644 index 00000000000..a1c9284dbaf --- /dev/null +++ b/vitest.extension-msteams-paths.mjs @@ -0,0 +1,9 @@ +import { bundledPluginRoot } from "./scripts/lib/bundled-plugin-paths.mjs"; + +export const msTeamsExtensionIds = ["msteams"]; + +export const msTeamsExtensionTestRoots = msTeamsExtensionIds.map((id) => bundledPluginRoot(id)); + +export function isMsTeamsExtensionRoot(root) { + return msTeamsExtensionTestRoots.includes(root); +} diff --git a/vitest.extension-msteams.config.ts b/vitest.extension-msteams.config.ts new file mode 100644 index 00000000000..c28e92c1080 --- /dev/null +++ b/vitest.extension-msteams.config.ts @@ -0,0 +1,17 @@ +import { msTeamsExtensionTestRoots } from "./vitest.extension-msteams-paths.mjs"; +import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; + +export function createExtensionMsTeamsVitestConfig(env?: Record) { + return createScopedVitestConfig( + msTeamsExtensionTestRoots.map((root) => `${root}/**/*.test.ts`), + { + dir: "extensions", + env, + name: "extension-msteams", + passWithNoTests: true, + setupFiles: ["test/setup.extensions.ts"], + }, + ); +} + +export default createExtensionMsTeamsVitestConfig(); diff --git a/vitest.extensions.config.ts b/vitest.extensions.config.ts index d9e5168e68e..5df8ead5090 100644 --- a/vitest.extensions.config.ts +++ b/vitest.extensions.config.ts @@ -3,9 +3,11 @@ import { extensionExcludedChannelTestGlobs } from "./vitest.channel-paths.mjs"; import { acpxExtensionTestRoots } from "./vitest.extension-acpx-paths.mjs"; import { blueBubblesExtensionTestRoots } from "./vitest.extension-bluebubbles-paths.mjs"; import { diffsExtensionTestRoots } from "./vitest.extension-diffs-paths.mjs"; +import { feishuExtensionTestRoots } from "./vitest.extension-feishu-paths.mjs"; import { matrixExtensionTestRoots } from "./vitest.extension-matrix-paths.mjs"; import { memoryExtensionTestRoots } from "./vitest.extension-memory-paths.mjs"; import { messagingExtensionTestRoots } from "./vitest.extension-messaging-paths.mjs"; +import { msTeamsExtensionTestRoots } from "./vitest.extension-msteams-paths.mjs"; import { providerExtensionTestRoots } from "./vitest.extension-provider-paths.mjs"; import { telegramExtensionTestRoots } from "./vitest.extension-telegram-paths.mjs"; import { loadPatternListFromEnv } from "./vitest.pattern-file.ts"; @@ -33,9 +35,11 @@ export function createExtensionsVitestConfig( ...acpxExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`), ...blueBubblesExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`), ...diffsExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`), + ...feishuExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`), ...matrixExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`), ...memoryExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`), ...messagingExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`), + ...msTeamsExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`), ...providerExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`), ...telegramExtensionTestRoots.map((root) => `${root.replace(/^extensions\//u, "")}/**`), ], diff --git a/vitest.hooks.config.ts b/vitest.hooks.config.ts new file mode 100644 index 00000000000..a1e033ae63b --- /dev/null +++ b/vitest.hooks.config.ts @@ -0,0 +1,12 @@ +import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; + +export function createHooksVitestConfig(env?: Record) { + return createScopedVitestConfig(["src/hooks/**/*.test.ts"], { + dir: "src/hooks", + env, + name: "hooks", + passWithNoTests: true, + }); +} + +export default createHooksVitestConfig(); diff --git a/vitest.shared.config.ts b/vitest.shared.config.ts index 17b4ee31ada..78751c521e2 100644 --- a/vitest.shared.config.ts +++ b/vitest.shared.config.ts @@ -159,14 +159,19 @@ export const sharedVitestConfig = { "vitest.extension-channels.config.ts", "vitest.extension-diffs-paths.mjs", "vitest.extension-diffs.config.ts", + "vitest.extension-feishu-paths.mjs", + "vitest.extension-feishu.config.ts", "vitest.extension-matrix-paths.mjs", "vitest.extension-matrix.config.ts", "vitest.extension-memory-paths.mjs", "vitest.extension-memory.config.ts", "vitest.extension-messaging-paths.mjs", "vitest.extension-messaging.config.ts", + "vitest.extension-msteams-paths.mjs", + "vitest.extension-msteams.config.ts", "vitest.extensions.config.ts", "vitest.gateway.config.ts", + "vitest.hooks.config.ts", "vitest.infra.config.ts", "vitest.live.config.ts", "vitest.media.config.ts", @@ -176,6 +181,7 @@ export const sharedVitestConfig = { "vitest.shared-core.config.ts", "vitest.shared.config.ts", "vitest.tooling.config.ts", + "vitest.tui.config.ts", "vitest.ui.config.ts", "vitest.unit.config.ts", "vitest.unit-paths.mjs", diff --git a/vitest.tui.config.ts b/vitest.tui.config.ts new file mode 100644 index 00000000000..b5c4eeac9c5 --- /dev/null +++ b/vitest.tui.config.ts @@ -0,0 +1,12 @@ +import { createScopedVitestConfig } from "./vitest.scoped-config.ts"; + +export function createTuiVitestConfig(env?: Record) { + return createScopedVitestConfig(["src/tui/**/*.test.ts"], { + dir: "src", + env, + name: "tui", + passWithNoTests: true, + }); +} + +export default createTuiVitestConfig(); diff --git a/vitest.unit-paths.mjs b/vitest.unit-paths.mjs index 7e63a9d7e87..afa77e409a2 100644 --- a/vitest.unit-paths.mjs +++ b/vitest.unit-paths.mjs @@ -40,6 +40,7 @@ export const bundledPluginDependentUnitTestFiles = [ export const unitTestAdditionalExcludePatterns = [ "src/gateway/**", + "src/hooks/**", "src/infra/**", `${BUNDLED_PLUGIN_ROOT_DIR}/**`, "src/browser/**", @@ -58,6 +59,7 @@ export const unitTestAdditionalExcludePatterns = [ "src/secrets/**", "src/shared/**", "src/media-understanding/**", + "src/tui/**", "src/plugins/contracts/**", "src/scripts/**", "src/infra/boundary-path.test.ts",