Skip to content

test(plugins): isolate plugin dir per test process - #15296

Merged
diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.52from
woodsonl:test/isolate-plugins-dir
Oct 6, 2026
Merged

diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.52from
woodsonl:test/isolate-plugins-dir

Conversation

@woodsonl

@woodsonl woodsonl commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Summary

tests/_setup/isolateDataDir.ts now points OMNIROUTE_PLUGINS_DIR at $DATA_DIR/plugins in every test process. The plugin scanner stops reading the developer's real ~/.omniroute/plugins during local test runs, and the chat pipeline stops loading plugins from it.

Why

  • getDefaultPluginDir() (src/lib/plugins/scanner.ts:46-57) returns OMNIROUTE_PLUGINS_DIR, else $HOME/.omniroute/plugins. The setup isolated DATA_DIR and left the plugin dir on the HOME default.
  • So every chat-pipeline test (the 28 tests/unit files that use tests/integration/_chatPipelineHarness.ts) scanned the real plugin dir. A request-mutating plugin installed locally could turn them red, and its code ran inside the test processes.
  • tests/unit/plugins-fs-safety.test.ts installed plugins into, and deleted them from, that same real directory.
  • CI runners have a clean HOME, so CI never hit this.

Changes

  • tests/_setup/isolateDataDir.ts: after the DATA_DIR block, default OMNIROUTE_PLUGINS_DIR to $DATA_DIR/plugins. A value the caller already set still wins.
    • A blank or whitespace-only value counts as unset, the same as the scanner's own .trim().
    • A plain ||= would keep " ", and the scanner would then fall back to HOME (the red run below shows this).
  • tests/unit/plugins-fs-safety.test.ts: pins OMNIROUTE_PLUGINS_DIR under the file's own temp DATA_DIR before the manager singleton resolves its install root.
    • Before this change, the between-test cleanup re-derived the root from HOME.
    • The three staging-residue assertions inspected $TEST_DATA_DIR/plugins, a directory the manager never wrote to, so their existsSync guard skipped them every time. They now inspect the real install root.
  • tests/unit/isolate-datadir.test.ts: adds child-process cases, in the same pattern as the existing DATA_DIR cases.
    • getDefaultPluginDir() resolves to $DATA_DIR/plugins when the value is unset, blank, or whitespace-only.
    • An explicit value is kept.

The resulting layout matches production, where DATA_DIR defaults to ~/.omniroute and the plugin dir to ~/.omniroute/plugins.

Validation (TDD)

Every run used the package.json import chain:

node --import tsx/esm --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test --test-force-exit <files>

Setup state tests/unit/isolate-datadir.test.ts
Unmodified 3 pass, 1 fail: the resolver returned ~/.omniroute/plugins in place of $DATA_DIR/plugins
Plain ||= 3 pass, 1 fail: the " " case fell back to ~/.omniroute/plugins
This PR 4/4 pass
  • plugins-fs-safety and plugins-scanner: 30/30 pass.
  • tests/integration/plugins-lifecycle.test.ts: 17/17 pass.
  • One batch run with APP_LOG_LEVEL=info: 507/507 pass.
    • It covered the 8 other plugin-manager suites, the 12 unit files that set OMNIROUTE_PLUGINS_DIR themselves, and all 28 harness-based unit files.
    • Every scanner.dir_resolved line in that run points at a temp directory or at one of plugins-scanner's fixed fixture values. None points at the real home plugin dir.
  • eslint with config/quality/eslint-suppressions.json, and prettier --check: clean on the three changed files.

tests/_setup/isolateDataDir.ts gave every test process a fresh DATA_DIR
but left the plugin directory alone. getDefaultPluginDir()
(src/lib/plugins/scanner.ts) reads OMNIROUTE_PLUGINS_DIR, else
$HOME/.omniroute/plugins, so every chat-pipeline test scanned, and could
load, the developer's real plugins, and plugins-fs-safety installed into
and deleted from that real directory. CI runners have a clean HOME, so CI
never saw it.

- isolateDataDir.ts: default OMNIROUTE_PLUGINS_DIR to $DATA_DIR/plugins
  unless the caller already set it. A blank or whitespace-only value
  counts as unset, matching the scanner's own trim; a plain ||= keeps
  "   ", and the scanner then falls back to HOME.
- plugins-fs-safety.test.ts: pin OMNIROUTE_PLUGINS_DIR under the file's
  own temp DATA_DIR before the manager singleton resolves it, so installs,
  the between-test cleanup (which re-derived the root from HOME), and the
  three staging-residue assertions (which inspected
  $TEST_DATA_DIR/plugins, a directory the manager never wrote to) share
  one root.
- isolate-datadir.test.ts: spawn a child that loads the setup and assert
  getDefaultPluginDir() resolves to $DATA_DIR/plugins for unset, blank,
  and whitespace-only values, and that an explicit value is kept.
@woodsonl
woodsonl requested a review from diegosouzapw as a code owner October 1, 2026 18:49
@diegosouzapw
diegosouzapw merged commit a46b309 into diegosouzapw:release/v3.8.52 Oct 6, 2026
44 of 51 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants