Testing
Crosswalker has three separate test surfaces. Know which you’re working on before picking commands.
| # | Surface | Framework | When to run |
|---|---|---|---|
| 1 | Plugin unit tests | Jest + ts-jest | Every plugin code change |
| 2 | Plugin E2E tests | WebdriverIO + wdio-obsidian-service | Before release, after core logic changes |
| 3 | Docs E2E tests | Playwright | Every docs change (content, theme, plugins), before deploy |
1. Plugin unit tests (Jest)
Section titled “1. Plugin unit tests (Jest)”Unit tests use Jest with ts-jest and a minimal Obsidian API mock at tests/__mocks__/obsidian.ts. Fully headless — no Obsidian runtime required.
What’s tested
Section titled “What’s tested”- CSV parser — parsing, column analysis, edge cases, streaming
- Settings data — defaults, validation
- Config manager — fingerprinting, matching (planned)
- Generation engine — output structure (planned)
Writing a unit test
Section titled “Writing a unit test”Tests live in tests/ alongside the code they test:
Lint (part of the plugin unit-test surface)
Section titled “Lint (part of the plugin unit-test surface)”Required for community plugin submission:
Uses eslint-plugin-obsidianmd to enforce things like sentence case for UI text, no manual createEl('h3') for settings headings, no plugin name in heading text, etc. See the contributing page for the full rule list.
2. Plugin E2E tests (WebdriverIO)
Section titled “2. Plugin E2E tests (WebdriverIO)”E2E tests use WebdriverIO with wdio-obsidian-service to drive a real Obsidian instance via Chrome DevTools Protocol. Tests can exercise the import wizard, navigate multi-step flows, and verify generated vault structure.
Not run in CI currently (on the roadmap). Verifies:
- Plugin loads correctly into a fresh test vault
- Import wizard opens and all four steps render
- File generation produces expected folder structure and frontmatter
- Settings UI persists changes across reloads
See wdio.conf.mts for the config and test/e2e/ for specs.
3. Docs E2E tests (Playwright)
Section titled “3. Docs E2E tests (Playwright)”The docs site has a Playwright suite in docs/tests/ that runs against a built + previewed site. Catches rendering regressions, 404s, console errors, and verifies the UX/theme decisions.
Test suites
Section titled “Test suites”| Spec | Tests | Covers |
|---|---|---|
smoke.spec.ts | 10 | Homepage load, Nova top nav, sidebar, search, content pages (installation, features, agent-context, blog, architecture) |
deployment.spec.ts | 4 | HTTP 200, no console errors, no failed asset requests, meta tags present |
ux-fixes.spec.ts | 20 | Content width clamp at multiple breakpoints, narrower sidebar width, lastUpdated footer, PageTitle override (volatility badges + h1#_top accessibility anchor), smoke tests for new pages, regression checks |
Running the docs tests
Section titled “Running the docs tests”From docs/:
Or via the orchestrator from the repo root:
Testing against the live site
Section titled “Testing against the live site”Point Playwright at the production deployment instead of local preview:
Prerequisites (first time only)
Section titled “Prerequisites (first time only)”Configuration
Section titled “Configuration”- Config file:
docs/playwright.config.ts - Base path:
/crosswalker(matchesbaseinastro.config.mjs). Allpage.goto()calls must prefix this - Preview server: auto-starts
bun run previewon port 4321 - Browser: Chromium only (sufficient for docs coverage)
- Screenshots on failure: automatically captured to
docs/test-results/
Writing a new Playwright test
Section titled “Writing a new Playwright test”Common pitfalls:
| Issue | Fix |
|---|---|
| 404 on all pages | Forgot bun run build — preview serves from dist/ |
| Chromium not found | bun x playwright install chromium |
| Tailwind classes missing | Check docs/src/styles/global.css has @source directives |
| Base path 404s | Prefix every page.goto() with ${BASE}/ |
| Page renders but elements missing | Check the browser console in headed mode — MDX compilation errors show up as console warnings |
When to add tests here
Section titled “When to add tests here”Add to ux-fixes.spec.ts (or a new spec) when you:
- Add a new Starlight component override (like the
PageTitleone) - Change global CSS that affects layout (content width, sidebar width, figure sizing)
- Add a new page that should be part of the smoke suite
- Fix a visual regression — add a test that would have caught it
Manual testing
Section titled “Manual testing”For things that can’t be automated (mostly plugin UI edge cases):
bun run serve:plugin(watch mode)bun run fixtures— regenerate test fixtures intotest-vault/Frameworks/NIST-mini/(see Fixtures below)- Open
test-vault/in Obsidian - Test the import wizard with the regenerated sample data, or with custom data in
test-vault/Crosswalker Test Data/ - Check
crosswalker-debug.logfor detailed logs (enable in settings) - Use the Hot Reload plugin for faster iteration — no need to toggle the plugin on/off for each rebuild
Manual test documents live in test-vault/Crosswalker Test Docs/ for workflows that need guided human verification.
Fixtures
Section titled “Fixtures”Test fixtures are generated by a TS script in tools/. Source CSVs are committed; the script reads a CSV and emits Tier 1 markdown notes into the test vault. This gives reproducible, version-controlled test data without committing the generated markdown.
Why a generator (not just committed markdown)
Section titled “Why a generator (not just committed markdown)”Three options were considered:
- Commit pre-generated markdown — fragile when the Tier 1 schema evolves
- Build a fixtures-generating Obsidian plugin — over-engineered (test infrastructure shouldn’t itself need to be a plugin in a vault)
- TS generator script in
tools/— what we landed on
Option 3 keeps fixtures deterministic (committed CSV + versioned script → identical markdown across machines), regenerable (rerun the script when the schema changes), and out of node_modules-style “infrastructure repo” sprawl.
Layout
Section titled “Layout”Each row becomes one <id>.md file. Frontmatter conforms to spec/tier1.schema.json — curie, title, aliases, tags, domain-specific fields, plus a full _crosswalker provenance block.
Future: marketplace-driven fixtures
Section titled “Future: marketplace-driven fixtures”Once the community marketplace pattern lands, the generator gains a --from-bundle <id> mode that pulls a published Tier 1 bundle and drops it into the target vault. That makes published bundles a real fixture source — your tests run against the same bytes a user would download.
What the generator does NOT do (yet)
Section titled “What the generator does NOT do (yet)”- Doesn’t implement the full Ch 22 recipe grammar (folder/heading/tag/wikilink mechanism composition). That’s the v0.1
render()engine — separate work - Doesn’t generate crosswalk edges between frameworks. Add a second source CSV + second
bun run fixturesinvocation when you need that - Doesn’t produce junction notes (evidence links). Add hand-authored junction notes to
test-vault/when needed
What to run before a PR
Section titled “What to run before a PR”Matrix by change surface:
| You changed | Minimum tests |
|---|---|
| Plugin TypeScript code | bun run test + bun run lint |
| Plugin UI (settings tab, modals) | Above + manual test in Obsidian against fresh fixtures (bun run fixtures) |
| Plugin core logic (parser, generation) | Above + bun run e2e if you can run it locally |
tools/generate-fixtures.ts or tools/fixtures/synthetic/*.csv | bun run fixtures succeeds + spot-check generated markdown opens cleanly in Obsidian + _crosswalker block validates against spec/tier1.schema.json |
spec/tier1.schema.json or spec/recipe.schema.json | bun run fixtures (the generated frontmatter must still validate) + bump $id if breaking |
docs/ content (.mdx) | cd docs && bun run test:local |
docs/ theme / CSS / components | Above + visually verify in bun run serve:docs at multiple viewport widths |
| Both plugin and docs | All of the above |
- Docs deploy:
.github/workflows/deploy-docs.ymlruns on push tomain, builds docs and publishes to GitHub Pages - Plugin release: manual via
bun run version+ tagged release
E2E tests (both plugin WebdriverIO and docs Playwright) are not currently run in CI — on the roadmap. Run them locally before PRs that touch areas they cover.