# E2E Testing Guide for CLAIRE
_under construction_
This guide covers the End-to-End (E2E) testing system for the CLAIRE Electronic Lab Notebook, focusing on sustainable, CI-friendly testing practices.
## Overview
The E2E testing system is designed with these principles:
- **Zero-setup** for developers
- **CI-friendly** for GitHub Actions
- **Schema-agnostic** testing approach
- **Static fixtures** checked into repository
- **NODE_ENV-based** test attributes (no manual scripts)
## Quick Start
```bash
# Run all E2E tests with proper config
make test-e2e
# Run only ReviewSubmitPanel tests
make test-e2e-reviewsubmit
# Run with visual UI for debugging
make test-e2e-ui
# Run in debug mode
make test-e2e-debug
```
## Test Structure
```
frontend/tests/
├── e2e/ # E2E tests using Playwright
│ ├── reviewsubmit/ # ReviewSubmitPanel component tests
│ │ ├── display.spec.ts # Data display and rendering
│ │ ├── interaction.spec.ts # UI interactions
│ │ ├── validation.spec.ts # Form validation
│ │ └── edge-cases.spec.ts # Edge cases & performance
│ ├── helpers/ # Test utilities
│ │ ├── page-objects.ts # Page Object Model
│ │ └── test-utils.ts # Test data builders
│ └── test-component.html # Standalone test component
├── fixtures/ # Static test data (checked in)
│ ├── sops/ # SOP schema fixtures
│ │ ├── basic-sop.json # Standard SOP for most tests
│ │ ├── all-field-types-sop.json # All field types
│ │ └── minimal-sop.json # Minimal edge case
│ ├── eln-data/ # ELN form data fixtures
│ │ ├── complete-form.json # Fully filled form
│ │ ├── partial-form.json # Partial form (missing required)
│ │ └── empty-form.json # Empty form
│ └── test-scenarios/ # Test scenarios with metadata
│ ├── sopTest1-complete.json # Complete test scenario
│ └── sopTest1-partial.json # Partial test scenario
└── README.md
```
## Key Features
### Automatic Test Attributes
Test attributes are automatically enabled when `NODE_ENV=test`:
```typescript
// In ReviewSubmitPanel.tsx
const testAttrs = process.env.NODE_ENV === 'test' ? {
'data-testid': 'review-submit-panel'
} : {};
return
```
**Benefits:**
- ✅ **Zero-setup** - Test runners automatically set NODE_ENV=test
- ✅ **Production-safe** - No test attributes in production builds
- ✅ **No scripts** - No need for complex attribute management
### Static Test Fixtures
All test data is stored as JSON files checked into the repository:
```typescript
// Automatic fixture loading
static async loadBasicSOP(): Promise {
return basicSOP as SOP;
}
static async loadCompleteELNData(): Promise {
return completeELNData as ELNFormData;
}
```
**Benefits:**
- ✅ **Consistent** across environments
- ✅ **Schema-compliant** with SOPTemplateSchema
- ✅ **Version controlled** - changes tracked in git
- ✅ **Fast** - no API calls or complex setup
### Standalone Test Component
For fast, isolated testing, we use a standalone HTML file (`test-component.html`) that mimics the ReviewSubmitPanel structure:
- Static HTML with proper data-testid attributes
- Interactive features (collapsible cards, etc.)
- Representative test data
- No dependencies on full application stack
## Make Rules Integration
The Makefile provides convenient commands that handle environment setup:
```makefile
test-e2e:
@$(MAKE) config ENV=test # Sets up test config files
@cd frontend && NODE_ENV=test npx playwright test
test-e2e-reviewsubmit:
@$(MAKE) config ENV=test
@cd frontend && NODE_ENV=test npx playwright test tests/e2e/reviewsubmit
test-e2e-integration:
@$(MAKE) config ENV=test
@$(MAKE) start-backend ENV=test & # Real backend integration
@cd frontend && NODE_ENV=test npx playwright test
```
## Test Data Management
### SOP Fixtures
SOP fixtures follow the actual SOPTemplateSchema structure:
```json
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"id": "basic-sop-fixture",
"taskgroups": [
{
"id": "taskgroup_basic_info",
"_schemaType": "TaskGroup",
"children": [
{
"id": "task_patient_data",
"_schemaType": "Task",
"children": [
{
"id": "patient_id",
"_schemaType": "Field",
"type": "string",
"required": true
}
]
}
]
}
]
}
```
Note: `_schemaType` fields are being phased out in favor of a more standardized schema structure.
**Key Properties:**
- `type`: For fields, identifies data type (string, integer, boolean, date, enum, array)
- `children`: Array of nested schema elements (indicates containers)
- `parent`: Array defining hierarchy relationships
- `ui_config`: Rendering configuration (icons, variants)
- `ordinal`: Display order for elements
- **No `_schemaType`**: Structure determined by presence of `type` (fields) vs `children` (containers)
(_schemaType is going away)
### ELN Data Fixtures
ELN fixtures represent completed form data:
```json
{
"values": {
"patient_id": "PT-001",
"patient_age": 35,
"consent_given": true
},
"metadata": {
"sop_id": "basic-sop-fixture",
"completion_percentage": 100
}
}
```
### Test Scenarios
Test scenarios combine SOPs, ELN data, and expected validation results:
```json
{
"name": "Basic Valid Form",
"sop_id": "basic-sop-fixture",
"eln_data": {
"patient_id": "P001",
"additional_fields": "..."
},
"expected_validation": {
"isValid": true,
"missingRequiredFields": [],
"totalFields": 6
}
}
```
## Page Object Model
The `ReviewSubmitPageObject` class abstracts UI interactions:
```typescript
const reviewPanel = new ReviewSubmitPageObject(page);
// Navigation and setup
await reviewPanel.waitForLoaded();
// Field interactions
const value = await reviewPanel.getFieldValue('Patient ID');
const isRequired = await reviewPanel.isFieldRequired('Patient ID');
// Card interactions
await reviewPanel.toggleCard('Basic Information');
const isExpanded = await reviewPanel.isCardExpanded('Basic Information');
// Validation checks
const summary = await reviewPanel.getValidationSummary();
const missingFields = await reviewPanel.getMissingRequiredFields();
```
## Development Workflow
### Test-First Development
1. **Write tests** for new component behavior
2. **Run tests** to see them fail
3. **Implement feature** to make tests pass
4. **Refactor** with confidence that tests catch regressions
### Schema-Agnostic Testing
Tests follow the same principles as the components:
```typescript
// ✅ Good - Schema-driven
const isField = (element: any) => Boolean(element.type && FIELD_TYPES.includes(element.type));
const isContainer = (element: any) => Boolean(element.children && element.children.length > 0);
// ❌ Bad - Hardcoded assumptions
const isPatientField = (element: any) => element.id.includes('patient');
const usesSchemaType = (element: any) => element._schemaType === 'Field'; // _schemaType is deprecated
```
**Guidelines:**
- Identify fields by `element.type` property (string, integer, boolean, etc.)
- Identify containers by `element.children` array presence
- Use schema structure (`children`, `parent`) for navigation
- Test validation based on `required` and `validation` properties
- Never use `_schemaType` (deprecated SAM-only property)
- Never hardcode field names or specific counts
### Adding New Tests
1. **Create test file** in appropriate subdirectory
2. **Use page objects** for UI interactions
3. **Load static fixtures** for consistent data
4. **Test multiple scenarios** (valid, invalid, edge cases)
Example:
```typescript
test('renders enum fields as badges', async () => {
const sop = await TestDataBuilder.loadAllFieldTypesSOP();
const elnData = await TestDataBuilder.loadCompleteELNData();
// Use page object for interactions
const fieldValue = await reviewPanel.getFieldValue('Sample Type');
expect(fieldValue).toContain('blood');
});
```
## CI/CD Integration
### GitHub Actions
Tests run efficiently in CI with:
- **Fast startup** using static fixtures
- **Parallel execution** for speed
- **Proper isolation** between test runs
- **Minimal resource usage**
### Environment Configuration
```yaml
# In GitHub Actions workflow
- name: Run E2E Tests
run: |
make config ENV=test
cd frontend && NODE_ENV=test npx playwright test
```
The `ENV=test` ensures:
- Test config files are deployed to `frontend/public/config.json`
- Backend configs use test settings
- API endpoints point to test environment
## Debugging
### Visual Debugging
```bash
# Open test in browser with visible actions
make test-e2e-headed
# Use Playwright Inspector for step-by-step debugging
make test-e2e-debug
```
### Test Reports
```bash
# View detailed HTML report after test run
npx playwright show-report
```
### Common Issues
| Issue | Solution |
|-------|----------|
| Test attributes not found | Ensure `NODE_ENV=test` is set |
| Fixture not found | Check file paths in `fixtures/` directory |
| Component not rendering | Verify SOP schema structure in fixtures |
| Port mismatch | Check `playwright.config.ts` baseURL matches dev server |
## Performance Monitoring
### Targets
- **Form Load**: <2 seconds
- **Field Interactions**: <100ms
- **Memory Usage**: <100MB for form data
- **Test Execution**: <30 seconds for full suite
### Monitoring
```typescript
test('loads large forms within performance targets', async () => {
const startTime = performance.now();
await reviewPanel.waitForLoaded();
const loadTime = performance.now() - startTime;
expect(loadTime).toBeLessThan(2000); // 2 second target
});
```
## Best Practices
### Do ✅
- Use static fixtures for consistent test data
- Follow schema-agnostic principles
- Test user workflows, not implementation details
- Use page objects for complex interactions
- Test validation behavior comprehensively
### Don't ❌
- Hardcode field names or specific field counts
- Rely on external services or APIs
- Create overly complex test setup procedures
- Test internal component state directly
- Skip edge cases and error scenarios
## Future Enhancements
### Potential Additions
- **Visual regression testing** with screenshot comparisons
- **Accessibility testing** for WCAG compliance
- **Cross-browser testing** with extended browser matrix
- **Performance monitoring** with continuous tracking
- **Integration testing** with real backend services
### Test Data Expansion
- **Complex nested schemas** for advanced hierarchy testing
- **Internationalization** support with multi-language data
- **Real-world scenarios** based on production usage patterns
- **Error simulation** for network and API failure cases