eharris128_Obsidian-LLM-Plugin/test
Evan Harris edd21015c2 Add local E2E suite driving real sandboxed Obsidian (wdio-obsidian-service)
npm run test:e2e builds the plugin, type-checks the specs, stages a clean
copy into test/plugin-dist/, and runs 13 Mocha specs against a real,
sandboxed Obsidian instance (downloaded to .obsidian-cache/ on first run;
~6s wall-clock after that). No API keys or network providers needed.

Coverage: plugin load + command registration + built-in skill seeding,
widget open/focus-or-open/new-chat-always-fresh/per-tab input isolation,
slash menu open/Escape/filtering, chat modal, chats panel, chat details
panel, and the header settings toggle.

Design notes (details in test/README.md):
- The service copies data.json from the plugin dir into test vaults, so
  plugins: ["."] would leak the developer's real API keys. The staging
  script writes a deterministic test data.json instead (rootVaultFolder
  "AI" so built-in skills seed; nothing else).
- Specs read the plugin id from the staged manifest at runtime rather
  than hardcoding it.
- Specs live under test/ with their own tsconfig (root tsconfig now
  excludes test/); OBSIDIAN_APP_VERSION / OBSIDIAN_INSTALLER_VERSION pin
  the Obsidian version under test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 14:16:18 -05:00
..
specs Add local E2E suite driving real sandboxed Obsidian (wdio-obsidian-service) 2026-06-06 14:16:18 -05:00
vaults/simple Add local E2E suite driving real sandboxed Obsidian (wdio-obsidian-service) 2026-06-06 14:16:18 -05:00
README.md Add local E2E suite driving real sandboxed Obsidian (wdio-obsidian-service) 2026-06-06 14:16:18 -05:00
tsconfig.json Add local E2E suite driving real sandboxed Obsidian (wdio-obsidian-service) 2026-06-06 14:16:18 -05:00

E2E Test Suite

End-to-end tests that drive a real, sandboxed Obsidian instance via wdio-obsidian-service. Nothing here touches your real vault, config, or data.json.

npm run test:e2e

The first run downloads Obsidian (~150 MB) into .obsidian-cache/ (gitignored); subsequent runs reuse the cache. Pin versions with env vars:

OBSIDIAN_APP_VERSION=earliest OBSIDIAN_INSTALLER_VERSION=earliest npm run test:e2e

(earliest resolves to minAppVersion from manifest.json.)

Layout

Path Purpose
wdio.conf.mts (repo root) WebdriverIO config — one sandboxed Obsidian per spec file, up to 4 in parallel
scripts/stage-plugin.mjs Copies manifest.json + main.js + styles.css into test/plugin-dist/ with a deterministic test data.json
test/plugin-dist/ Staged plugin installed into test vaults (gitignored)
test/vaults/simple/ Default test vault, copied fresh per run
test/specs/*.e2e.ts Mocha specs (own test/tsconfig.json, type-checked by test:e2e)
test/logs/ wdio logs (gitignored)

Conventions

  • Never pass plugins: ["."] in wdio.conf.mts. The service copies data.json from the plugin dir into test vaults — pointing at the repo root would leak the developer's real API keys/settings into the sandbox and make runs non-deterministic. Always go through test/plugin-dist/.
  • Never hardcode the plugin id. Read it via PLUGIN_ID from test/specs/helpers.ts (the dev worktree may carry a local-only manifest id).
  • Specs must not require API keys or network providers. The staged test data.json enables rootVaultFolder: "AI" (which seeds built-in skills) and nothing else. Provider round-trip tests, if added later, must skip gracefully when the provider is unavailable.
  • The slash menu element always exists on document.body with display: none — assert toBeDisplayed(), never toExist().
  • Each spec file gets its own Obsidian instance, but tests within a file share state — clean up leaves in beforeEach/after hooks.