fix(tests): inject plugin loader dependencies
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
import { describe, it, expect, beforeEach, afterEach, mock } from "bun:test"
|
||||
import type { PluginComponentsResult } from "./loader"
|
||||
import {
|
||||
clearPluginComponentsCache,
|
||||
loadAllPluginComponents,
|
||||
loadAllPluginComponentsWithDeps,
|
||||
type PluginComponentsResult,
|
||||
} from "./loader"
|
||||
|
||||
function createPluginComponentsResult(): PluginComponentsResult {
|
||||
return {
|
||||
@@ -13,10 +18,6 @@ function createPluginComponentsResult(): PluginComponentsResult {
|
||||
}
|
||||
}
|
||||
|
||||
async function importFreshLoaderModule() {
|
||||
return import(`./loader?plugin-loader-cache-test=${Date.now()}-${Math.random()}`)
|
||||
}
|
||||
|
||||
describe("loadAllPluginComponents", () => {
|
||||
const originalEnv = { ...process.env }
|
||||
|
||||
@@ -138,20 +139,20 @@ describe("loadAllPluginComponents", () => {
|
||||
const loadPluginMcpServers = mock(async () => result.mcpServers)
|
||||
const loadPluginHooksConfigs = mock(() => result.hooksConfigs)
|
||||
|
||||
mock.module("./discovery", () => ({ discoverInstalledPlugins }))
|
||||
mock.module("./command-loader", () => ({ loadPluginCommands }))
|
||||
mock.module("./skill-loader", () => ({ loadPluginSkillsAsCommands }))
|
||||
mock.module("./agent-loader", () => ({ loadPluginAgents }))
|
||||
mock.module("./mcp-server-loader", () => ({ loadPluginMcpServers }))
|
||||
mock.module("./hook-loader", () => ({ loadPluginHooksConfigs }))
|
||||
|
||||
const { clearPluginComponentsCache, loadAllPluginComponents } = await importFreshLoaderModule()
|
||||
clearPluginComponentsCache()
|
||||
const enabledPluginsOverride = { "demo@test": true }
|
||||
|
||||
// when
|
||||
const firstResult = await loadAllPluginComponents({ enabledPluginsOverride })
|
||||
const secondResult = await loadAllPluginComponents({ enabledPluginsOverride })
|
||||
const deps = {
|
||||
discoverInstalledPlugins,
|
||||
loadPluginCommands,
|
||||
loadPluginSkillsAsCommands,
|
||||
loadPluginAgents,
|
||||
loadPluginMcpServers,
|
||||
loadPluginHooksConfigs,
|
||||
}
|
||||
const firstResult = await loadAllPluginComponentsWithDeps({ enabledPluginsOverride }, deps)
|
||||
const secondResult = await loadAllPluginComponentsWithDeps({ enabledPluginsOverride }, deps)
|
||||
|
||||
// then
|
||||
expect(firstResult).toEqual(result)
|
||||
@@ -176,19 +177,19 @@ describe("loadAllPluginComponents", () => {
|
||||
const loadPluginMcpServers = mock(async () => result.mcpServers)
|
||||
const loadPluginHooksConfigs = mock(() => result.hooksConfigs)
|
||||
|
||||
mock.module("./discovery", () => ({ discoverInstalledPlugins }))
|
||||
mock.module("./command-loader", () => ({ loadPluginCommands }))
|
||||
mock.module("./skill-loader", () => ({ loadPluginSkillsAsCommands }))
|
||||
mock.module("./agent-loader", () => ({ loadPluginAgents }))
|
||||
mock.module("./mcp-server-loader", () => ({ loadPluginMcpServers }))
|
||||
mock.module("./hook-loader", () => ({ loadPluginHooksConfigs }))
|
||||
|
||||
const { clearPluginComponentsCache, loadAllPluginComponents } = await importFreshLoaderModule()
|
||||
clearPluginComponentsCache()
|
||||
|
||||
// when
|
||||
await loadAllPluginComponents({ enabledPluginsOverride: { "demo@test": true } })
|
||||
await loadAllPluginComponents({ enabledPluginsOverride: { "demo@test": false } })
|
||||
const deps = {
|
||||
discoverInstalledPlugins,
|
||||
loadPluginCommands,
|
||||
loadPluginSkillsAsCommands,
|
||||
loadPluginAgents,
|
||||
loadPluginMcpServers,
|
||||
loadPluginHooksConfigs,
|
||||
}
|
||||
await loadAllPluginComponentsWithDeps({ enabledPluginsOverride: { "demo@test": true } }, deps)
|
||||
await loadAllPluginComponentsWithDeps({ enabledPluginsOverride: { "demo@test": false } }, deps)
|
||||
|
||||
// then
|
||||
expect(discoverInstalledPlugins).toHaveBeenCalledTimes(2)
|
||||
@@ -211,20 +212,20 @@ describe("loadAllPluginComponents", () => {
|
||||
const loadPluginMcpServers = mock(async () => result.mcpServers)
|
||||
const loadPluginHooksConfigs = mock(() => result.hooksConfigs)
|
||||
|
||||
mock.module("./discovery", () => ({ discoverInstalledPlugins }))
|
||||
mock.module("./command-loader", () => ({ loadPluginCommands }))
|
||||
mock.module("./skill-loader", () => ({ loadPluginSkillsAsCommands }))
|
||||
mock.module("./agent-loader", () => ({ loadPluginAgents }))
|
||||
mock.module("./mcp-server-loader", () => ({ loadPluginMcpServers }))
|
||||
mock.module("./hook-loader", () => ({ loadPluginHooksConfigs }))
|
||||
|
||||
const { clearPluginComponentsCache, loadAllPluginComponents } = await importFreshLoaderModule()
|
||||
clearPluginComponentsCache()
|
||||
|
||||
// when
|
||||
await loadAllPluginComponents()
|
||||
const deps = {
|
||||
discoverInstalledPlugins,
|
||||
loadPluginCommands,
|
||||
loadPluginSkillsAsCommands,
|
||||
loadPluginAgents,
|
||||
loadPluginMcpServers,
|
||||
loadPluginHooksConfigs,
|
||||
}
|
||||
await loadAllPluginComponentsWithDeps(undefined, deps)
|
||||
clearPluginComponentsCache()
|
||||
await loadAllPluginComponents()
|
||||
await loadAllPluginComponentsWithDeps(undefined, deps)
|
||||
|
||||
// then
|
||||
expect(discoverInstalledPlugins).toHaveBeenCalledTimes(2)
|
||||
@@ -247,20 +248,20 @@ describe("loadAllPluginComponents", () => {
|
||||
const loadPluginMcpServers = mock(async () => result.mcpServers)
|
||||
const loadPluginHooksConfigs = mock(() => result.hooksConfigs)
|
||||
|
||||
mock.module("./discovery", () => ({ discoverInstalledPlugins }))
|
||||
mock.module("./command-loader", () => ({ loadPluginCommands }))
|
||||
mock.module("./skill-loader", () => ({ loadPluginSkillsAsCommands }))
|
||||
mock.module("./agent-loader", () => ({ loadPluginAgents }))
|
||||
mock.module("./mcp-server-loader", () => ({ loadPluginMcpServers }))
|
||||
mock.module("./hook-loader", () => ({ loadPluginHooksConfigs }))
|
||||
|
||||
const { clearPluginComponentsCache, loadAllPluginComponents } = await importFreshLoaderModule()
|
||||
clearPluginComponentsCache()
|
||||
|
||||
// when
|
||||
const firstResult = await loadAllPluginComponents()
|
||||
const deps = {
|
||||
discoverInstalledPlugins,
|
||||
loadPluginCommands,
|
||||
loadPluginSkillsAsCommands,
|
||||
loadPluginAgents,
|
||||
loadPluginMcpServers,
|
||||
loadPluginHooksConfigs,
|
||||
}
|
||||
const firstResult = await loadAllPluginComponentsWithDeps(undefined, deps)
|
||||
firstResult.commands["demo:command"]!.description = "mutated"
|
||||
const secondResult = await loadAllPluginComponents()
|
||||
const secondResult = await loadAllPluginComponentsWithDeps(undefined, deps)
|
||||
|
||||
// then
|
||||
expect(secondResult.commands["demo:command"]!.description).toBe("demo")
|
||||
|
||||
@@ -27,8 +27,26 @@ export interface PluginComponentsResult {
|
||||
errors: PluginLoadError[]
|
||||
}
|
||||
|
||||
export interface PluginComponentLoadDeps {
|
||||
discoverInstalledPlugins: typeof discoverInstalledPlugins
|
||||
loadPluginCommands: typeof loadPluginCommands
|
||||
loadPluginSkillsAsCommands: typeof loadPluginSkillsAsCommands
|
||||
loadPluginAgents: typeof loadPluginAgents
|
||||
loadPluginMcpServers: typeof loadPluginMcpServers
|
||||
loadPluginHooksConfigs: typeof loadPluginHooksConfigs
|
||||
}
|
||||
|
||||
const cachedPluginComponentsByKey = new Map<string, PluginComponentsResult>()
|
||||
|
||||
const defaultPluginComponentLoadDeps: PluginComponentLoadDeps = {
|
||||
discoverInstalledPlugins,
|
||||
loadPluginCommands,
|
||||
loadPluginSkillsAsCommands,
|
||||
loadPluginAgents,
|
||||
loadPluginMcpServers,
|
||||
loadPluginHooksConfigs,
|
||||
}
|
||||
|
||||
function clonePluginComponentsResult(
|
||||
result: PluginComponentsResult,
|
||||
): PluginComponentsResult {
|
||||
@@ -54,7 +72,10 @@ export function clearPluginComponentsCache(): void {
|
||||
cachedPluginComponentsByKey.clear()
|
||||
}
|
||||
|
||||
export async function loadAllPluginComponents(options?: PluginLoaderOptions): Promise<PluginComponentsResult> {
|
||||
async function loadAllPluginComponentsInternal(
|
||||
options?: PluginLoaderOptions,
|
||||
deps: PluginComponentLoadDeps = defaultPluginComponentLoadDeps,
|
||||
): Promise<PluginComponentsResult> {
|
||||
if (isClaudeCodePluginsDisabled()) {
|
||||
log("Claude Code plugin loading disabled via OPENCODE_DISABLE_CLAUDE_CODE env var")
|
||||
return {
|
||||
@@ -74,14 +95,14 @@ export async function loadAllPluginComponents(options?: PluginLoaderOptions): Pr
|
||||
return clonePluginComponentsResult(cachedPluginComponents)
|
||||
}
|
||||
|
||||
const { plugins, errors } = discoverInstalledPlugins(options)
|
||||
const { plugins, errors } = deps.discoverInstalledPlugins(options)
|
||||
|
||||
const [commands, skills, agents, mcpServers, hooksConfigs] = await Promise.all([
|
||||
Promise.resolve(loadPluginCommands(plugins)),
|
||||
Promise.resolve(loadPluginSkillsAsCommands(plugins)),
|
||||
Promise.resolve(loadPluginAgents(plugins)),
|
||||
loadPluginMcpServers(plugins),
|
||||
Promise.resolve(loadPluginHooksConfigs(plugins)),
|
||||
Promise.resolve(deps.loadPluginCommands(plugins)),
|
||||
Promise.resolve(deps.loadPluginSkillsAsCommands(plugins)),
|
||||
Promise.resolve(deps.loadPluginAgents(plugins)),
|
||||
deps.loadPluginMcpServers(plugins),
|
||||
Promise.resolve(deps.loadPluginHooksConfigs(plugins)),
|
||||
])
|
||||
|
||||
log(`Loaded ${plugins.length} plugins with ${Object.keys(commands).length} commands, ${Object.keys(skills).length} skills, ${Object.keys(agents).length} agents, ${Object.keys(mcpServers).length} MCP servers`)
|
||||
@@ -100,3 +121,14 @@ export async function loadAllPluginComponents(options?: PluginLoaderOptions): Pr
|
||||
|
||||
return clonePluginComponentsResult(result)
|
||||
}
|
||||
|
||||
export async function loadAllPluginComponents(options?: PluginLoaderOptions): Promise<PluginComponentsResult> {
|
||||
return loadAllPluginComponentsInternal(options)
|
||||
}
|
||||
|
||||
export async function loadAllPluginComponentsWithDeps(
|
||||
options: PluginLoaderOptions | undefined,
|
||||
deps: PluginComponentLoadDeps,
|
||||
): Promise<PluginComponentsResult> {
|
||||
return loadAllPluginComponentsInternal(options, deps)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user