Skip to content

Testing

Speedwave’s tests span several layers: Rust crates, MCP servers, the CLI, the Angular desktop UI, and end-to-end scenarios against both the CLI and the packaged desktop app. Run the layer that matches what you changed, and let CI run the rest before merge. If you haven’t set up the toolchain yet, start with development setup.

make test runs everything: Rust, Angular, MCP, entrypoint, config, and desktop-build checks. For faster local loops, run just the layer you touched:

CommandWhat it runs
make test-rustRust unit and integration tests (speedwave-runtime, speedwave-cli)
make test-cliCLI-specific tests
make test-mcpAll MCP workspace tests (shared, hub, Slack, GitLab, and so on)
make test-angularAngular desktop UI tests
make test-e2eCLI end-to-end tests against the debug CLI (needs bats-core)
make test-entrypointContainer entrypoint script tests (needs bats-core)
make test-desktopDesktop integration tests, building the CLI, Angular, MCP, and OS CLI first

Desktop E2E tests aren’t part of the default make test target because they take much longer to run.

make coverage runs Rust, MCP, and Angular coverage together, or run make coverage-rust, make coverage-mcp, make coverage-angular individually. Thresholds live in each workspace’s vitest.config.ts for MCP and Angular, and Rust coverage fails under 70% lines. MCP workspaces mostly hold to 100% lines and functions, with a couple of exceptions sitting a few points lower.

The Office MCP worker has a split coverage story worth knowing about: the 100% vitest figure covers the TypeScript orchestration layer (path policy, argv construction, error handling), while the subprocesses it wraps, like pandoc, soffice, and the Python build scripts, are mocked in that suite. Those scripts get exercised for real by make test-mcp-office-py, which builds a throwaway virtual environment and reopens the generated documents with the real libraries. It runs in CI’s test job rather than under make coverage-mcp.

Desktop E2E tests drive a Tauri release binary with WebdriverIO. The app embeds tauri-plugin-webdriver, which serves W3C WebDriver on port 4445, so no external driver binary is needed on any platform.

make test-e2e-desktop builds the release binary on your current machine and runs the WebdriverIO suite against it. macOS needs Xcode command-line tools, Rust, and Node.js; Windows needs Rust, Node.js, and WebView2.

For coverage across both supported platforms, make test-e2e-all runs the suite on macOS and Windows in parallel over SSH to dedicated test machines (SPEEDWAVE_WINDOWS_HOST, SPEEDWAVE_MACOS_HOST). Each platform goes through three phases: build the release artifact, install it fresh and run the suite, then wipe all state and repeat the install and run a second time. That second fresh install catches state that survives a normal user-data wipe, like a leftover Lima cache or WSL2 distro.

The 18 spec files (desktop/e2e/specs/) mostly run in numeric order, covering app lifecycle, setup wizard, container health, navigation, settings, and project management, then chat, providers, integrations, logs, and OAuth login. 07-factory-reset.spec.ts is the one exception: the wdio config moves it to the end of the run regardless of its number, since it wipes local state and restarts the app, and nothing after it could survive that. All interactive elements expose data-testid attributes for these tests to target.

Rust unit tests live in #[cfg(test)] mod tests at the bottom of their source file, with integration tests under each crate’s tests/ directory. MCP tool tests import the tool’s createXTools() factory (returning ToolDefinition[] objects with tool and handler fields), mock the service client, and cover metadata shape, success cases, parameter validation, and error handling. Angular desktop tests use a MockTauriService to stand in for Tauri commands.