--- type: testing title: Unit tests description: Overview of the in-module unit test suites in src/*.rs (including the web panel and the version flag), what each one covers, how they isolate files, and how to run them. tags: [testing, cargo, unit-tests] verified: - by: openwiki/0.7.2 at: 2026-10-21T21:49:12.291Z sources: - id: openwiki-source-651d1fb6c9e49916a916ab51 resource: repo://Cargo.toml - id: openwiki-source-1b05507d7085e8e99a9b64f1 resource: repo://src/ai.rs - id: openwiki-source-9fec9d1af408501c9c455161 resource: repo://src/app.rs - id: openwiki-source-043e6252badc57a1ee6bfb48 resource: repo://src/autoreply.rs - id: openwiki-source-2a737474d86fc75cc9d9694f resource: repo://src/config.rs - id: openwiki-source-ce0c4ea8cd3b15431fa691ce resource: repo://src/history.rs - id: openwiki-source-b55a21a31ede1b56cd31a6a6 resource: repo://src/main.rs - id: openwiki-source-6bddea306b9b87f180f1fc02 resource: repo://src/ui.rs - id: openwiki-source-7b75006986d8b0337adc6ca0 resource: repo://src/web.rs - id: openwiki-source-7ea5eac45e5030178a6ea05b resource: repo://src/whatsapp.rs generated: { by: "claude-code", at: "2026-10-21T21:49:12.291Z" } --- # Unit tests All tests are plain Rust unit tests in `#[cfg(test)] mod tests` blocks at the bottom of each source file. There are no integration tests, no `[dev-dependencies]` (`Cargo.toml` only has `[dependencies]`) and no test touches the network, binds a port or uses a real WhatsApp session. ## Running ```sh cargo test # whole suite cargo test autoreply:: # one module cargo test should_schedule # by name filter ``` ## Suites | Module | Tests | Location | Covers | |---|---|---|---| | `autoreply` | 55 | `src/autoreply.rs:505+` | private/group/self-chat detection, `supports_autoreply` (groups yes, broadcasts and newsletters no), `ReplyGate::should_schedule` rules (disabled, own messages, self-chat, backlog, blank/placeholder text, voice notes and images trigger, pending chat), pending tracking and `take_pending`, `answered_by_owner`, `catch_up_due` rules, `build_turns` (system turn naming private chat, group or self-chat, roles, `is_ai` in the self-chat, context cap, blank texts skipped, voice notes, stored image descriptions vs. unseen images, assistant turns untouched, group sender prefixes), `context_start`, `mark_own_mentions` | | `config` | 37 | `src/config.rs:342+` | defaults, full files, ignored legacy `system_prompt` key, blank values, trimming, base URL normalisation, `Debug` masking, DB and AI log paths, `ai_log`, `reply_delay_seconds` (default, custom and `0`, negatives rejected, legacy cooldown keys ignored), catch-up and `ai_retries` defaults/custom values/negative rejection, `web_port` (unset, valid, `0` and out of range rejected), BOM/CRLF, non-leaking parse errors, missing/invalid/unreadable files, `SOUL.md` reading (missing, blank, as written without BOM, non-UTF-8 error naming the path) | | `ai` | 27 | `src/ai.rs:576+` | text request body with the `no_reply` tool, image description body (no tools) and its `vision.md`/default request, image validation limits, `describe_image` errors, `Debug` redaction, reply parsing (`no_reply` with or without text, other tool calls ignored, missing choices/content), endpoint construction, AI log records (no key, images redacted, `no_reply` record), logging only when enabled, append-only log writes, retry policy (`is_retryable`, `StatusError` message, linear `retry_delay`), truncation | | `whatsapp` | 22 | `src/whatsapp.rs:965+` | fatal-only app state sync reporting, message rendering and placeholders, captions, image references, voice/image detection, silent messages, JID device suffix, push-name filtering | | `app` | 20 | `src/app.rs:1443+` | autoreply enable rules (private, self-chat LID, groups; broadcasts, newsletters and missing AI refused), `web_chats` filtering and order, vision applicability, `select_images_to_describe` (last five in arrival order, known and out-of-context images skipped, nothing without vision), `arrived_after`, `manual_reply_after`, `description_failure_status`, list filter matching, selection, page steps and toggle helpers, AltGr handling, fixed function-key codes | | `history` | 18 | `src/history.rs:543+` | dedupe by message id, ordering and limits, `messages_since` (boundary, limit keeps most recent, ascending order), chat name fallbacks, per-chat and global autoreply flags, `message_exists`, image descriptions (per chat, replaced, deleted with the chat), `delete_chat`, contacts, on-disk open | | `ui` | 15 | `src/ui.rs:575+` | footer key help (F4 highlight), version label, sender labels, clock time, QR text, wrapping, visible lines, input tail, messages title, list title (global marker, filter), selection clamp | | `web` | 9 | `src/web.rs:366+` | query stripping, route resolution, `X-Wh-Request` header check (any case, missing/wrong value), which routes require it, request body trimming, empty/invalid UTF-8 rejection and the 1024-byte limit | | `main` | 2 | `src/main.rs:186+` | only `--version` / `-V` request the version; `BUILD_VERSION` starts with the package version and names a commit | Total: 205 `#[test]` functions. ## Test isolation - History tests use `History::open_in_memory()` (only compiled for tests, `src/history.rs:78-89`); the on-disk test writes under `std::env::temp_dir()` in a per-process directory (`src/history.rs:837-852`). - AI tests check request bodies, parsing, log records and the retry policy without sending requests; the append test writes a per-process file under `std::env::temp_dir()` and removes it (`src/ai.rs:856-868`). - Config tests that read `SOUL.md`-style prompt files write per-process scratch files under the `target` directory and remove them (`scratch_path`, `src/config.rs:349-375`). - Web tests exercise the pure routing and parsing helpers; the HTTP server itself is never started. Pages with module details: [AI autoreply](../workflows/ai-autoreply.md), [Configuration](../operations/configuration-and-data.md), [AI client](../integrations/ai-client.md), [WhatsApp client](../integrations/whatsapp-client.md), [Web control panel](../integrations/web-control-panel.md), [History store](../concepts/history-store.md), [Terminal UI](../architecture/terminal-ui.md), [Application state](../architecture/app-state.md), [Runtime and event loop](../architecture/runtime-and-event-loop.md).