From 7f1a4ce1f1aa5bf4b07499fc7803c91188ca865d Mon Sep 17 00:00:00 2001 From: ruohki Date: Sat, 28 Feb 2026 20:12:08 +0100 Subject: [PATCH] docs: map existing codebase --- .planning/codebase/ARCHITECTURE.md | 97 +++++++++ .planning/codebase/CONCERNS.md | 104 +++++++++ .planning/codebase/CONVENTIONS.md | 200 ++++++++++++++++++ .planning/codebase/INTEGRATIONS.md | 76 +++++++ .planning/codebase/STACK.md | 128 ++++++++++++ .planning/codebase/STRUCTURE.md | 120 +++++++++++ .planning/codebase/TESTING.md | 324 +++++++++++++++++++++++++++++ 7 files changed, 1049 insertions(+) create mode 100644 .planning/codebase/ARCHITECTURE.md create mode 100644 .planning/codebase/CONCERNS.md create mode 100644 .planning/codebase/CONVENTIONS.md create mode 100644 .planning/codebase/INTEGRATIONS.md create mode 100644 .planning/codebase/STACK.md create mode 100644 .planning/codebase/STRUCTURE.md create mode 100644 .planning/codebase/TESTING.md diff --git a/.planning/codebase/ARCHITECTURE.md b/.planning/codebase/ARCHITECTURE.md new file mode 100644 index 0000000..cbc20ca --- /dev/null +++ b/.planning/codebase/ARCHITECTURE.md @@ -0,0 +1,97 @@ +# Architecture + +**Analysis Date:** 2026-02-28 + +## Pattern Overview + +**Overall:** Single-Binary CLI/TUI Application (Rust) + +**Key Characteristics:** +- Monolithic Rust binary using Ratatui for terminal UI +- Minimal dependency footprint (only Ratatui as external dependency) +- Single entry point with main function +- Early-stage project with foundational structure only + +## Layers + +**Presentation Layer:** +- Purpose: Terminal user interface rendering and interaction +- Location: `src/main.rs` (currently) +- Contains: TUI initialization, event handling, widget rendering +- Depends on: Ratatui framework +- Used by: End users through terminal + +**Business Logic Layer:** +- Purpose: Core application functionality +- Location: TBD - not yet implemented +- Contains: Data processing, command handling, state management +- Depends on: None currently defined +- Used by: Presentation layer + +**Data Layer:** +- Purpose: Data persistence and retrieval +- Location: TBD - not yet implemented +- Contains: File I/O, caching, serialization +- Depends on: Standard library (File, IO) +- Used by: Business logic layer + +## Data Flow + +**Typical User Interaction Flow:** + +1. Terminal input captured by Ratatui event handling +2. User action (keyboard/mouse) parsed into application command +3. Command dispatched to business logic handler +4. Handler processes request, potentially reads/writes data +5. State updated based on result +6. UI re-rendered with new state in next frame + +**State Management:** +- Single application state entity (not yet defined) +- Immutable state passed to rendering function +- Ratatui handles incremental screen updates + +## Key Abstractions + +**Terminal User Interface (TUI):** +- Purpose: Encapsulate all terminal rendering and input handling +- Examples: `src/main.rs` (current single module) +- Pattern: React-like paradigm via Ratatui (state -> render) + +**Application Command/Action:** +- Purpose: Abstract user intentions from input events +- Examples: Not yet implemented +- Pattern: Enum-based command pattern expected + +## Entry Points + +**Binary Entry:** +- Location: `src/main.rs` +- Triggers: `cargo run` or binary execution +- Responsibilities: + - Initialize Ratatui terminal + - Set up event loop + - Handle application lifecycle + - Render UI each frame + - Currently: Placeholder with "Hello, world!" output + +## Error Handling + +**Strategy:** Not yet defined + +**Patterns:** +- Ratatui provides Result types for I/O operations +- Expected approach: Result-based error propagation using ? operator +- Terminal restoration should be ensured on panic (Ratatui provides Drop impl) + +## Cross-Cutting Concerns + +**Logging:** Not yet implemented. Standard approach would use `log` crate or println! macros during development. + +**Validation:** Not yet implemented. Expected in business logic layer once commands are defined. + +**Terminal State:** Ratatui manages terminal state (raw mode, cursor visibility, etc.). Must ensure proper cleanup on application exit. + +--- + +*Architecture analysis: 2026-02-28* diff --git a/.planning/codebase/CONCERNS.md b/.planning/codebase/CONCERNS.md new file mode 100644 index 0000000..724c4c8 --- /dev/null +++ b/.planning/codebase/CONCERNS.md @@ -0,0 +1,104 @@ +# Codebase Concerns + +**Analysis Date:** 2026-02-28 + +## Critical Issues + +**Empty Application Stub:** +- Issue: The entire application is a bare "Hello, world!" stub with no functional implementation +- Files: `src/main.rs` +- Impact: No actual BBS markdown functionality exists; application is not usable +- Fix approach: Implement core application logic for markdown bulletin board system functionality + +**Invalid Edition Specification:** +- Issue: `Cargo.toml` specifies `edition = "2024"` which is not a valid Rust edition +- Files: `Cargo.toml` +- Impact: Build will fail or behave unexpectedly if edition validation is enforced; incorrect edition can affect language feature availability +- Fix approach: Change to a valid edition: `2021` (latest stable) or `2018` if legacy support needed + +## Tech Debt + +**Minimal Dependency Management:** +- Issue: Heavy dependency on ratatui (0.30.0) and its entire ecosystem for a stub application +- Files: `Cargo.toml` +- Impact: Unnecessary compiled binary size and build time for functionality that doesn't yet exist; approximately 60+ transitive dependencies for "Hello, world!" +- Fix approach: Keep ratatui when actual TUI is implemented; document why ratatui was chosen early + +**No Error Handling:** +- Issue: Application has no error handling, logging, or graceful failure modes +- Files: `src/main.rs` +- Impact: Crashes will be silent or unhelpful; no debugging information available +- Fix approach: Implement structured error handling; consider using `anyhow` or `thiserror` crate (already available in dependencies) + +**No Architecture Documentation:** +- Issue: Zero guidance on how BBS-MD should be structured or what features should be implemented +- Files: Project root (missing design docs) +- Impact: Development direction unclear; future contributors won't understand intent +- Fix approach: Create architecture documentation, feature specification, and roadmap + +## Missing Critical Features + +**No TUI Implementation:** +- What's missing: Terminal UI is imported (ratatui) but never used +- Blocks: Cannot create/view/edit bulletin board content +- Priority: High + +**No Data Persistence:** +- What's missing: No markdown file handling, no storage mechanism +- Blocks: Cannot persist BBS posts or configuration +- Priority: High + +**No Input Processing:** +- What's missing: Application ignores user input entirely +- Blocks: Cannot interact with application +- Priority: High + +## Test Coverage Gaps + +**Zero Testing:** +- What's not tested: All functionality (or complete lack thereof) +- Files: No test directory exists; `src/main.rs` has no tests +- Risk: No confidence in correctness; refactoring will be dangerous +- Priority: High + +## Scalability & Architecture Concerns + +**Monolithic Structure:** +- Problem: Single main.rs file will quickly become unmaintainable as features are added +- Current capacity: ~45 lines before severe maintainability issues +- Scaling path: Create modular structure with separate modules for TUI layer, data layer, business logic + +**Dependency Organization:** +- Problem: Entire ratatui ecosystem locked in at build time even when not used +- Current capacity: 60+ transitive dependencies inflating binary +- Scaling path: Feature-gate dependencies or defer dependency addition until features are implemented + +## Security Considerations + +**Unvalidated Input:** +- Risk: Once input processing is added, no visible validation or sanitization strategy exists +- Files: Will be implemented in future features +- Current mitigation: None (application ignores input) +- Recommendations: Plan input validation for markdown parsing; sanitize user-provided content if displayed; consider file path traversal protections if file loading is implemented + +**File System Access:** +- Risk: Future markdown file handling could expose security issues (directory traversal, privilege escalation) +- Files: Not yet implemented +- Current mitigation: None +- Recommendations: When implementing file I/O, enforce strict path validation; restrict operations to designated directories only + +## Dependencies at Risk + +**Edition Mismatch:** +- Risk: Invalid edition specification may cause build failures or unexpected behavior in future toolchain versions +- Impact: Application may not compile with newer Rust tools +- Migration plan: Immediately fix to `edition = "2021"` to match stable toolchain + +**Tight Coupling to Ratatui:** +- Risk: Early adoption of specific TUI framework before requirements are clear +- Impact: Switching frameworks later will require significant refactoring +- Migration plan: Encapsulate ratatui behind abstraction layer; consider generic TUI trait to allow future framework swaps + +--- + +*Concerns audit: 2026-02-28* diff --git a/.planning/codebase/CONVENTIONS.md b/.planning/codebase/CONVENTIONS.md new file mode 100644 index 0000000..feff410 --- /dev/null +++ b/.planning/codebase/CONVENTIONS.md @@ -0,0 +1,200 @@ +# Coding Conventions + +**Analysis Date:** 2026-02-28 + +## Overview + +This is an early-stage Rust project with minimal codebase (single `main.rs` file). Conventions are established based on: +- Rust language defaults and community standards +- Cargo default behavior +- Current code patterns in the project + +## Naming Patterns + +**Files:** +- Snake case: `main.rs`, `lib.rs` are standard entry points +- Module files use snake_case: `user_service.rs`, `data_handler.rs` +- Test modules within files or in separate `tests/` directory + +**Functions:** +- Snake case throughout: `fn handle_connection()`, `fn parse_input()` +- Use descriptive verb-based names: `fn calculate_sum()`, `fn build_response()` + +**Variables:** +- Snake case for bindings: `let user_id`, `let response_data` +- Constants use UPPER_CASE: `const MAX_BUFFER_SIZE: usize = 1024` +- Mutable bindings explicitly marked: `let mut count = 0` + +**Types and Structs:** +- PascalCase for type names: `struct User`, `enum Status`, `trait Handler` +- Generic parameters use single letters or PascalCase: `T`, `S`, `Request` +- Lifetime parameters use lowercase: `'a`, `'static` + +## Code Style + +**Formatting:** +- Default Rust formatting applied by `rustfmt` (de facto standard) +- 4-space indentation (Rust default) +- No semicolons in final expressions that return values +- Closing braces on same line except for block statements + +**Linting:** +- Clippy lints should be addressed as part of development +- No explicit `clippy.toml` or linting configuration currently present +- Default clippy warnings and errors should be resolved before commit + +**Edition:** +- Rust 2024 edition (specified in `Cargo.toml`) +- Supports latest language features and idioms + +## Import Organization + +**Order:** +1. Standard library imports (`use std::`) +2. External crate imports (`use ratatui::`, other external deps) +3. Internal crate imports (`use crate::`) +4. Module declarations (`mod xyz;`) + +**Example:** +```rust +use std::io; +use std::collections::HashMap; + +use ratatui::backend::CrosstermBackend; +use ratatui::Terminal; + +use crate::ui::draw; +use crate::handler::InputHandler; +``` + +**Path Aliases:** +- No path aliases configured currently +- Can be added via workspace root configuration if needed + +## Error Handling + +**Patterns:** +- Use `Result` for fallible operations +- Propagate errors with `?` operator rather than unwrapping when possible +- Use `anyhow::Result` for application-level errors (dependency available) +- Only use `.unwrap()` or `.expect()` for code that should never panic in normal operation + +**Example:** +```rust +fn read_config(path: &str) -> Result { + let content = std::fs::read_to_string(path)?; + let config = serde_json::from_str(&content)?; + Ok(config) +} +``` + +## Logging + +**Framework:** Not yet selected/integrated + +**When logging is added:** +- Use `log` crate for production logging +- Use `env_logger` or similar for log configuration +- Log levels: ERROR for failures, WARN for unusual conditions, INFO for significant events, DEBUG for detailed traces +- Avoid logging sensitive data (credentials, tokens, PII) + +## Comments + +**When to Comment:** +- Explain the "why" not the "what" +- Document non-obvious algorithmic decisions +- Explain trade-offs or workarounds +- Mark intentional violations of conventions with `// FIXME:` or `// TODO:` + +**Doc Comments:** +- Use `///` for public item documentation +- Document public functions, structs, enums, traits +- Include examples for complex or non-obvious public APIs + +**Example:** +```rust +/// Processes a user command from the input buffer. +/// +/// This function parses the raw input and dispatches to appropriate handlers. +/// +/// # Arguments +/// * `input` - Raw user input string +/// +/// # Returns +/// `Result` indicating success or the error encountered +pub fn process_command(input: &str) -> Result { + // Implementation +} +``` + +## Function Design + +**Size:** +- Keep functions small and focused (ideally < 50 lines) +- Extract helper functions for complex logic +- Separate parsing, validation, and execution logic + +**Parameters:** +- Use owned values for simple types, references for larger types +- Prefer `&[T]` over `&Vec` for function parameters +- Use structs to group related parameters (> 3 related params) + +**Return Values:** +- Use `Result` for operations that can fail +- Use `Option` for values that may be absent +- Avoid returning `Box` unless necessary for dynamic dispatch + +## Module Design + +**Exports:** +- Explicitly declare public items with `pub` +- Use `pub use` to re-export important types at module boundaries +- Keep implementation details private (`non-pub` by default) + +**Module Structure:** +```rust +// src/main.rs +mod ui; +mod handler; +mod model; + +use ui::App; +use handler::InputHandler; + +fn main() { + // Implementation +} +``` + +**Barrel Files:** +- Use `mod.rs` files in subdirectories to organize module exports +- Example: `src/ui/mod.rs` exports types from `ui/draw.rs`, `ui/state.rs` + +## Unsafe Code + +**Usage:** +- Avoid unsafe blocks unless necessary for FFI or performance-critical code +- Document unsafe code with `// SAFETY:` comments explaining invariants +- Minimize unsafe scope + +**Example:** +```rust +// SAFETY: ptr is guaranteed to point to valid, initialized memory +// returned from foreign_function, which owns its lifetime +unsafe { + let result = process_data(ptr); +} +``` + +## Workspace and Multi-Crate Structure + +**Currently:** Single binary crate (`bbs-md`) + +**If expanding:** +- Consider separating into `bbs-md` (binary) and `bbs-md-core` (library) +- Use workspace for shared dependencies and configuration +- Place library code in `src/lib.rs`, binary-specific code in `src/main.rs` + +--- + +*Convention analysis: 2026-02-28* diff --git a/.planning/codebase/INTEGRATIONS.md b/.planning/codebase/INTEGRATIONS.md new file mode 100644 index 0000000..d59b27b --- /dev/null +++ b/.planning/codebase/INTEGRATIONS.md @@ -0,0 +1,76 @@ +# External Integrations + +**Analysis Date:** 2026-02-28 + +## APIs & External Services + +**Not detected** - This is a standalone TUI application with no external API integrations. + +## Data Storage + +**Databases:** +- Not detected - No database client/ORM dependencies present + +**File Storage:** +- Local filesystem only - Markdown files read/written to local disk + +**Caching:** +- Not detected - No external caching service + +## Authentication & Identity + +**Auth Provider:** +- Custom or None - No authentication framework detected + +**Implementation:** +- Local-only TUI application with no user authentication layer + +## Monitoring & Observability + +**Error Tracking:** +- Not detected - No error tracking service integration + +**Logs:** +- Standard output/stderr via log crate facade +- Controlled via application logging configuration + +## CI/CD & Deployment + +**Hosting:** +- Standalone binary deployment - Compiled as single executable + +**CI Pipeline:** +- Not detected - No CI/CD configuration files present + +## Environment Configuration + +**Required env vars:** +- None detected - Configuration appears to be hardcoded or via CLI arguments + +**Secrets location:** +- Not applicable - No external service credentials required + +## Webhooks & Callbacks + +**Incoming:** +- Not applicable - Standalone CLI application + +**Outgoing:** +- Not applicable - No webhook support detected + +## Terminal Environment + +**Integration Points:** +- Terminal protocol: VT100 escape sequences +- Platform support via crossterm: + - Unix/Linux systems: Raw mode via termios + - Windows systems: Windows API for console mode + - macOS: POSIX terminal support + +**Signal Handling:** +- Unix signals (SIGTERM, SIGINT) for graceful shutdown +- Integrated via signal-hook and mio event loop + +--- + +*Integration audit: 2026-02-28* diff --git a/.planning/codebase/STACK.md b/.planning/codebase/STACK.md new file mode 100644 index 0000000..9f8514d --- /dev/null +++ b/.planning/codebase/STACK.md @@ -0,0 +1,128 @@ +# Technology Stack + +**Analysis Date:** 2026-02-28 + +## Languages + +**Primary:** +- Rust - CLI/TUI application for markdown bulletin board system + +## Runtime + +**Environment:** +- Rust compiler and runtime + +**Package Manager:** +- Cargo +- Lockfile: `Cargo.lock` present + +## Frameworks + +**Core:** +- ratatui 0.30.0 - Terminal user interface (TUI) framework for building rich CLI applications + +**Build:** +- cargo - Rust package manager and build system + +## Key Dependencies + +**Critical:** +- ratatui 0.30.0 - Main TUI framework providing terminal rendering, event handling, and widgets +- ratatui-core - Core functionality for ratatui +- ratatui-crossterm - Crossterm backend integration for ratatui +- ratatui-macros - Proc macros for ratatui +- ratatui-termwiz - Termwiz backend support for ratatui +- ratatui-widgets - Widget library for ratatui + +**Terminal & Input:** +- crossterm 0.29.0 - Cross-platform terminal manipulation library (Windows/Unix compatible) +- signal-hook - Unix signal handling for clean shutdowns +- signal-hook-mio - Integration between signal-hook and mio +- termwiz - Terminal operations library with wide character support +- terminfo - Terminal capability detection +- vtparse - VT100 escape sequence parser +- utf8parse - UTF-8 parsing utilities + +**UI Rendering & Text:** +- unicode-width - Calculate display width of unicode characters +- unicode-truncate - Truncate unicode strings to display width +- unicode-segmentation - Segment unicode text +- wezterm-bidi - Bidirectional text support +- fancy-regex - Advanced regex support with lookahead/lookbehind +- regex 1.x - Regular expression library + +**Graphics & Color:** +- csscolorparser 0.6.2 - Parse CSS color strings +- wezterm-color-types - Color type definitions +- euclid - 2D and 3D geometry primitives +- line-clipping - Line clipping algorithms + +**Data Structures & Utilities:** +- indexmap - Hash map preserving insertion order +- hashbrown - Faster hashmap implementation +- smallvec - Vector that stores small amounts inline +- itertools - Iterator extensions +- nom - Parser combinators library +- pest - PEG parser generator +- strum/strum_macros - Enum utilities and macros + +**Serialization:** +- serde/serde_json - Serialization framework +- base64 - Base64 encoding/decoding + +**Error Handling:** +- anyhow 1.0.102 - Flexible error handling +- thiserror - Structured error types + +**Platform Support:** +- libc - C library bindings (Unix) +- rustix - Wrapper around system calls +- nix - Unix-like API bindings +- winapi - Windows API bindings +- windows-sys - Windows system APIs +- parking_lot - Synchronization primitives + +**Hashing & Crypto:** +- sha2 - SHA-2 digest algorithms +- xxhash-rust - xxHash algorithm + +**UUID & ID Generation:** +- uuid - UUID generation and parsing +- mac_address - MAC address utilities + +**Logging:** +- log - Logging facade + +**Development & Macros:** +- syn - Rust syntax tree parsing +- quote - Quoting for proc macros +- proc-macro2 - Proc macro utilities +- darling - Attribute macro argument parsing + +## Configuration + +**Build Configuration:** +- Edition: 2024 (Rust edition) +- Target: Binary executable +- Manifest: `Cargo.toml` + +**Dependencies Management:** +- Lock file: `Cargo.lock` ensures reproducible builds +- All dependencies from crates.io registry +- Transitive dependency management handled by Cargo + +## Platform Requirements + +**Development:** +- Rust toolchain (cargo) +- POSIX-compliant system (Linux, macOS) or Windows +- Terminal support for modern escape sequences + +**Production:** +- Binary compiled for target platform (Linux, macOS, Windows) +- Terminal with VT100 escape sequence support +- UTF-8 capable terminal + +--- + +*Stack analysis: 2026-02-28* diff --git a/.planning/codebase/STRUCTURE.md b/.planning/codebase/STRUCTURE.md new file mode 100644 index 0000000..a09df59 --- /dev/null +++ b/.planning/codebase/STRUCTURE.md @@ -0,0 +1,120 @@ +# Codebase Structure + +**Analysis Date:** 2026-02-28 + +## Directory Layout + +``` +bbs-md/ +├── src/ # Rust source code +│ └── main.rs # Binary entry point and main application logic +├── target/ # Build artifacts (generated) +├── .git/ # Git repository metadata +├── .planning/ # Planning and documentation +│ └── codebase/ # Architecture and structure docs +├── Cargo.toml # Rust package manifest +├── Cargo.lock # Dependency lock file +└── .gitignore # Git ignore rules +``` + +## Directory Purposes + +**src/** +- Purpose: All Rust source code for the project +- Contains: Rust modules and binary logic +- Key files: `main.rs` + +**.planning/codebase/** +- Purpose: Architecture and codebase analysis documents +- Contains: ARCHITECTURE.md, STRUCTURE.md, CONVENTIONS.md, TESTING.md (as written) +- Generated by: Codebase mapping process + +**target/** +- Purpose: Build output directory (generated by Cargo) +- Contains: Compiled binaries, dependencies, metadata +- Generated: Yes +- Committed: No (in .gitignore) + +## Key File Locations + +**Entry Points:** +- `src/main.rs`: Main binary executable, contains fn main() and all current application logic + +**Configuration:** +- `Cargo.toml`: Package metadata, dependencies, build configuration + +**Build Output:** +- `Cargo.lock`: Locked dependency versions ensuring reproducible builds + +## Naming Conventions + +**Files:** +- `main.rs`: Entry point for binary crate +- `lib.rs`: Would be used for library crate (not present) +- Module files: `module_name.rs` (snake_case) +- Cargo files: `Cargo.toml`, `Cargo.lock` + +**Directories:** +- `src/`: Source code directory (Rust convention) +- `target/`: Build output (Cargo convention) +- Module directories: `snake_case/` for organizing modules into subdirectories + +**Modules:** +- Snake_case for module names in Rust +- Single-word module names preferred for clarity + +## Where to Add New Code + +**New Feature:** +- Primary code: `src/main.rs` until structure grows +- Once > 300 lines: Extract to `src/feature_name.rs`, then `mod feature_name;` in main.rs +- Tests: In same file with `#[cfg(test)]` module, or separate `src/feature_name_test.rs` + +**New Component/Module:** +- Implementation: Create `src/module_name.rs` +- Export in `src/main.rs` with `mod module_name;` +- Public items: Use `pub` keyword and re-export in main if needed for internal use + +**Utilities:** +- Shared helpers: Create `src/utils.rs` or `src/common.rs` for cross-cutting utilities +- General-purpose: Keep in dedicated module, expose via public functions + +**UI Components:** +- Ratatui-specific code: Keep in dedicated module like `src/ui.rs` or `src/widgets.rs` +- Separate widget rendering logic from business logic +- Re-export commonly used widgets from central location + +## Special Directories + +**target/:** +- Purpose: Contains compiled binaries, intermediate build files, and dependencies +- Generated: Yes +- Committed: No + +**.git/:** +- Purpose: Git repository metadata +- Generated: Yes +- Committed: Not applicable (part of .git directory) + +## Recommended Module Organization (As Project Grows) + +Once the codebase expands beyond the current single-file structure: + +``` +src/ +├── main.rs # Binary entry, module declarations, main loop +├── app.rs # Application state and core logic +├── ui/ +│ ├── mod.rs # UI module exports +│ ├── widgets.rs # Custom widget definitions +│ └── events.rs # Event handling logic +├── commands.rs # Command/action definitions +├── errors.rs # Error types +└── utils.rs # Utility functions +``` + +This structure keeps concerns separated while maintaining minimal interdependencies. + +--- + +*Structure analysis: 2026-02-28* diff --git a/.planning/codebase/TESTING.md b/.planning/codebase/TESTING.md new file mode 100644 index 0000000..1650f8a --- /dev/null +++ b/.planning/codebase/TESTING.md @@ -0,0 +1,324 @@ +# Testing Patterns + +**Analysis Date:** 2026-02-28 + +## Test Framework + +**Test Runner:** +- Rust built-in test framework (via `cargo test`) +- No external test framework currently integrated +- Can add `tokio` for async testing if needed later + +**Assertion Library:** +- Standard `assert!()` and `assert_eq!()` macros from standard library +- Can add `pretty_assertions` crate for better failure output if desired + +**Run Commands:** +```bash +cargo test # Run all tests +cargo test -- --nocapture # Run tests with output visible +cargo test -- --test-threads=1 # Run tests sequentially +cargo test --lib # Run only library tests +cargo test --doc # Run doctests +``` + +**Watch Mode:** +```bash +# Using cargo-watch (install with: cargo install cargo-watch) +cargo watch -x test # Re-run tests on file changes +``` + +**Coverage:** +```bash +# Using cargo-tarpaulin (install with: cargo install cargo-tarpaulin) +cargo tarpaulin --out Html # Generate HTML coverage report +``` + +## Test File Organization + +**Location - Unit Tests:** +- Co-located with implementation: Tests in same file as source code +- Tests go in submodule at end of source file + +**Location - Integration Tests:** +- Separate `tests/` directory at workspace root +- File: `tests/integration_test.rs` or similar +- Each file is compiled as separate crate + +**Naming:** +- Unit test modules: `#[cfg(test)] mod tests` +- Integration test files: `integration_test.rs`, `e2e_test.rs` +- Test functions: `test_function_name_description()` +- Unit tests: `tests::test_parses_valid_input()` + +**Current Structure:** +``` +src/ +├── main.rs # Contains #[cfg(test)] mod tests +├── lib.rs # If created, contains library tests +└── ... + +tests/ +├── integration_test.rs +└── ... +``` + +## Test Structure + +**Suite Organization - Unit Test Pattern:** +```rust +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_function_does_something() { + let input = setup_test_data(); + let result = function_under_test(input); + assert_eq!(result, expected_value); + } +} +``` + +**Suite Organization - Integration Test Pattern:** +```rust +// tests/integration_test.rs +#[test] +fn test_system_integrates_correctly() { + let app = App::new(); + let result = app.process_command("help"); + assert!(result.is_ok()); +} +``` + +**Patterns:** +- **Setup:** Create test data or fixtures in test function body +- **Teardown:** Not typically needed in Rust; cleanup happens automatically when test scope ends +- **Assertion:** Use `assert!()`, `assert_eq!()`, `assert_ne!()` for conditions + +## Mocking + +**Framework:** No explicit mocking framework currently integrated + +**If mocking becomes necessary:** +- Use `mockito` crate for HTTP mocking +- Use `mockall` crate for trait-based mocking +- Use `proptest` crate for property-based testing + +**Current Approach:** +- Manual test doubles: Create simplified implementations of traits for testing +- Dependency injection: Pass different implementations at test time +- Stub data: Return hardcoded test data instead of external calls + +**Example of Manual Test Double:** +```rust +#[cfg(test)] +mod tests { + struct MockDataStore { + data: Vec, + } + + impl DataStore for MockDataStore { + fn fetch(&self, id: u32) -> Option { + self.data.get(id as usize).cloned() + } + } + + #[test] + fn test_with_mock() { + let mock = MockDataStore { data: vec!["test".to_string()] }; + let result = process_data(&mock); + assert!(result.is_ok()); + } +} +``` + +**What to Mock:** +- External service calls (network, file I/O) +- Database operations +- Time-dependent behavior +- Hardware-dependent code + +**What NOT to Mock:** +- Core business logic +- Standard library functions +- Tested utility functions +- Pure functions + +## Fixtures and Factories + +**Test Data:** +- Currently: Manual test data created in test functions +- Pattern: Helper functions to build test objects + +**Example:** +```rust +#[cfg(test)] +mod tests { + fn create_test_user() -> User { + User { + id: 1, + name: "Test User".to_string(), + email: "test@example.com".to_string(), + } + } + + #[test] + fn test_user_creation() { + let user = create_test_user(); + assert_eq!(user.name, "Test User"); + } +} +``` + +**Location:** +- Helper functions in same module as tests: `#[cfg(test)] mod tests` +- If many fixtures needed: Create `src/test_utils.rs` (not included in release build via `#[cfg(test)]`) + +## Coverage + +**Requirements:** Not currently enforced + +**To Enable Coverage Tracking:** +```bash +# Using llvm-cov (install with: cargo install cargo-llvm-cov) +cargo llvm-cov # Generate coverage report +cargo llvm-cov --html # HTML report in target/llvm-cov/html +``` + +**Target for new code:** +- Aim for 80%+ coverage on public APIs +- 100% coverage on critical paths +- Document uncovered code with `#[cfg(test)]` or comments + +## Test Types + +**Unit Tests:** +- Scope: Single function or small module in isolation +- Approach: Test behavior with various inputs including edge cases +- Location: Same file as implementation in `#[cfg(test)] mod tests` +- Tools: Standard library assertions + +**Integration Tests:** +- Scope: Multiple components working together +- Approach: Test workflows and interactions between modules +- Location: `tests/` directory at workspace root +- Tools: Standard library assertions + +**Doc Tests:** +- Scope: Examples in `///` doc comments +- Approach: Verify example code actually works +- Location: Documentation strings in source +- Tools: Built-in `cargo test --doc` + +**E2E Tests:** +- Currently: Not applicable (TUI application, no external API) +- When applicable: Test complete user workflows end-to-end + +**Example Doc Test:** +```rust +/// Calculate the sum of two numbers. +/// +/// # Examples +/// +/// ``` +/// assert_eq!(add(2, 2), 4); +/// ``` +pub fn add(a: i32, b: i32) -> i32 { + a + b +} +``` + +## Common Patterns + +**Async Testing:** +- Not currently used (no async in codebase) +- When needed: Use `#[tokio::test]` attribute with `tokio` crate + +**Example (future reference):** +```rust +#[tokio::test] +async fn test_async_function() { + let result = async_operation().await; + assert!(result.is_ok()); +} +``` + +**Error Testing:** +- Test both success and failure paths +- Use `.is_err()` or `.is_ok()` to test Result types +- Use `.is_some()` or `.is_none()` to test Option types + +**Example:** +```rust +#[test] +fn test_handles_invalid_input() { + let result = parse_config("invalid"); + assert!(result.is_err()); +} + +#[test] +fn test_handles_valid_input() { + let result = parse_config("valid"); + assert!(result.is_ok()); +} +``` + +**Property-Based Testing (future):** +If using `proptest`: +```rust +#[test] +fn test_reverse_is_involutive(input in ".*") { + let reversed = reverse(&input); + let double_reversed = reverse(&reversed); + assert_eq!(input, double_reversed); +} +``` + +## Test Organization Best Practices + +**File Structure:** +``` +src/ +├── main.rs +├── ui.rs # Contains #[cfg(test)] mod tests at bottom +├── handler.rs # Contains #[cfg(test)] mod tests at bottom +└── model.rs # Contains #[cfg(test)] mod tests at bottom + +tests/ +├── integration_tests.rs # Full-system integration tests +└── fixtures/ # Test data files if needed +``` + +**Test Module Template:** +```rust +// At end of source file +#[cfg(test)] +mod tests { + use super::*; + + // Setup helpers + fn create_test_fixture() -> TestData { + // ... + } + + // Tests organized by function + mod function_name_tests { + use super::*; + + #[test] + fn test_success_case() { + // ... + } + + #[test] + fn test_error_case() { + // ... + } + } +} +``` + +--- + +*Testing analysis: 2026-02-28*