--- name: Tests type: architecture-map-page slice: 02-tauri-runtime last_verified: 2026/05/09 --- # Tests > **Where you are:** [Architecture map](../README.md) → [Tauri runtime](README.md) → Tests **Plain English summary.** A single integration test file that protects three security-relevant config invariants: the loopback LLM CSP must stay narrow, any updater config that ships must carry a non-empty pubkey, and the secondary windows must never get high-risk plugin permissions. Unit tests live alongside the code they test (each command file has its own `#[cfg(test)]` module). ## At a glance - Path: `src-tauri/tests/config_hardening.rs` (93 LOC). - Tauri commands exposed: none. - Events emitted: none. - Depends on: `serde_json` (for parsing the JSON configs), `std::fs` and `std::path::Path` (for walking the capabilities directory). ## What's in here ### `csp_keeps_loopback_narrow` (`src-tauri/tests/config_hardening.rs:15`) Reads `src-tauri/tauri.conf.json`, finds the `connect-src` directive of `app.security.csp`, asserts: - `http://127.0.0.1:*` is present. - `ws://127.0.0.1:*` is present. - `http://localhost:*` is absent. - `ws://localhost:*` is absent. This is the runtime sibling of the build-time guard in `src-tauri/build.rs:30`. Both must agree. The build guard is the harder check (it stops compilation) and the integration test is the safety net for someone running `cargo test` without `cargo build` between edits. ### `updater_is_signed_or_absent` (`src-tauri/tests/config_hardening.rs:35`) If `plugins.updater` exists in `tauri.conf.json`, asserts the `pubkey` field is a non-empty string. If `plugins.updater` is absent (which it currently is), the test is a no-op. The intent is that you cannot accidentally ship an updater config with a placeholder / empty key. ### `secondary_windows_do_not_get_high_risk_plugin_permissions` (`src-tauri/tests/config_hardening.rs:50`) Scans `src-tauri/capabilities/*.json`. For each capability whose `windows` array references any of `tasks-float`, `transcript-viewer`, or `transcription-preview`, asserts no permission starts with the prefixes `dialog:`, `autostart:`, `global-shortcut:`, `opener:`, or `updater:`. Catches drift the moment someone adds, say, `dialog:default` to a secondary capability. See [Capabilities and ACL](capabilities-and-acl.md). ### Unit tests (other locations) Each command module has its own `#[cfg(test)] mod tests` block. Notable ones: - `commands/audio.rs` — `recording_filenames_are_unique_across_rapid_calls` (RB-06 regression for filename collisions), `stop_worker_awaits_full_termination_no_writes_after_join`, `stop_worker_is_idempotent`. - `commands/models.rs` — `compose_accelerators` matrix (RB-07 regression for the hard-coded `["cpu", "vulkan"]` bug). - `commands/llm.rs` — `classify_llm_load_error` covers VRAM / corrupt-file / permission / unknown classifications. - `commands/paste.rs` — terminal classifier and PowerShell escape-sequence tests. - `commands/intentions.rs` — `validate_hhmm` accepts/rejects. - `commands/power.rs` — `power_assertion_is_a_no_op_drop` (registry hygiene), `multiple_assertions_get_unique_ids`. - `commands/security.rs` — `accepts_main_window` / `rejects_secondary_windows` for `ensure_main_window_label`. - `commands/tts.rs` — rate-clamp, platform-specific rate-mapping, macOS voice parser, Windows here-string escape. - `commands/fs.rs` — `write_text_file_roundtrips_utf8`, `write_text_file_errors_on_bad_parent`. - `commands/mod.rs` — `build_initial_prompt` shape across all combinations of caller/profile/term inputs. ## Data flow - The integration test file loads `tauri.conf.json` and the `capabilities/*.json` files at runtime via `env!("CARGO_MANIFEST_DIR")`. No Tauri runtime is started. - Unit tests stay in the same compilation units as their target code, so they have direct access to private functions. ## Watch-outs - The integration test crate does not build with the full Tauri runtime. If you ever need a test that exercises `tauri::Builder` end-to-end, you will need to add a `#[tokio::test]` with a `tauri::test::mock_app()` helper, which is not currently used anywhere. - `csp_keeps_loopback_narrow` uses `directive.starts_with("connect-src ")` (with trailing space) which would match `connect-src-elem` — BUT the build-time guard in `build.rs` does the stricter full-name match. If the CSP ever gains a `connect-src-elem` directive that shouldn't include the loopback entries, this integration test would still pass while the build guard correctly checks the actual `connect-src`. Worth tightening for parity. - The `updater_is_signed_or_absent` test is currently a no-op because no `plugins.updater` block ships. The first time a real updater config lands, the test will run. Document that fact in the PR that adds the updater so reviewers know the previously-passing test now checks something. ## See also - [Tauri config](tauri-config.md) — the file the CSP test reads. - [Capabilities and ACL](capabilities-and-acl.md) — the files the secondary-windows test walks. - [Cargo and features](cargo-and-features.md) — the build-time CSP guard pair. - [Commands README](commands/README.md) — index of the command-level unit tests.