12 KiB
Testing Infrastructure Documentation
This document provides a comprehensive overview of the testing infrastructure for the Rust shadcn/ui project, with a focus on the radio-group component as an example.
Overview
The testing infrastructure is designed to ensure component quality, cross-framework parity, and maintainability across all supported Rust web frameworks. It consists of multiple layers of testing:
- Unit Tests - Framework-specific component tests
- Integration Tests - Cross-framework parity and consistency tests
- Accessibility Tests - ARIA compliance and usability tests
- Theme Tests - Visual consistency across design variants
- Build Tests - Compilation and dependency validation
Architecture
Test Utilities (packages/test-utils)
The test utilities package provides shared testing infrastructure:
use shadcn_ui_test_utils::{
ComponentTester, ComponentComparator, ParityChecker,
Framework, Theme, FrameworkImplementation, ComponentSpec, PropSpec
};
Core Components
ComponentTester- Validates individual component behaviorComponentComparator- Compares implementations across frameworksParityChecker- Ensures API and feature parityThemeValidator- Validates theme consistencyVisualRegression- Visual regression testing (planned)
Framework Support
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Framework {
Leptos,
Yew,
Dioxus, // Planned
}
Theme Variants
#[derive(Debug, Clone, PartialEq)]
pub enum Theme {
Default,
NewYork,
}
Testing Layers
1. Unit Tests
Unit tests are framework-specific and test individual component functionality.
Yew Unit Tests
#[wasm_bindgen_test]
fn test_radio_group_renders() {
let rendered = yew::start_app_with_props::<RadioGroup>(RadioGroupProps {
value: Some("option1".to_string()),
on_value_change: None,
disabled: false,
// ... other props
});
let container = rendered.query_selector("[role='radiogroup']").unwrap();
assert!(container.is_some(), "Radio group should have role='radiogroup'");
}
Leptos Unit Tests
#[wasm_bindgen_test]
fn test_radio_group_renders() {
let (selected_value, _) = create_signal(None::<String>);
let rendered = mount_to_body(|| {
view! {
<RadioGroup value=selected_value>
<RadioGroupItem value="option1".to_string()>
"Option 1"
</RadioGroupItem>
</RadioGroup>
}
});
let container = web_sys::window()
.unwrap()
.document()
.unwrap()
.query_selector("[role='radiogroup']")
.unwrap();
assert!(container.is_some(), "Radio group should have role='radiogroup'");
}
2. Integration Tests
Integration tests ensure cross-framework parity and consistency.
#[test]
fn test_radio_group_cross_framework_parity() {
let mut props = HashMap::new();
props.insert("value".to_string(), PropSpec {
prop_type: "Option<String>".to_string(),
required: false,
default_value: Some("None".to_string()),
});
// ... more props
let radio_group_spec = ComponentSpec {
name: "RadioGroup".to_string(),
props,
events: vec!["on_value_change".to_string()],
variants: vec!["Default".to_string(), "NewYork".to_string()],
sizes: vec![],
};
let yew_impl = FrameworkImplementation {
framework: Framework::Yew,
component_spec: radio_group_spec.clone(),
css_classes: vec![
"grid".to_string(),
"gap-2".to_string(),
// ... more classes
],
dependencies: vec!["yew".to_string(), "yew_style".to_string()],
};
let leptos_impl = FrameworkImplementation {
framework: Framework::Leptos,
component_spec: radio_group_spec,
css_classes: vec![
"grid".to_string(),
"gap-2".to_string(),
// ... more classes
],
dependencies: vec!["leptos".to_string(), "leptos_style".to_string()],
};
let checker = ParityChecker::new()
.add_implementation(yew_impl)
.add_implementation(leptos_impl);
let api_result = checker.check_api_parity();
assert!(api_result.frameworks_match, "RadioGroup API should match across frameworks");
assert_eq!(api_result.score, 1.0, "RadioGroup should have perfect parity score");
}
3. Accessibility Tests
Accessibility tests ensure ARIA compliance and usability.
#[test]
fn test_radio_group_accessibility_features() {
let yew_tester = ComponentTester::new("radio-group", Framework::Yew)
.with_theme(Theme::Default)
.with_property("value", "option1")
.with_property("disabled", "false");
let leptos_tester = ComponentTester::new("radio-group", Framework::Leptos)
.with_theme(Theme::Default)
.with_property("value", "option1")
.with_property("disabled", "false");
// Test accessibility features
let yew_accessibility = yew_tester.test_accessibility();
assert!(yew_accessibility.passed, "Yew RadioGroup should be accessible");
let leptos_accessibility = leptos_tester.test_accessibility();
assert!(leptos_accessibility.passed, "Leptos RadioGroup should be accessible");
}
4. Theme Tests
Theme tests validate visual consistency across design variants.
#[test]
fn test_radio_group_theme_consistency() {
let validator = ThemeValidator::new()
.add_component_classes("radio-group", vec![
"grid".to_string(),
"gap-2".to_string(),
])
.add_component_classes("radio-group-item", vec![
"aspect-square".to_string(),
"h-4".to_string(),
"w-4".to_string(),
"rounded-full".to_string(),
"border".to_string(),
"border-primary".to_string(),
"text-primary".to_string(),
// ... more classes
]);
let default_result = validator.validate_theme_classes("radio-group", Theme::Default);
assert!(default_result.passed, "RadioGroup should have valid default theme classes");
let new_york_result = validator.validate_theme_classes("radio-group", Theme::NewYork);
assert!(new_york_result.passed, "RadioGroup should have valid New York theme classes");
}
Test Categories
Component-Specific Tests
Each component should include tests for:
- Rendering - Component renders correctly
- Props - All props work as expected
- Events - Event handlers function properly
- State - Component state management
- Styling - CSS classes and themes
- Accessibility - ARIA attributes and keyboard navigation
- Variants - Different theme variants
- Edge Cases - Error states, disabled states, etc.
Cross-Framework Tests
Cross-framework tests ensure:
- API Parity - Same props and events across frameworks
- Feature Parity - Same functionality across frameworks
- Theme Parity - Same visual appearance across frameworks
- Dependency Parity - Equivalent dependencies across frameworks
Integration Tests
Integration tests validate:
- Registry Integration - Components are properly registered
- Build Integration - Components compile correctly
- Documentation Integration - Documentation is generated correctly
- Example Integration - Examples work correctly
Running Tests
Individual Component Tests
# Test Yew radio-group
cargo test -p shadcn-ui-yew-radio-group
# Test Leptos radio-group
cargo test -p shadcn-ui-leptos-radio-group
Integration Tests
# Run all integration tests
cargo test --test radio_group_integration_test
# Run specific integration test
cargo test test_radio_group_cross_framework_parity
Complete Test Suite
# Run the comprehensive test script
./scripts/test_radio_group.sh
Test Script Features
The test script (scripts/test_radio_group.sh) provides:
- Colored Output - Easy-to-read test results
- Comprehensive Coverage - All test types in one command
- Detailed Reporting - Pass/fail counts and summaries
- Error Handling - Proper exit codes for CI/CD
Test Results
Success Output
🧪 Running RadioGroup Component Tests
=====================================
ℹ️ INFO: Running Yew RadioGroup Unit Tests...
✅ PASS: Yew RadioGroup Unit Tests completed successfully
ℹ️ INFO: Running Leptos RadioGroup Unit Tests...
✅ PASS: Leptos RadioGroup Unit Tests completed successfully
...
📊 Test Summary
===============
Total tests: 12
Passed: 12
Failed: 0
✅ PASS: All RadioGroup tests passed! 🎉
Failure Output
❌ FAIL: Yew RadioGroup Unit Tests failed
...
📊 Test Summary
===============
Total tests: 12
Passed: 8
Failed: 4
❌ FAIL: 4 test(s) failed. Please check the output above.
Best Practices
Writing Tests
- Test Structure - Follow the established patterns
- Naming - Use descriptive test names
- Assertions - Include meaningful assertion messages
- Coverage - Test all public APIs and edge cases
- Isolation - Tests should be independent
Framework-Specific Considerations
Yew Tests
- Use
wasm_bindgen_testfor browser tests - Use
yew::start_app_with_propsfor component testing - Test DOM queries and event handling
Leptos Tests
- Use
mount_to_bodyfor component mounting - Use signals for state management testing
- Test context providers and consumers
Cross-Framework Testing
- API Consistency - Ensure same props and events
- Feature Completeness - All features available in all frameworks
- Theme Support - Both default and New York variants
- Accessibility - Same ARIA attributes and behavior
Continuous Integration
GitHub Actions
The testing infrastructure integrates with GitHub Actions:
- name: Run RadioGroup Tests
run: ./scripts/test_radio_group.sh
Local Development
For local development:
# Quick test during development
cargo test -p shadcn-ui-yew-radio-group --lib
# Full test suite
./scripts/test_radio_group.sh
# Specific test category
cargo test test_radio_group_cross_framework_parity
Future Enhancements
Planned Features
- Visual Regression Testing - Automated visual comparison
- Performance Testing - Bundle size and runtime performance
- Browser Testing - Cross-browser compatibility
- Mobile Testing - Touch interactions and responsive design
- Accessibility Auditing - Automated accessibility scanning
Test Coverage Metrics
- Line Coverage - Track code coverage percentage
- Branch Coverage - Ensure all code paths are tested
- Function Coverage - All public functions tested
- Integration Coverage - All framework combinations tested
Troubleshooting
Common Issues
- WASM Tests Failing - Ensure
wasm32-unknown-unknowntarget is installed - Browser Tests - Ensure browser environment is available
- Dependency Issues - Check Cargo.toml dependencies
- Build Failures - Verify component implementations
Debugging Tips
- Verbose Output - Use
RUST_LOG=debugfor detailed logging - Single Test - Run individual tests for focused debugging
- Browser Console - Check browser console for WASM test errors
- Test Isolation - Ensure tests don't interfere with each other
Conclusion
The testing infrastructure provides comprehensive coverage for component quality, cross-framework parity, and maintainability. By following the established patterns and running the complete test suite, developers can ensure that components work correctly across all supported frameworks and maintain the high quality standards of the Rust shadcn/ui project.