Skip to main content

Rust

  • Unit tests sit next to the code (#[cfg(test)] modules or a tests.rs); integration tests in crates/<crate>/tests/. ide-host has the most: opening projects, trust, VCS flows, run configurations, plugins, the remote protocol.
  • Tests that need real external tools (language servers, Docker, build tools) are #[ignore]d with a reason and run explicitly with -- --ignored.
  • Use NullSink when a crate wants an EventSink and the test doesn’t care about events.
  • CI runs the suite on macOS, Ubuntu 22.04 and Windows with --no-fail-fast. Test fixtures write LF files, so CI sets git config --global core.autocrlf false; do the same on Windows if fixture comparisons fail.
  • The CI test run also regenerates src/bindings.ts (the export_bindings test) and fails if it differs from the committed file.
Plugins have their own workspaces: see Plugin host › Testing the host.

Frontend unit tests

pnpm test runs vitest run over src/**/*.test.{ts,tsx}, perf/**/*.test.ts and scripts/**/*.test.ts in jsdom. The full suite takes several minutes, so while iterating run a subset:
pnpm test -- <path> ignores the path and runs the whole suite. Use pnpm vitest run <path>.
What to know when writing them:
  • Tests live next to the module (foo.test.ts) or in a feature’s __tests__/ folder.
  • src/test/setup.ts makes jsdom look like macOS (so ⌘ keymaps apply; opt into Windows explicitly) and gives elements a size so virtualized lists render rows.
  • Outside Tauri, isTauri() is false and features use their in-memory backends. To simulate a backend event, use emitLocalIdeEvent from @/platform/ipc.
  • Some tests are repository checks rather than unit tests: the text catalogs (src/platform/locales/*.test.ts), WebKit compatibility (src/platform/webkitCompatibility.test.ts), the theme token reference (scripts/theme/theme.test.ts). They run in pnpm test too.

End-to-end tests

pnpm e2e runs Playwright against the UI in plain-browser mode: Vite serves the frontend (port 1450, or OPENIDEA_E2E_PORT), the shell injects a sample project, and features fall back to in-memory backends — no Tauri, no Rust build, no network.
  • Specs are e2e/*.spec.ts. Import test and expect from e2e/fixtures.ts; its workbench fixture opens the sample project (acme-api) and helpers like openFromTree and doubleShift cover common steps.
  • Specs use the macOS keymap (Meta+…) on every OS; the fixture forces it.
  • To exercise code paths that need a desktop backend, stubDesktop(page) switches the page to desktop mode over a stub: you register handlers per command name (window.__ipc.handlers.lsp_goto = …), push values into a Channel with send, and emit IdeEvents with emit. Unhandled commands fail as unavailable. ipcCalls(page, cmd) returns the calls made.
  • Standalone pages for focused component tests are e2e/*.html + e2e/*.fixture.ts.
  • In CI, E2E runs in the mcr.microsoft.com/playwright container matching the @playwright/test version, with one retry; on failure the HTML report and traces (trace: "retain-on-failure") are uploaded as an artifact.

Verifying in the real app

Unit and E2E tests don’t run the Rust backend inside the webview. For UI or runtime behaviour, run pnpm tauri dev and check the change in the app. Debug builds include the Tauri MCP bridge, so the check can be scripted; find the port with pnpm dev:status (see Development setup). The repository’s agent skill .agents/skills/verify describes driving the app that way and capturing screenshots.