first commit
This commit is contained in:
71
docs/devtools/tooling/installer/src/testing/run-plugin.md
Normal file
71
docs/devtools/tooling/installer/src/testing/run-plugin.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# `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
|
||||
|
||||
```ts
|
||||
import { runPlugin } from "@suaveplan/installer";
|
||||
|
||||
const result = await runPlugin(myPlugin, {
|
||||
answers: { targetDir: "/.suaveplan/skills" },
|
||||
});
|
||||
expect(result.summary.written).toBe(5);
|
||||
```
|
||||
|
||||
## Advanced Example
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user