Files
skills/docs/devtools/tooling/installer/src/testing/run-plugin.md
2026-05-29 08:20:56 +01:00

2.5 KiB

run-plugin

Purpose

End-to-end test harness for plugins. runPlugin(plugin, options) wires up an in-memory filesystem, a scripted CLI, a no-op logger, and a basic template engine, then drives the plugin through the full detect → prompts → plan → apply → postInstall pipeline. Returns the filesystem and the recorded CLI interaction so tests can assert on what was written and what was prompted. Zero real disk I/O.

Features

  • Sensible defaults: in-memory MemoryFs, scripted ScriptCli, no-op logger, {{var}}-style template engine — all overridable.
  • Returns { ops, summary, handle, dryRun, fs, cli } so tests can inspect the plan, the resulting fs, and the prompt history.
  • Same RunOptions surface as Host.run: dryRun, force, noInteractive, only, exclude, signal.
  • Defaults noInteractive to true so test runs never block on a prompt that wasn't scripted.

Basic Example

import { runPlugin } from "@suaveplan/installer";

const result = await runPlugin(myPlugin, {
    answers: { targetDir: "/.suaveplan/skills" },
});
expect(result.summary.written).toBe(5);

Advanced Example

import { runPlugin, ScriptCli } from "@suaveplan/installer";

const cli = new ScriptCli({ confirm: [true, false] });
const ac = new AbortController();
const result = await runPlugin(myPlugin, {
    cli,
    signal: ac.signal,
    answers: { skills: ["echo", "crypto"] },
    only: ["crypto"],
    force: false,
});

expect(cli.record.confirms).toEqual([
    { message: "Overwrite existing file?", answer: true },
]);
expect(result.ops.every((op) => op.path.includes("crypto"))).toBe(true);

API Reference

  • runPlugin<TAnswers, THandle>(plugin, options): Promise<RunPluginResult<THandle>>
  • interface RunPluginOptions<TAnswers> — { answers?, fs?, cli?, cwd?, logger?, templates?, signal?, dryRun?, force?, noInteractive?, only?, exclude? }.
  • interface RunPluginResult<THandle> extends HostRunResult<THandle> — adds fs: MemoryFs and cli: InstallerCli.

Implementation Notes

The default template engine handles only {{varName}} substitution and returns empty string for unknown vars — that's enough for plugin tests that don't care about templates and avoids adding a dependency on @suaveplan/templates to the test surface. The default cwd is / (POSIX root in MemoryFs's namespace) so paths in plans can be written literally. Tests that need a different cwd should pass it explicitly; both DiskFs and MemoryFs honour the value identically.