Testing
Pyramid
┌──────────────┐
│ E2E (5%) │ Playwright + integration_test
├──────────────┤
│ Contract (15%)│ OpenAPI-driven
├──────────────┤
│ Integration (30%)│ Pest Feature, Vitest, Flutter widget
├──────────────┤
│ Unit (50%) │ Pest Unit, Vitest, Flutter unit
└──────────────┘
Coverage Targets
| Area | Target |
|---|---|
server/app/Services | 90% |
server/app/Policies | 100% |
server/app/Http/Controllers | 70% |
ui/src/features | 75% |
app/lib/features | 70% |
Key Suites
Pest (server)
tests/Unit/Attendance—AttendanceProcessor,RedFlagEngine,RosterService.tests/Feature/Attendance— punch endpoint, window enforcement, multi-channel.tests/Feature/Leave+tests/Feature/Regularization— chain transitions.tests/Feature/Policies— full role × scope × resource matrix.tests/Feature/Locking— auto-lock scheduled command.
Vitest (web)
- Form + query hook tests per feature.
- Role guard tests on routes.
Playwright (e2e)
- Happy path: login → view today → drill into an attendance row.
- Manager flow: approve a leave end-to-end.
Flutter
- Unit: geofence distance, punch buffer replay.
- Widget: check-in button states.
- Integration: mocked backend driven test on a real emulator.
Test Data
- Factories via
Database\Factoriesfor every model. - Scenario seeders (
DemoTenantSeeder) produce a realistic 50-employee / 3-shift / 1-month dataset for manual QA and for the mobile app's "demo mode".
Load Testing
k6 script in ops/load/punch.js:
- 500 rps sustained
POST /attendance/punchfor 10 minutes. - Asserts p95 < 500 ms, error rate < 0.5%.
- Runs against staging before every GA.