Skip to content
🚧 Early alpha — building the foundation. See the roadmap →

Testing

Created

Crosswalker has three separate test surfaces. Know which you’re working on before picking commands.

#SurfaceFrameworkWhen to run
1Plugin unit testsJest + ts-jestEvery plugin code change
2Plugin E2E testsWebdriverIO + wdio-obsidian-serviceBefore release, after core logic changes
3Docs E2E testsPlaywrightEvery docs change (content, theme, plugins), before deploy

Unit tests use Jest with ts-jest and a minimal Obsidian API mock at tests/__mocks__/obsidian.ts. Fully headless — no Obsidian runtime required.

bun run test          # One-shot
bun run test:watch    # Watch mode
  • CSV parser — parsing, column analysis, edge cases, streaming
  • Settings data — defaults, validation
  • Config manager — fingerprinting, matching (planned)
  • Generation engine — output structure (planned)

Tests live in tests/ alongside the code they test:

import { parseCSV } from '../src/import/parsers/csv-parser';

describe('parseCSV', () => {
  it('parses simple CSV', async () => {
    const result = await parseCSV('Name,ID\nAlice,1');
    expect(result.rows).toHaveLength(1);
    expect(result.columns[0].name).toBe('Name');
  });
});

Lint (part of the plugin unit-test surface)

Section titled “Lint (part of the plugin unit-test surface)”

Required for community plugin submission:

bun run lint            # Check
bun run lint:fix        # Auto-fix what can be fixed

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.

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.

bun run e2e              # Requires Obsidian installed locally

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.

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.

SpecTestsCovers
smoke.spec.ts10Homepage load, Nova top nav, sidebar, search, content pages (installation, features, agent-context, blog, architecture)
deployment.spec.ts4HTTP 200, no console errors, no failed asset requests, meta tags present
ux-fixes.spec.ts20Content 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

From docs/:

cd docs

bun run test:local       # Run all tests — auto-builds + previews + runs Chromium
bun run test:deploy      # Deployment-only subset (faster)
bun run test:e2e         # Headed mode — watch the browser
bun run test:e2e:ui      # Playwright UI mode — interactive debugging

Or via the orchestrator from the repo root:

bun run serve            # Interactive menu → option 8

Point Playwright at the production deployment instead of local preview:

cd docs
TEST_URL=https://cybersader.github.io bun run test:deploy
cd docs
bun install
bun x playwright install chromium    # Download the test browser
bun run build                          # Preview server serves from dist/
  • Config file: docs/playwright.config.ts
  • Base path: /crosswalker (matches base in astro.config.mjs). All page.goto() calls must prefix this
  • Preview server: auto-starts bun run preview on port 4321
  • Browser: Chromium only (sufficient for docs coverage)
  • Screenshots on failure: automatically captured to docs/test-results/
import { test, expect } from '@playwright/test';

const BASE = '/crosswalker';

test('my new page loads', async ({ page }) => {
  await page.goto(`${BASE}/my-section/my-page/`);
  await expect(page.locator('h1')).toContainText('My Page');
});

Common pitfalls:

IssueFix
404 on all pagesForgot bun run build — preview serves from dist/
Chromium not foundbun x playwright install chromium
Tailwind classes missingCheck docs/src/styles/global.css has @source directives
Base path 404sPrefix every page.goto() with ${BASE}/
Page renders but elements missingCheck the browser console in headed mode — MDX compilation errors show up as console warnings

Add to ux-fixes.spec.ts (or a new spec) when you:

  • Add a new Starlight component override (like the PageTitle one)
  • 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

For things that can’t be automated (mostly plugin UI edge cases):

  1. bun run serve:plugin (watch mode)
  2. Open test-vault/ in Obsidian
  3. Test the import wizard with sample data in test-vault/Crosswalker Test Data/
  4. Check crosswalker-debug.log for detailed logs (enable in settings)
  5. 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.

Matrix by change surface:

You changedMinimum tests
Plugin TypeScript codebun run test + bun run lint
Plugin UI (settings tab, modals)Above + manual test in Obsidian
Plugin core logic (parser, generation)Above + bun run e2e if you can run it locally
docs/ content (.mdx)cd docs && bun run test:local
docs/ theme / CSS / componentsAbove + visually verify in bun run serve:docs at multiple viewport widths
Both plugin and docsAll of the above
  • Docs deploy: .github/workflows/deploy-docs.yml runs on push to main, 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.