10 — Frontend Testing Strategy
Scope: What the FE pyramid looks like across web, mobile, desktop, and kiosk; what must be green to ship; how journeys map to e2e gates. This doc inherits from the platform-wide
../../11-testing-strategy-qa.mdand elaborates the FE slice.Companions:
09-non-functional-requirements.md·../../standards/FRONTEND_DEFINITION_OF_DONE.md
1. Pyramid
| Layer | Web | Mobile | Desktop | Kiosk |
|---|---|---|---|---|
| Unit | Vitest | Jest | Vitest (renderer) + Node test runner (main / sync worker) | shared with desktop |
| Component | Testing Library (@testing-library/react) | React Native Testing Library | Testing Library | shared |
| Visual regression | Chromatic per Storybook story (per primary locale + RTL) | Loki / RN Storybook + Chromatic web stories for shared primitives | Chromatic per renderer story | shared |
| End-to-end | Playwright (Chromium + WebKit + Firefox; mobile emulation Pixel 5 + iPhone 13) | Detox (iOS Sim + Android Emulator; one Pixel 4a profile gates main) | Playwright Electron driver against packaged build | Playwright Electron driver in kiosk-shell mode |
| Accessibility | axe-core in Storybook + Playwright @axe-core/playwright | Detox + manual VoiceOver / TalkBack scripts | axe + manual NVDA | tap-target + screen-reader audits |
| Performance | Lighthouse-CI (3 runs median) | Reassure on hot screens | synthetic perf test for HK board / reservation list | manual idle-loop test (24h) |
| Contract | Generated OpenAPI clients typecheck-validated; mock BFF via msw | msw for native (works in Expo) | msw in renderer; nock in main / sync worker | shared |
| i18n / pseudo-locale | en-XA rendered for every PR; truncation + RTL flips checked | same | same | same |
| Integration (sync) | n/a | n/a | full sync round-trip against test BFF; conflict-resolution fixture | shared |
Coverage floors:
- Unit: 80% lines on
packages/feature-*andpackages/ui-melmastoon - Component: every primitive story has at least one interaction test
- E2E: every gated journey (see §3) has at least one scenario per platform it ships on
2. What must be green to merge a PR
PR-merge gate (CI):
- Typecheck passes (
tsc --noEmit) across the workspace - ESLint passes (incl.
eslint-plugin-boundaries, no-raw-color, no-physical-properties, i18n key checks) - Unit + component tests green; coverage above floor
- Visual regression: zero unreviewed Chromatic diffs (or explicit accept)
- Bundle / size budgets within thresholds (
@next/bundle-analyzer/ EAS Build report / electron-builder size) - Lighthouse-CI (web changes only): perf >= 90, a11y >= 95, best-practices >= 95, SEO >= 95
- axe: zero serious / critical issues on every changed Storybook story
- New telemetry events declared in
../catalogs/C1-telemetry-event-dictionary.md(P1 doc)
PR-review gate (human):
- Design review checklist signed off (
../../standards/DESIGN_REVIEW_CHECKLIST.md) - Frontend DoD signed off (
../../standards/FRONTEND_DEFINITION_OF_DONE.md) - Security review for any change touching auth, payment, lock/key, AI orchestration, multi-tenant boundary
3. Critical journey e2e gates
These journeys MUST have a passing e2e on every release branch. Failure blocks release.
| Gate ID | Surface | Journey | E2E test name |
|---|---|---|---|
| G-WEB-1 | Web meta + tenant booking | Search -> filter -> map toggle -> property detail -> handoff -> bootstrap -> quote -> hold -> guest details -> cash-on-arrival -> confirmation | web/e2e/full-meta-to-cash-confirmation.spec.ts |
| G-WEB-2 | Tenant booking | Direct entry to <tenant>.melmastoon.app/book -> bootstrap -> quote -> hold -> card payment via Adyen test mode -> return -> confirmation | web/e2e/tenant-booking-card.spec.ts |
| G-WEB-3 | Tenant booking | Hold-expiry mid-funnel -> re-quote -> resume | web/e2e/hold-expiry-resume.spec.ts |
| G-MOB-1 | Mobile | Discover (search) -> property detail -> Book -> bootstrap tenant -> quote -> hold -> MFS payment -> return -> confirmation | mobile/e2e/discover-to-mfs.spec.ts |
| G-MOB-2 | Mobile | Trips tab opened offline -> cached upcoming reservation visible -> "Get directions" works -> "Modify dates" cleanly disabled with banner | mobile/e2e/trips-offline.spec.ts |
| G-MOB-3 | Mobile | Push notification arrival -> deep-link into ConfirmationScreen from cold start | mobile/e2e/push-deeplink-cold.spec.ts |
| G-DSK-1 | Desktop | Front-desk arrival flow: walk-in -> create reservation -> assign room -> issue key (encoder) -> print registration card | desktop/e2e/walkin-to-key.spec.ts |
| G-DSK-2 | Desktop | Sync recovery: go offline for 30 min, make 5 status changes -> reconnect -> outbox replays without conflict | desktop/e2e/sync-recovery.spec.ts |
| G-DSK-3 | Desktop | HK board: drag room from dirty to cleaning -> assign housekeeper -> mark inspected -> verify event publication | desktop/e2e/hk-board-flow.spec.ts |
| G-KIO-1 | Kiosk (R2) | Self-checkin: pre-arrived guest -> passport scan -> e-signature -> payment -> key issuance -> idle-reset works | kiosk/e2e/self-checkin-happy.spec.ts |
Adding a journey to this list requires PR review by QA + the surface owner.
4. Test data and fixtures
- Test tenants:
kabul-grand-hotel(PS/DR primary),karachi-gateway-suites(UR/EN primary),dubai-pearl-residency(AR/EN primary),paris-petit-palais(FR/EN, Phase 2) - Test properties: at least one property per tenant with full media, rooms, rate plans, policies seeded
- Test guests:
guest.alpha@example.test(returning loyalty),guest.beta@example.test(first-time),guest.gamma@example.test(RTL primary, Pashto) - Test cards: Adyen test cards per https://docs.adyen.com/development-resources/testing/test-card-numbers
- Test MFS accounts: documented in
tooling/test-fixtures/mfs.jsonof impl monorepo - Test locks: stub encoder in
tooling/test-fixtures/lock-stubs.ts; physical lock simulator for E2E ring (R2)
5. Localisation testing
- Pseudo-locale
en-XArendered every PR — checks for hardcoded strings + truncation + bidi flips - Real-locale review per release: native speaker review for PS / DR / UR / AR / FR (Phase 2)
- Numerals invariant: financial confirmations always Latin numerals — automated assertion in confirmation snapshot tests
6. Performance testing
See 09-non-functional-requirements.md §1. Per-PR perf budgets are gated; per-release synthetic perf runs cover:
- Web: Lighthouse-CI on top 5 routes per app
- Mobile: Reassure on
SearchScreen,PropertyDetailScreen,BookingFlow,TripsTab - Desktop: synthetic HK board with 200 rooms, reservation list with 50 rows
- Local AI: cold first-token + warm first-token + 50-token completion latency
7. Security testing
- Static:
eslint-plugin-security,npm auditin CI - Dependency: Dependabot weekly; alert-on-critical immediate
- Dynamic: BFF security tested separately (see service
SECURITY_MODEL.md); FE security tested for CSP, cookie flags, XSS escaping, CSRF token presence - Penetration: external pen-test before R1 GA, then quarterly
8. Open questions
- Should we adopt Playwright Component Testing for
@ghasi/ui-melmastoonto replace some Vitest+Testing-Library tests? Trade-off: real browser vs jsdom speed. - Mobile visual regression on real devices vs simulators only — coverage vs cost.
- Desktop e2e test ring: do we run on all 3 OS in CI, or rotate (Mac matrix Mon, Windows Tue, Linux Wed)?