test(plugin-loader): isolate discovery name derivation
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -16,18 +16,17 @@ function createTemporaryDirectory(prefix: string): string {
|
||||
|
||||
describe("discoverInstalledPlugins", () => {
|
||||
beforeEach(() => {
|
||||
// Mock logger to avoid noise in test output and force process isolation in CI
|
||||
mock.module("../../shared/logger", () => ({
|
||||
log: () => {},
|
||||
}))
|
||||
|
||||
|
||||
const pluginsHome = createTemporaryDirectory("omo-claude-plugins-")
|
||||
process.env.CLAUDE_PLUGINS_HOME = pluginsHome
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
mock.restore()
|
||||
|
||||
|
||||
if (originalClaudePluginsHome === undefined) {
|
||||
delete process.env.CLAUDE_PLUGINS_HOME
|
||||
} else {
|
||||
@@ -42,7 +41,6 @@ describe("discoverInstalledPlugins", () => {
|
||||
it("preserves scoped package name from npm plugin keys", () => {
|
||||
//#given
|
||||
const pluginsHome = process.env.CLAUDE_PLUGINS_HOME as string
|
||||
// Use unique temp directory with scoped path to prevent cross-test contamination
|
||||
const installPathBase = createTemporaryDirectory("omo-scoped-plugin-")
|
||||
const installPath = join(installPathBase, "@myorg", "my-plugin")
|
||||
mkdirSync(installPath, { recursive: true })
|
||||
@@ -68,7 +66,10 @@ describe("discoverInstalledPlugins", () => {
|
||||
)
|
||||
|
||||
//#when
|
||||
const discovered = discoverInstalledPlugins({ pluginsHomeOverride: pluginsHome })
|
||||
const discovered = discoverInstalledPlugins({
|
||||
pluginsHomeOverride: pluginsHome,
|
||||
loadPluginManifestOverride: () => null,
|
||||
})
|
||||
|
||||
//#then
|
||||
expect(discovered.errors).toHaveLength(0)
|
||||
@@ -79,7 +80,6 @@ describe("discoverInstalledPlugins", () => {
|
||||
it("derives package name from file URL plugin keys", () => {
|
||||
//#given
|
||||
const pluginsHome = process.env.CLAUDE_PLUGINS_HOME as string
|
||||
// Use unique temp directory directly to prevent cross-test contamination
|
||||
const installPath = createTemporaryDirectory("omo-fileurl-plugin-")
|
||||
|
||||
const databasePath = join(pluginsHome, "installed_plugins.json")
|
||||
@@ -103,7 +103,10 @@ describe("discoverInstalledPlugins", () => {
|
||||
)
|
||||
|
||||
//#when
|
||||
const discovered = discoverInstalledPlugins({ pluginsHomeOverride: pluginsHome })
|
||||
const discovered = discoverInstalledPlugins({
|
||||
pluginsHomeOverride: pluginsHome,
|
||||
loadPluginManifestOverride: () => null,
|
||||
})
|
||||
|
||||
//#then
|
||||
expect(discovered.errors).toHaveLength(0)
|
||||
@@ -114,7 +117,6 @@ describe("discoverInstalledPlugins", () => {
|
||||
it("derives canonical package name from npm plugin keys", () => {
|
||||
//#given
|
||||
const pluginsHome = process.env.CLAUDE_PLUGINS_HOME as string
|
||||
// Use unique temp directory directly to prevent cross-test contamination
|
||||
const installPath = createTemporaryDirectory("omo-npm-plugin-")
|
||||
|
||||
const databasePath = join(pluginsHome, "installed_plugins.json")
|
||||
@@ -138,7 +140,10 @@ describe("discoverInstalledPlugins", () => {
|
||||
)
|
||||
|
||||
//#when
|
||||
const discovered = discoverInstalledPlugins({ pluginsHomeOverride: pluginsHome })
|
||||
const discovered = discoverInstalledPlugins({
|
||||
pluginsHomeOverride: pluginsHome,
|
||||
loadPluginManifestOverride: () => null,
|
||||
})
|
||||
|
||||
//#then
|
||||
expect(discovered.errors).toHaveLength(0)
|
||||
|
||||
@@ -64,7 +64,7 @@ function loadClaudeSettings(): ClaudeSettings | null {
|
||||
}
|
||||
}
|
||||
|
||||
function loadPluginManifest(installPath: string): PluginManifest | null {
|
||||
export function loadPluginManifest(installPath: string): PluginManifest | null {
|
||||
const manifestPath = join(installPath, ".claude-plugin", "plugin.json")
|
||||
if (!existsSync(manifestPath)) {
|
||||
return null
|
||||
@@ -176,6 +176,7 @@ export function discoverInstalledPlugins(options?: PluginLoaderOptions): PluginL
|
||||
|
||||
const settingsEnabledPlugins = settings?.enabledPlugins
|
||||
const overrideEnabledPlugins = options?.enabledPluginsOverride
|
||||
const pluginManifestLoader = options?.loadPluginManifestOverride ?? loadPluginManifest
|
||||
|
||||
for (const [pluginKey, installation] of extractPluginEntries(db)) {
|
||||
if (!installation) continue
|
||||
@@ -196,7 +197,7 @@ export function discoverInstalledPlugins(options?: PluginLoaderOptions): PluginL
|
||||
continue
|
||||
}
|
||||
|
||||
const manifest = loadPluginManifest(installPath)
|
||||
const manifest = pluginManifestLoader(installPath)
|
||||
const pluginName = manifest?.name || derivePluginNameFromKey(pluginKey)
|
||||
|
||||
const loadedPlugin: LoadedPlugin = {
|
||||
|
||||
@@ -227,6 +227,12 @@ export interface PluginLoaderOptions {
|
||||
*/
|
||||
pluginsHomeOverride?: string
|
||||
|
||||
/**
|
||||
* Override plugin manifest loading for testing.
|
||||
* Return null to force plugin name derivation from the plugin key.
|
||||
*/
|
||||
loadPluginManifestOverride?: (installPath: string) => PluginManifest | null
|
||||
|
||||
/**
|
||||
* Override enabled plugins from oh-my-opencode config.
|
||||
* Key format: "pluginName@marketplace" (e.g., "shell-scripting@claude-code-workflows")
|
||||
|
||||
Reference in New Issue
Block a user