unit-tests.md 6.3 KB


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-651d1fb6c9 resource: repo://Cargo.toml
  • id: openwiki-source-1b05507d70 resource: repo://src/ai.rs
  • id: openwiki-source-9fec9d1af4 resource: repo://src/app.rs
  • id: openwiki-source-043e6252ba resource: repo://src/autoreply.rs
  • id: openwiki-source-2a737474d8 resource: repo://src/config.rs
  • id: openwiki-source-ce0c4ea8cd resource: repo://src/history.rs
  • id: openwiki-source-b55a21a31e resource: repo://src/main.rs
  • id: openwiki-source-6bddea306b resource: repo://src/ui.rs
  • id: openwiki-source-7b75006986 resource: repo://src/web.rs
  • id: openwiki-source-7ea5eac45e 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

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, Configuration, AI client, WhatsApp client, Web control panel, History store, Terminal UI, Application state, Runtime and event loop.