--- name: gpui-test description: Generate comprehensive tests for GPUI components, views, state management, and user interactions --- # GPUI Test Generation Generate comprehensive tests for GPUI components including unit tests, integration tests, state management tests, and user interaction tests. ## Arguments - `$1`: Component path (required) - Path to the component file to generate tests for ## Workflow ### 1. Analyze Component Structure - Read the component file - Identify component type (View, Model, Element) - Extract component struct and fields - Identify render method and UI structure - Find state management patterns - Locate event handlers and actions - Identify dependencies and injected services ### 2. Generate Unit Tests Create unit tests for component logic: #### Component Initialization Tests ```rust #[cfg(test)] mod tests { use super::*; use gpui::*; #[gpui::test] fn test_component_initialization() { App::test(|cx| { let state = cx.new_model(|_| AppState::default()); let view = cx.new_view(|cx| MyComponent::new(state.clone(), cx)); assert!(view.is_some()); }); } #[gpui::test] fn test_initial_state() { App::test(|cx| { let state = cx.new_model(|_| AppState { count: 0, items: vec![], }); let view = cx.new_view(|cx| MyComponent::new(state.clone(), cx)); view.update(cx, |view, cx| { let state = view.state.read(cx); assert_eq!(state.count, 0); assert_eq!(state.items.len(), 0); }); }); } } ``` #### State Management Tests ```rust #[gpui::test] fn test_state_updates() { App::test(|cx| { let state = cx.new_model(|_| AppState { count: 0 }); let view = cx.new_view(|cx| Counter::new(state.clone(), cx)); // Update state state.update(cx, |state, cx| { state.count = 5; cx.notify(); }); // Verify view reflects change view.update(cx, |view, cx| { let state = view.state.read(cx); assert_eq!(state.count, 5); }); }); } #[gpui::test] fn test_subscription_updates() { App::test(|cx| { let state = cx.new_model(|_| AppState { count: 0 }); let view = cx.new_view(|cx| Counter::new(state.clone(), cx)); let initial_render_count = view.render_count(); // Update should trigger rerender via subscription state.update(cx, |state, cx| { state.count += 1; cx.notify(); }); assert_eq!(view.render_count(), initial_render_count + 1); }); } ``` ### 3. Create Integration Tests Generate integration tests for component interactions: #### User Interaction Tests ```rust #[gpui::test] fn test_button_click() { App::test(|cx| { let state = cx.new_model(|_| AppState { count: 0 }); let view = cx.new_view(|cx| Counter::new(state.clone(), cx)); // Simulate button click view.update(cx, |view, cx| { view.handle_increment(cx); }); // Verify state updated state.update(cx, |state, _| { assert_eq!(state.count, 1); }); }); } #[gpui::test] fn test_input_change() { App::test(|cx| { let state = cx.new_model(|_| FormState::default()); let view = cx.new_view(|cx| Form::new(state.clone(), cx)); // Simulate input change view.update(cx, |view, cx| { view.handle_input_change("test value", cx); }); // Verify state updated state.update(cx, |state, _| { assert_eq!(state.input_value, "test value"); }); }); } ``` #### Action Handling Tests ```rust #[gpui::test] fn test_action_dispatch() { App::test(|cx| { let state = cx.new_model(|_| AppState { count: 0 }); let view = cx.new_view(|cx| Counter::new(state.clone(), cx)); // Dispatch action view.update(cx, |view, cx| { cx.dispatch_action(Increment); }); // Verify action handled state.update(cx, |state, _| { assert_eq!(state.count, 1); }); }); } ``` ### 4. Add Interaction Tests Test complex user interactions: #### Multi-Step Interactions ```rust #[gpui::test] fn test_complete_user_flow() { App::test(|cx| { let state = cx.new_model(|_| TodoState::default()); let view = cx.new_view(|cx| TodoList::new(state.clone(), cx)); view.update(cx, |view, cx| { // Add item view.handle_add_todo("Buy milk", cx); // Mark complete view.handle_toggle_todo(0, cx); // Delete item view.handle_delete_todo(0, cx); }); state.update(cx, |state, _| { assert_eq!(state.todos.len(), 0); }); }); } ``` #### Edge Cases ```rust #[gpui::test] fn test_empty_state() { App::test(|cx| { let state = cx.new_model(|_| AppState::default()); let view = cx.new_view(|cx| MyComponent::new(state.clone(), cx)); // Verify graceful handling of empty state view.update(cx, |view, cx| { let element = view.render(cx); // Assert renders without panic }); }); } #[gpui::test] fn test_boundary_conditions() { App::test(|cx| { let state = cx.new_model(|_| CounterState { count: i32::MAX }); let view = cx.new_view(|cx| Counter::new(state.clone(), cx)); // Test overflow handling view.update(cx, |view, cx| { view.handle_increment(cx); }); state.update(cx, |state, _| { // Should handle overflow gracefully assert!(state.count == i32::MAX || state.count == 0); }); }); } ``` ### 5. Generate Test Utilities Create helper functions for testing: ```rust // Test helpers mod test_utils { use super::*; use gpui::*; pub fn create_test_state() -> AppState { AppState { count: 0, items: vec!["item1".to_string(), "item2".to_string()], is_loading: false, } } pub fn create_test_view(cx: &mut WindowContext) -> View { let state = cx.new_model(|_| create_test_state()); cx.new_view(|cx| MyComponent::new(state, cx)) } pub fn assert_state_equals(state: &Model, expected_count: i32, cx: &mut AppContext) { state.update(cx, |state, _| { assert_eq!(state.count, expected_count); }); } } ``` ### 6. Provide Coverage Report Generate overview of test coverage: ```rust // Coverage targets: // - Component initialization: ✓ // - State updates: ✓ // - User interactions: ✓ // - Action handling: ✓ // - Edge cases: ✓ // - Error handling: ⚠ (needs work) // - Async operations: ⚠ (needs work) ``` ### 7. Add Async Tests For components with async operations: ```rust #[gpui::test] async fn test_async_data_loading() { App::test(|cx| async move { let state = cx.new_model(|_| DataState::default()); let view = cx.new_view(|cx| DataView::new(state.clone(), cx)); // Trigger async load view.update(cx, |view, cx| { view.load_data(cx); }); // Wait for completion cx.run_until_parked(); // Verify data loaded state.update(cx, |state, _| { assert!(state.is_loaded); assert!(!state.data.is_empty()); }); }); } #[gpui::test] async fn test_async_error_handling() { App::test(|cx| async move { let state = cx.new_model(|_| DataState::default()); let view = cx.new_view(|cx| DataView::new(state.clone(), cx)); // Trigger async operation that will fail view.update(cx, |view, cx| { view.load_data_with_error(cx); }); cx.run_until_parked(); // Verify error handled state.update(cx, |state, _| { assert!(state.error.is_some()); assert!(!state.is_loaded); }); }); } ``` ### 8. Generate Property-Based Tests For complex logic, generate property-based tests: ```rust #[cfg(test)] mod property_tests { use super::*; use proptest::prelude::*; proptest! { #[test] fn test_counter_never_negative(increments in 0..100u32, decrements in 0..100u32) { App::test(|cx| { let state = cx.new_model(|_| CounterState { count: 0 }); state.update(cx, |state, _| { for _ in 0..increments { state.count += 1; } for _ in 0..decrements { state.count = state.count.saturating_sub(1); } }); state.update(cx, |state, _| { prop_assert!(state.count >= 0); Ok(()) }).unwrap(); }); } } } ``` ### 9. Add Benchmark Tests Create performance benchmarks: ```rust // benches/component_bench.rs use criterion::{black_box, criterion_group, criterion_main, Criterion}; fn render_benchmark(c: &mut Criterion) { c.bench_function("component render", |b| { App::test(|cx| { let state = cx.new_model(|_| create_large_state()); let view = cx.new_view(|cx| MyComponent::new(state, cx)); b.iter(|| { view.update(cx, |view, cx| { black_box(view.render(cx)); }); }); }); }); } criterion_group!(benches, render_benchmark); criterion_main!(benches); ``` ### 10. Generate Test Documentation Create documentation for tests: ```rust //! Component Tests //! //! This module contains comprehensive tests for MyComponent including: //! //! - Unit tests for component logic and state management //! - Integration tests for user interactions //! - Async tests for data loading //! - Property-based tests for invariants //! - Performance benchmarks //! //! ## Running Tests //! //! ```bash //! # Run all tests //! cargo test //! //! # Run specific test //! cargo test test_state_updates //! //! # Run with output //! cargo test -- --nocapture //! //! # Run benchmarks //! cargo bench //! ``` ``` ## Test Categories ### Unit Tests - Component initialization - State management - Helper functions - Pure logic ### Integration Tests - User interactions - Component composition - Event propagation - Action handling ### UI Tests - Render output - Layout calculations - Style application - Theme integration ### Performance Tests - Render benchmarks - State update performance - Memory usage - Subscription efficiency ## Example Usage ```bash # Generate tests for specific component /gpui-test src/ui/views/counter.rs # Generate tests for all components in directory /gpui-test src/ui/components/ # Generate tests with benchmarks /gpui-test src/ui/views/data_view.rs --with-benchmarks ``` ## Best Practices - Test behavior, not implementation - Use descriptive test names - Test edge cases and error conditions - Keep tests focused and independent - Use test utilities for common setup - Document complex test scenarios - Maintain high coverage (>80%) - Run tests in CI/CD pipeline ## Output Structure ``` tests/ ├── component_name_test.rs │ ├── Unit tests │ ├── Integration tests │ └── Test utilities └── benches/ └── component_name_bench.rs ```