cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists ๐Ÿƒ
charm leaflet readability golang

docs: update README and add architecture and testing documentation

+414 -175
+64 -3
README.md
··· 16 16 .JML. YM `Ybmd9' `Mbmo`Mbmmd'.JMML.`Mbmmd' `Moo9^Yo..JMML. 17 17 ``` 18 18 19 - A note, task & time management CLI built with Golang & Charm.sh libs. Inspired by TaskWarrior & todo.txt CLI applications. 19 + Noteleaf is a unified personal productivity CLI that combines task management, note-taking, and media tracking in one place. 20 + It provides TaskWarrior-inspired task management with additional support for notes, articles, books, movies, and TV shows - all built with Golang & Charm.sh libs. Inspired by TaskWarrior & todo.txt CLI applications. 21 + 22 + ## Why? 23 + 24 + - **Fragmented productivity tools**: Instead of juggling multiple apps for tasks, notes, reading lists, and media queues, Noteleaf provides a single CLI interface 25 + - **Terminal-native workflow**: For developers and power users who prefer staying in the terminal, Noteleaf offers rich TUIs without leaving your command line 26 + - **Lightweight and fast**: No desktop apps or web interfaces - just a fast, focused CLI tool 27 + - **Unified data model**: Tasks, notes, and media items can reference each other, creating a connected knowledge and productivity system 28 + 29 + ## Getting started 30 + 31 + ### Prerequisites 32 + 33 + Go v1.24+ 34 + 35 + ### Installation 36 + 37 + ```sh 38 + git clone https://github.com/stormlightlabs/noteleaf 39 + cd noteleaf 40 + go build -o ./tmp/noteleaf ./cmd 41 + go install 42 + ``` 43 + 44 + ### Basic usage 45 + 46 + ```sh 47 + # Initialize the application 48 + noteleaf setup 49 + 50 + # Add sample data for exploration 51 + noteleaf setup seed 52 + 53 + # Create your first task 54 + noteleaf task add "Learn Noteleaf CLI" 55 + 56 + # View tasks 57 + noteleaf task list 58 + 59 + # Create a note 60 + noteleaf note add "My first note" 61 + 62 + # Add a book to your reading list 63 + noteleaf media book add "The Name of the Wind" 64 + ``` 65 + 66 + ## Status 67 + 68 + **Status**: Work in Progress (MVP completed) 69 + 70 + ### Completed 20 71 21 - ## Development 72 + Core functionality is complete and stable: 22 73 23 - Requires Go v1.24+ 74 + - Task management with projects and tags 75 + - Note-taking system 76 + - Article parsing from URLs 77 + - Media tracking (books, movies, TV shows) 78 + 79 + ### Planned 80 + 81 + - Time tracking integration 82 + - Advanced search and filtering 83 + - Export/import functionality 84 + - Plugin system
-58
docs/cli.md
··· 1 - # CLI Docs 2 - 3 - ## CommandGroup Interface Pattern 4 - 5 - This section outlines the CommandGroup interface pattern for implementing CLI commands in the noteleaf application. 6 - 7 - ### Core Concepts 8 - 9 - Each major command group implements the CommandGroup interface with a `Create() *cobra.Command` method. Command groups receive handlers as constructor dependencies, enabling dependency injection for testing. Handler initialization occurs centrally in main.go with `log.Fatalf` error handling to fail fast during application startup. 10 - 11 - ### CommandGroup Interface 12 - 13 - interface `CommandGroup` provides a consistent contract for all command groups. Each implementation encapsulates related commands and the shared handler dependency. The Create method returns a fully configured cobra command tree. 14 - 15 - #### Implementations 16 - 17 - TaskCommands handles todo and task-related operations using TaskHandler. MovieCommand manages movie queue operations via MovieHandler. 18 - TVCommand handles TV show queue operations through TVHandler. NoteCommand manages note operations using NoteHandler. 19 - 20 - ### Handler Lifecycle 21 - 22 - Handlers are created once in `main.go` during application startup. Initialization errors prevent application launch rather than causing runtime failures. 23 - Handlers persist for the application lifetime without requiring cleanup. Commands access handlers through struct fields rather than creating new instances. 24 - 25 - ### Testing 26 - 27 - `CommandGroup` structs accept handlers as constructor parameters, enabling easy dependency injection of mock handlers for testing. 28 - Command logic can be tested independently of handler implementations. The interface allows mocking entire command groups for integration testing. 29 - 30 - ### Registry 31 - 32 - `main.go` uses a registry pattern to organize command groups by category. Core commands include task, note, and media functionality. 33 - Management commands handle configuration, setup, and maintenance operations. The pattern provides clean separation and easy extension for new command groups. 34 - 35 - ## UI and Styling System 36 - 37 - The application uses a structured color palette system located in `internal/ui/colors.go` for consistent terminal output styling. 38 - 39 - ### Color Architecture 40 - 41 - The color system implements a `Key` type with 74 predefined colors from the Charm ecosystem, including warm tones (Cumin, Tang, Paprika), cool tones (Sapphire, Oceania, Zinc), and neutral grays (Pepper through Butter). Each color provides hex values via the `Hex()` method and implements Go's `color.Color` interface through `RGBA()`. 42 - 43 - ### Predefined Styles 44 - 45 - Three core lipgloss styles handle common UI elements: 46 - 47 - - `TitleColorStyle` uses color 212 with bold formatting for command titles 48 - - `SelectedColorStyle` provides white-on-212 highlighting for selected items 49 - - `HeaderColorStyle` applies color 240 with bold formatting for section headers 50 - 51 - ### Color Categories 52 - 53 - Colors are organized into primary, secondary, and tertiary categories are accessed through `IsPrimary()`, `IsSecondary()`, and `IsTertiary()` methods on the `Key` type. 54 - 55 - ### Lipgloss Integration 56 - 57 - The styling system integrates with the Charmbracelet lipgloss library for terminal UI rendering. 58 - Colors from the `Key` type convert to lipgloss color values through their `Hex()` method. The predefined `TitleColorStyle`, `SelectedColorStyle`, and `HeaderColorStyle` variables provide lipgloss styles that can be applied to strings with `.Render()`.
+87
docs/dev/ARCHITECTURE.md
··· 1 + # System Architecture 2 + 3 + Noteleaf is a CLI/TUI application for task and content management built on Go with SQLite persistence and terminal-based interfaces. 4 + 5 + ## Core Architecture 6 + 7 + ### Application Structure 8 + 9 + The application follows a layered architecture with clear separation between presentation, business logic, and data access layers. 10 + 11 + **Entry Point** - `cmd/main.go` initializes the application with dependency injection, creates handlers, and configures the Cobra command tree using the CommandGroup pattern. 12 + 13 + **CLI Framework** - Built on `spf13/cobra` with `charmbracelet/fang` providing enhanced CLI features including color schemes, versioning, and improved help formatting. 14 + 15 + **TUI Components** - Interactive interfaces use `charmbracelet/bubbletea` for state management and `charmbracelet/lipgloss` for styling with a consistent color palette system in `internal/ui/colors.go`. 16 + 17 + ### Data Layer 18 + 19 + **Database** - SQLite with schema migrations in `internal/store/sql/migrations/`. The `internal/store` package manages database connections and configuration. 20 + 21 + **Repository Pattern** - Data access abstracts through repository interfaces in `internal/repo/` with validation logic ensuring data integrity at the persistence boundary. 22 + 23 + **Models** - Entity definitions in `internal/models/` implement standardized Model interfaces with common fields (ID, Created, Modified). 24 + 25 + ### Business Logic 26 + 27 + **Handlers** - Business logic resides in `internal/handlers/` with one handler per domain (TaskHandler, NoteHandler, ArticleHandler, etc.). Handlers receive repository dependencies through constructor injection. 28 + 29 + **Services** - Domain-specific operations in `internal/services/` handle complex business workflows and external integrations. 30 + 31 + **Validation** - Schema-based validation at repository level with custom ValidationError types providing detailed field-level error messages. 32 + 33 + ## Domain Features 34 + 35 + ### Content Management 36 + 37 + **Articles** - Web scraping using `gocolly/colly` with domain-specific extraction rules stored in `internal/articles/rules/`. Articles are parsed to markdown and stored with dual file references (markdown + HTML). 38 + 39 + **Tasks** - Todo/task management inspired by TaskWarrior with filtering, status tracking, and interactive TUI views. 40 + 41 + **Notes** - Simple note management with markdown support and glamour-based terminal rendering. 42 + 43 + **Media Queues** - Separate queues for books, movies, and TV shows with status tracking and metadata management. 44 + 45 + ### User Interface 46 + 47 + **Command Groups** - Commands organized into core functionality (task, note, article, media) and management operations (setup, config, status) using the CommandGroup interface pattern. 48 + 49 + **Interactive Views** - Bubbletea-based TUI components for list navigation, item selection, and data entry with consistent styling through the lipgloss color system. 50 + 51 + **Terminal Output** - Markdown rendering through `charmbracelet/glamour` for rich text display in terminal environments. 52 + 53 + ## Dependencies 54 + 55 + **CLI/TUI** - Cobra command framework, Bubbletea state management, Lipgloss styling, Fang CLI enhancements. 56 + 57 + **Data** - SQLite driver (`mattn/go-sqlite3`), TOML configuration parsing. 58 + 59 + **Content Processing** - Colly web scraping, HTML/XML query libraries, Glamour markdown rendering, text processing utilities. 60 + 61 + **Utilities** - UUID generation, time handling, logging through `charmbracelet/log`. 62 + 63 + ## Design Decisions and Tradeoffs 64 + 65 + ### Technology Choices 66 + 67 + **Go over Rust** - Go was selected for its simplicity, excellent CLI ecosystem (Cobra, Charm libraries), and faster development velocity. While Rust + Ratatui would provide better memory safety and potentially superior performance, Go's straightforward concurrency model and mature tooling ecosystem made it the pragmatic choice for rapid prototyping and iteration. 68 + 69 + **SQLite over PostgreSQL** - SQLite provides zero-configuration deployment and sufficient performance for single-user CLI applications. The embedded database eliminates setup complexity while supporting full SQL features needed for filtering and querying. PostgreSQL would add deployment overhead without meaningful benefits for this use case. 70 + 71 + **Repository Pattern over Active Record** - Repository interfaces enable clean separation between business logic and data access, facilitating testing through dependency injection. This pattern scales better than Active Record for complex domain logic while maintaining clear boundaries between layers. 72 + 73 + ### Architectural Tradeoffs 74 + 75 + **CommandGroup Interface** - Centralizes command registration while enabling modular command organization. The pattern requires additional abstraction but provides consistent dependency injection and testing capabilities across all command groups. 76 + 77 + **Handler-based Business Logic** - Business logic in handlers rather than rich domain models keeps the codebase simple and avoids over-engineering. While this approach may not scale to complex business rules, it provides clear separation of concerns for the current feature set. 78 + 79 + **Dual Storage for Articles** - Articles store both markdown and HTML versions to balance processing speed with format flexibility. This doubles storage requirements but eliminates runtime conversion overhead and preserves original formatting. 80 + 81 + ### Component Interactions 82 + 83 + **Handler โ†’ Repository โ†’ Database** - Request flow follows a linear path from CLI commands through business logic to data persistence. This pattern ensures consistent validation and error handling while maintaining clear separation of concerns. 84 + 85 + **TUI State Management** - Bubbletea's unidirectional data flow provides predictable state updates for interactive components. The model-view-update pattern ensures consistent UI behavior across different terminal environments. 86 + 87 + **Configuration and Migration** - Application startup validates configuration and runs database migrations before initializing handlers. This fail-fast approach prevents runtime errors and ensures consistent database schema across deployments.
+263
docs/dev/TESTING.md
··· 1 + # Testing Documentation 2 + 3 + This document outlines the testing patterns and practices used in the `noteleaf` application. 4 + 5 + ## Overview 6 + 7 + The codebase follows Go's standard testing practices with specialized testing utilities for complex scenarios. Tests use the standard library along with carefully selected dependencies like faker for data generation and BubbleTea for TUI testing. This approach keeps dependencies minimal while providing robust testing infrastructure for interactive components and complex integrations. 8 + 9 + ### Organization 10 + 11 + Each package contains its own test files alongside the source code. Test files are organized by functionality and mirror the structure of the source code they test. The codebase includes four main test utility files that provide specialized testing infrastructure: 12 + 13 + - `internal/services/test_utilities.go` - HTTP mocking and media service testing 14 + - `internal/repo/test_utilities.go` - Database testing and data generation 15 + - `internal/ui/test_utilities.go` - TUI testing framework and interactive component testing 16 + - `internal/handlers/test_utilities.go` - Handler testing with database isolation and input simulation 17 + 18 + ## Patterns 19 + 20 + ### Handler Creation 21 + 22 + Tests create real handler instances using temporary databases to ensure test isolation. Factory functions handle both database setup and handler initialization, returning both the handler and a cleanup function. 23 + 24 + ### Database Isolation 25 + 26 + Tests use temporary directories and environment variable manipulation to create isolated database instances. Each test gets its own temporary SQLite database that is automatically cleaned up after the test completes. 27 + 28 + The `setupCommandTest` function creates a temporary directory, sets `XDG_CONFIG_HOME` to point to it, and initializes the database schema. This ensures tests don't interfere with each other or with development data. 29 + 30 + ### Resource Management 31 + 32 + Tests properly manage resources using cleanup functions returned by factory methods. The cleanup function handles both handler closure and temporary directory removal. This pattern ensures complete resource cleanup even if tests fail. 33 + 34 + ### Error Handling 35 + 36 + Tests use `t.Fatal` for setup errors that prevent test execution and `t.Error` for test assertion failures. Fatal errors stop test execution while errors allow tests to continue checking other conditions. 37 + 38 + ### Context Cancellation 39 + 40 + Error case testing frequently uses context cancellation to simulate database and network failures. The pattern creates a context, immediately cancels it, then calls the function under test to verify error handling. This provides a reliable way to test error paths without requiring complex mock setups or external failure injection. 41 + 42 + ### Command Structure 43 + 44 + Command group tests verify cobra command structure including use strings, aliases, short descriptions, and subcommand presence. Tests check that commands are properly configured without executing their logic. 45 + 46 + ### Interface Compliance 47 + 48 + Tests verify interface compliance using compile-time checks with blank identifier assignments. This ensures structs implement expected interfaces without runtime overhead. 49 + 50 + ## Test Infrastructure 51 + 52 + ### Test Utility Frameworks 53 + 54 + The codebase provides comprehensive testing utilities organized by layer and functionality. Each test utility file contains specialized helpers, mocks, and test infrastructure for its respective domain. 55 + 56 + #### Database Testing Utilities 57 + 58 + `internal/repo/test_utilities.go` provides comprehensive database testing infrastructure: 59 + 60 + - **In-Memory Database Creation**: `CreateTestDB` creates isolated SQLite databases with full schema 61 + - **Sample Data Factories**: Functions like `CreateSampleTask`, `CreateSampleBook` generate realistic test data 62 + - **Faker Integration**: Uses jaswdr/faker for generating realistic fake data with `CreateFakeArticle` 63 + - **Test Setup Helpers**: `SetupTestData` creates a full set of sample data across all models 64 + - **Custom Assertions**: Generic assertion helpers like `AssertEqual`, `AssertContains`, `AssertNoError` 65 + 66 + #### HTTP Service Testing 67 + 68 + `internal/services/test_utilities.go` provides HTTP mocking and media service testing: 69 + 70 + - **Mock Configuration**: `MockConfig` structure for configuring service behavior 71 + - **Function Replacement**: `SetupMediaMocks` replaces service functions with controllable mocks 72 + - **Sample Data Access**: Helper functions that use embedded HTML samples for realistic testing 73 + - **Specialized Scenarios**: Pre-configured mock setups for success and failure scenarios 74 + - **Assertion Helpers**: Domain-specific assertions for movies, TV shows, and error conditions 75 + 76 + #### TUI Testing Framework 77 + 78 + `internal/ui/test_utilities.go` provides a comprehensive BubbleTea testing framework: 79 + 80 + - **TUITestSuite**: Complete testing infrastructure for interactive TUI components 81 + - **Controlled I/O**: `ControlledOutput` and `ControlledInput` for deterministic testing 82 + - **Message Simulation**: Key press simulation, message queuing, and timing control 83 + - **State Verification**: Model state checking and view content assertions 84 + - **Timeout Handling**: Configurable timeouts for async operations 85 + - **Mock Repository**: Test doubles for repository interfaces 86 + 87 + #### Handler Testing Infrastructure 88 + 89 + `internal/handlers/test_utilities.go` provides end-to-end handler testing: 90 + 91 + - **Environment Isolation**: `HandlerTestHelper` creates isolated test environments 92 + - **Input Simulation**: `InputSimulator` for testing interactive components that use `fmt.Scanf` 93 + - **HTTP Mocking**: Comprehensive HTTP server mocking for external API testing 94 + - **Database Helpers**: Database corruption and error scenario testing 95 + - **Editor Mocking**: `MockEditor` for testing file editing workflows 96 + - **Assertion Helpers**: Handler-specific assertions and verification functions 97 + 98 + ### Advanced Testing Patterns 99 + 100 + #### Input Simulation for Interactive Components 101 + 102 + Interactive handlers that use `fmt.Scanf` require special testing infrastructure with an `io.Reader` implementation. 103 + 104 + The `InputSimulator` provides controlled input sequences that prevent tests from hanging while maintaining coverage of interactive code paths. 105 + 106 + #### TUI Testing with BubbleTea Framework 107 + 108 + The TUI testing framework addresses the fundamental challenge of testing interactive terminal applications in a deterministic, concurrent environment. BubbleTea's message-passing architecture creates unique testing requirements that standard Go testing patterns cannot adequately address. 109 + 110 + The framework implements a controlled execution environment that replaces BubbleTea's typical program loop with a deterministic testing harness. Rather than running an actual terminal program, the "testing suite" directly manages model state transitions by simulating the Update/View cycle. This approach eliminates the non-deterministic behavior inherent in real terminal interactions while preserving the exact message flow patterns that production code experiences. 111 + 112 + State verification relies on function composition patterns where test conditions are expressed as closures that capture specific model states. The `WaitFor` mechanism uses polling with configurable timeouts, addressing the async nature of BubbleTea model updates without creating race conditions. This pattern bridges imperative test assertions with BubbleTea's declarative update model. 113 + This is inspired by front-end/TS/JS testing patterns. 114 + 115 + The framework's I/O abstraction layer replaces terminal input/output with controlled buffers that implement standard Go interfaces. 116 + This design maintains interface compatibility while providing complete control over timing and content. The controlled I/O system captures all output for later verification and injects precise input sequences, enabling complex interaction testing without external dependencies. 117 + 118 + Concurrency management uses channels and context propagation to coordinate between the testing framework and the model under test. 119 + The suite manages goroutine lifecycle and ensures proper cleanup, preventing test interference and resource leaks. This architecture supports testing of models that perform background operations or handle async events. 120 + 121 + #### HTTP Service Mocking 122 + 123 + Service testing uses HTTP mocking with request capture. A `MockServer` is instantiated, and its URL is used in test scoped services. 124 + 125 + #### Database Schema Testing 126 + 127 + Database tests use comprehensive schema setup with (automatic) cleanup 128 + 129 + #### Environment Manipulation 130 + 131 + Environment testing utilities provide controlled environment manipulation. Environment variables are restored after instantiation. 132 + 133 + ## Test Organization Patterns 134 + 135 + ### Single Root Test 136 + 137 + The preferred test organization pattern uses a single root test function with nested subtests using `t.Run`. This provides clear hierarchical organization and allows running specific test sections while maintaining shared setup and context. This pattern offers several advantages: clear test hierarchy with logical grouping, ability to run specific test sections, consistent test structure across the codebase, and shared setup that can be inherited by subtests. 138 + 139 + ### Integration vs Unit Testing 140 + 141 + The codebase emphasizes integration testing over heavy mocking by using real handlers and services to verify actual behavior rather than mocked interactions. The goal is to catch integration issues while maintaining test reliability. 142 + 143 + ### Static Output 144 + 145 + UI components support static output modes for testing. Tests capture output using bytes.Buffer and verify content using string contains checks rather than exact string matching for better test maintainability. 146 + 147 + ### Standard Output Redirection 148 + 149 + For testing functions that write to stdout, tests use a pipe redirection pattern with goroutines to capture output. The pattern saves the original stdout, redirects to a pipe, captures output in a separate goroutine, and restores stdout after the test. This ensures clean output capture without interfering with the testing framework. 150 + 151 + ## Utilities 152 + 153 + ### Test Data Generation 154 + 155 + The codebase uses sophisticated data generation strategies: 156 + 157 + - **Factory Functions**: Each package provides factory functions for creating valid test data 158 + - **Faker Integration**: Uses `jaswdr/faker` for generating realistic fake data with proper randomization 159 + - **Sample Data Creators**: Functions like `CreateSampleTask`, `CreateSampleBook` provide consistent test data 160 + - **Embedded Resources**: Services use embedded HTML samples from real API responses for realistic testing 161 + 162 + ### Assertion Helpers 163 + 164 + Custom assertion functions provide clear error messages and reduce test code duplication: 165 + 166 + - **Generic Assertions**: `AssertEqual`, `AssertNoError`, `AssertContains` for common checks 167 + - **Domain-Specific Assertions**: `AssertMovieInResults`, `AssertNoteExists` for specialized verification 168 + - **TUI Assertions**: `AssertViewContains`, `AssertModelState` for BubbleTea model testing 169 + - **HTTP Assertions**: `AssertRequestMade` for verifying HTTP interactions 170 + 171 + ### Mock Infrastructure 172 + 173 + Each layer provides specialized mocking capabilities: 174 + 175 + - **Service Mocking**: Function replacement with configurable behavior and embedded test data 176 + - **HTTP Mocking**: `HTTPMockServer` with request capture and response customization 177 + - **Input Mocking**: `InputSimulator` for deterministic interactive component testing 178 + - **Editor Mocking**: `MockEditor` for file editing workflow testing 179 + - **Repository Mocking**: `MockTaskRepository` for TUI component testing 180 + 181 + ### Environment and Resource Management 182 + 183 + Testing utilities provide comprehensive resource management: 184 + 185 + - **Environment Isolation**: `EnvironmentTestHelper` for controlled environment variable manipulation 186 + - **Database Isolation**: Temporary SQLite databases with automatic cleanup 187 + - **File System Isolation**: Temporary directories with automatic cleanup 188 + - **Process Isolation**: Handler helpers that create completely isolated test environments 189 + 190 + ## Testing CLI Commands 191 + 192 + Command group tests focus on structure verification rather than execution testing. Tests check command configuration, subcommand presence, and interface compliance. This approach ensures command trees are properly constructed without requiring complex execution mocking. 193 + 194 + ### CommandGroup Interface Testing 195 + 196 + The CommandGroup interface enables testable CLI architecture. Tests verify that command groups implement the interface correctly and return properly configured cobra commands. This pattern separates command structure from command execution. 197 + 198 + Interface compliance is tested using compile-time checks within the "Interface Implementations" subtest, ensuring all command structs properly implement the CommandGroup interface without runtime overhead. 199 + 200 + ## Performance Considerations 201 + 202 + Tests avoid expensive operations in setup functions. Handler creation uses real instances but tests focus on structure verification rather than full execution paths. This keeps test suites fast while maintaining coverage of critical functionality. 203 + 204 + The single root test pattern allows for efficient resource management where setup costs can be amortized across multiple related test cases. 205 + 206 + ## Interactive Component Testing 207 + 208 + The codebase provides comprehensive testing infrastructure for interactive components, including both terminal UI applications and command-line interfaces that require user input. 209 + 210 + ### Input Simulation Framework 211 + 212 + Interactive handlers that use `fmt.Scanf` require specialized testing infrastructure: 213 + 214 + - **InputSimulator**: Provides controlled input sequences that implement `io.Reader` 215 + - **Menu Selection Helpers**: `MenuSelection`, `MenuCancel`, `MenuSequence` for common interaction patterns 216 + - **Handler Integration**: Handlers can accept `io.Reader` for input, enabling deterministic testing 217 + - **Cleanup Management**: Automatic cleanup prevents resource leaks in test environments 218 + 219 + ### TUI Testing with BubbleTea 220 + 221 + The TUI testing framework provides complete testing infrastructure for interactive terminal interfaces: 222 + 223 + - **TUITestSuite**: Comprehensive testing framework for BubbleTea models 224 + - **Message Simulation**: Key press simulation, window resize events, and custom message handling 225 + - **State Verification**: Model state checking with custom condition functions 226 + - **View Assertions**: Content verification and output capture 227 + - **Timing Control**: Configurable timeouts and delay handling for async operations 228 + - **Mock Integration**: Repository mocking for isolated component testing 229 + 230 + ### Interactive Test Scenarios 231 + 232 + Interactive handlers should test comprehensive scenarios: 233 + 234 + - **Valid user selections** - User chooses valid menu options and inputs 235 + - **Cancellation flows** - User chooses to cancel operations (option 0 or escape keys) 236 + - **Invalid choices** - User selects out-of-range options or provides invalid input 237 + - **Navigation patterns** - Keyboard navigation, scrolling, and multi-step interactions 238 + - **Error handling** - Network errors, service failures, and data validation errors 239 + - **Empty states** - Search returns no results, empty lists, and missing data 240 + - **Edge cases** - Boundary conditions, malformed input, and resource constraints 241 + 242 + ### TUI Component Testing Patterns 243 + 244 + BubbleTea components use specialized testing patterns: 245 + 246 + - **Key Sequence Testing**: Simulate complex user interactions with timing 247 + - **State Transition Testing**: Verify model state changes through user actions 248 + - **View Content Testing**: Assert specific content appears in rendered output 249 + - **Async Operation Testing**: Handle loading states and network operations 250 + - **Responsive Design Testing**: Test different terminal sizes and window resize handling 251 + 252 + This comprehensive testing approach ensures interactive components work reliably in automated environments while maintaining full coverage of user interaction paths. 253 + 254 + ## Errors 255 + 256 + Error coverage follows a systematic approach to identify and test failure scenarios: 257 + 258 + 1. **Context Cancellation** - Primary method for testing database and network timeout scenarios 259 + 2. **Invalid Input** - Malformed data, empty inputs, boundary conditions 260 + 3. **Resource Exhaustion** - Database connection failures, memory limits 261 + 4. **Constraint Violations** - Duplicate keys, foreign key failures 262 + 5. **State Validation** - Testing functions with invalid system states 263 + 6. **Interactive Input** - Invalid user choices, cancellation handling, input simulation errors
-114
docs/testing.md
··· 1 - # Testing Documentation 2 - 3 - This document outlines the testing patterns and practices used in the `noteleaf` application. 4 - 5 - ## Overview 6 - 7 - The codebase follows Go's standard testing practices without external libraries. Tests use only the standard library package and avoid mock frameworks or assertion libraries. This is to keep dependencies minimal and tests readable using standard Go patterns. 8 - 9 - ### Organization 10 - 11 - Each package contains its own test files alongside the source code. Test files are organized by functionality and mirror the structure of the source code they test. 12 - 13 - ## Patterns 14 - 15 - ### Handler Creation Pattern 16 - 17 - Tests create real handler instances using temporary databases to ensure test isolation. Factory functions handle both database setup and handler initialization, returning both the handler and a cleanup function. 18 - 19 - ### Database Isolation 20 - 21 - Tests use temporary directories and environment variable manipulation to create isolated database instances. Each test gets its own temporary SQLite database that is automatically cleaned up after the test completes. 22 - 23 - The `setupCommandTest` function creates a temporary directory, sets `XDG_CONFIG_HOME` to point to it, and initializes the database schema. This ensures tests don't interfere with each other or with development data. 24 - 25 - ### Resource Management 26 - 27 - Tests properly manage resources using cleanup functions returned by factory methods. The cleanup function handles both handler closure and temporary directory removal. This pattern ensures complete resource cleanup even if tests fail. 28 - 29 - ### Error Handling 30 - 31 - Tests use `t.Fatal` for setup errors that prevent test execution and `t.Error` for test assertion failures. Fatal errors stop test execution while errors allow tests to continue checking other conditions. 32 - 33 - ### Context Cancellation Testing Pattern 34 - 35 - Error case testing frequently uses context cancellation to simulate database and network failures. The pattern creates a context, immediately cancels it, then calls the function under test to verify error handling. This provides a reliable way to test error paths without requiring complex mock setups or external failure injection. 36 - 37 - ### Command Structure Testing 38 - 39 - Command group tests verify cobra command structure including use strings, aliases, short descriptions, and subcommand presence. Tests check that commands are properly configured without executing their logic. 40 - 41 - ### Interface Compliance Testing 42 - 43 - Tests verify interface compliance using compile-time checks with blank identifier assignments. This ensures structs implement expected interfaces without runtime overhead. 44 - 45 - ## Test Organization Patterns 46 - 47 - ### Single Root Test 48 - 49 - The preferred test organization pattern uses a single root test function with nested subtests using `t.Run`. This provides clear hierarchical organization and allows running specific test sections while maintaining shared setup and context. This pattern offers several advantages: clear test hierarchy with logical grouping, ability to run specific test sections, consistent test structure across the codebase, and shared setup that can be inherited by subtests. 50 - 51 - ### Integration vs Unit Testing 52 - 53 - The codebase emphasizes integration testing over heavy mocking by using real handlers and services to verify actual behavior rather than mocked interactions. The goal is to catch integration issues while maintaining test reliability. 54 - 55 - ### Static Output 56 - 57 - UI components support static output modes for testing. Tests capture output using bytes.Buffer and verify content using string contains checks rather than exact string matching for better test maintainability. 58 - 59 - ### Standard Output Redirection 60 - 61 - For testing functions that write to stdout, tests use a pipe redirection pattern with goroutines to capture output. The pattern saves the original stdout, redirects to a pipe, captures output in a separate goroutine, and restores stdout after the test. This ensures clean output capture without interfering with the testing framework. 62 - 63 - ## Utilities 64 - 65 - ### Helpers 66 - 67 - Test files include helper functions for creating test data and finding elements in collections. These utilities reduce code duplication and improve test readability. 68 - 69 - ### Mock Data 70 - 71 - Tests create realistic mock data using factory functions (powered by faker) that return properly initialized structs with sensible defaults. 72 - 73 - ## Testing CLI Commands 74 - 75 - Command group tests focus on structure verification rather than execution testing. Tests check command configuration, subcommand presence, and interface compliance. This approach ensures command trees are properly constructed without requiring complex execution mocking. 76 - 77 - ### CommandGroup Interface Testing 78 - 79 - The CommandGroup interface enables testable CLI architecture. Tests verify that command groups implement the interface correctly and return properly configured cobra commands. This pattern separates command structure from command execution. 80 - 81 - Interface compliance is tested using compile-time checks within the "Interface Implementations" subtest, ensuring all command structs properly implement the CommandGroup interface without runtime overhead. 82 - 83 - ## Performance Considerations 84 - 85 - Tests avoid expensive operations in setup functions. Handler creation uses real instances but tests focus on structure verification rather than full execution paths. This keeps test suites fast while maintaining coverage of critical functionality. 86 - 87 - The single root test pattern allows for efficient resource management where setup costs can be amortized across multiple related test cases. 88 - 89 - ## Interactive Component Testing 90 - 91 - Interactive components that use `fmt.Scanf` for user input require special testing infrastructure to prevent tests from hanging while waiting for stdin. 92 - 93 - ### Testing Success Scenarios 94 - 95 - Interactive handlers should test both success and error paths: 96 - 97 - - **Valid user selections** - User chooses valid menu options 98 - - **Cancellation** - User chooses to cancel (option 0) 99 - - **Invalid choices** - User selects out-of-range options 100 - - **Empty results** - Search returns no results 101 - - **Network errors** - Service calls fail 102 - 103 - This ensures tests run reliably in automated environments while maintaining coverage of the non-interactive code paths. 104 - 105 - ## Errors 106 - 107 - Error coverage follows a systematic approach to identify and test failure scenarios: 108 - 109 - 1. **Context Cancellation** - Primary method for testing database and network timeout scenarios 110 - 2. **Invalid Input** - Malformed data, empty inputs, boundary conditions 111 - 3. **Resource Exhaustion** - Database connection failures, memory limits 112 - 4. **Constraint Violations** - Duplicate keys, foreign key failures 113 - 5. **State Validation** - Testing functions with invalid system states 114 - 6. **Interactive Input** - Invalid user choices, cancellation handling, input simulation errors