Files
oh-my-pi/packages/coding-agent/test/marketplace/plugin-dir-roots.test.ts
T
Miroslav Drbal 4e199f93f7 feat: add marketplace plugin system
Add Claude Code-compatible marketplace plugin infrastructure:

- Registry: types, ID helpers, atomic read/write for marketplaces.json
  and installed_plugins.json (Claude Code format with version: 2)
- Fetcher: classifySource (6 ordered rules), parseMarketplaceCatalog,
  fetchMarketplace (local sources; git/http stubs for Phase 2)
- Resolver + Cache: resolvePluginSource with pathIsWithin containment,
  cachePlugin, removeCachedPlugin, cleanOrphanedCache
- MarketplaceManager: orchestrates add/remove/update marketplaces,
  install/uninstall/enable plugins, clearPluginRootsCache on mutation
- CLI: omp plugin marketplace add|remove|update|list,
  omp plugin discover, classifyInstallTarget for name@marketplace
- Discovery: listClaudePluginRoots reads OMP registry alongside
  Claude's, OMP authoritative for duplicate plugin IDs
- Args: --plugin-dir repeatable flag (parsing only, runtime wiring TBD)
- Slash command: /reload-plugins clears fs + roots cache
- Test fixtures and 130 tests across 8 test files
2026-03-30 13:44:53 +02:00

54 lines
1.7 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import { buildPluginDirRoot } from "@oh-my-pi/pi-coding-agent/discovery/plugin-dir-roots";
describe("buildPluginDirRoot", () => {
it("builds root with manifest name", () => {
const root = buildPluginDirRoot("/path/to/my-plugin", "custom-name");
expect(root).toEqual({
id: "custom-name@__local__",
marketplace: "__local__",
plugin: "custom-name",
version: "local",
path: "/path/to/my-plugin",
scope: "user",
});
});
it("falls back to directory basename when no manifest name", () => {
const root = buildPluginDirRoot("/path/to/my-plugin");
expect(root.plugin).toBe("my-plugin");
expect(root.id).toBe("my-plugin@__local__");
});
it("falls back to directory basename when manifest name is undefined", () => {
const root = buildPluginDirRoot("/some/dir/cool-plugin", undefined);
expect(root.plugin).toBe("cool-plugin");
expect(root.id).toBe("cool-plugin@__local__");
});
it("uses __local__ marketplace", () => {
const root = buildPluginDirRoot("/any/path", "test");
expect(root.marketplace).toBe("__local__");
});
it("uses local version string", () => {
const root = buildPluginDirRoot("/any/path", "test");
expect(root.version).toBe("local");
});
it("sets scope to user", () => {
const root = buildPluginDirRoot("/any/path", "test");
expect(root.scope).toBe("user");
});
it("preserves absolute path", () => {
const root = buildPluginDirRoot("/absolute/path/to/plugin", "test");
expect(root.path).toBe("/absolute/path/to/plugin");
});
it("constructs id as pluginName@__local__", () => {
const root = buildPluginDirRoot("/p", "my-tool");
expect(root.id).toBe("my-tool@__local__");
});
});