Testing Strategy

Testing matrix and coverage requirements for the V0.1 release across all three applications.

API (PHPUnit — ≥ 80% critical domain coverage)

All API security tests are CI-blocking. A failing test prevents merge.

Critical Test Categories

#CategoryWhat to test
1Collection securityNo line-level voters on collections. Doctrine Filter global ON. Cross-tenant queries must fail.
2Doctrine FilterFilter ON everywhere in HTTP. QueryFilterEnforcer returns 500 if filter OFF. CLI whitelist allows exempted commands.
3Slug / i18nNFKC/fold normalization. FR and AR slug collision tests are blocking. ICU version pinned.
4State ProcessortenantId injection from JWT. Malicious tenantId in body silently ignored.
5Voters + expressionsItem-level voters only. WRITE cross-tenant returns 403.
6ETag / If-MatchBehavior per CONCURRENCY_STRICT flag. 428 (missing header) / 412 (mismatch) when strict. Canonical JSON non-regression.
7Presigned uploadsAWS mocks for presigned PUT. HEAD post-upload with backoff. Size/type validation.
8RateLimiterAuth/public key isolation. Pepper rotation. Retry-After header. Quota per role.
9JWKSRollover (double-KID). Clock skew tolerance. aud as string and array. id_token refused. Cross-env/tenant tokens refused. Circuit breaker behavior.
10Public projectionsGET anonymous is cacheable (correct Vary/Cache-Control/ETag). Authorization present returns 403 + no-store. Edge strip tested.
11PreviewX-Preview-Token header. HMAC signature validation. Redis one-time (SETNX+TTL). Expired/replay returns 401.
12RFC 7807 errorsAll 4xx/5xx responses return application/problem+json conformant body.

Front-Office (Vitest + Playwright)

CategoryToolWhat to test
ComponentsTesting LibraryRendering, props, events, slots
AccessibilityTesting LibrarySkip link present, focus management, hreflang correct
CSPPlaywrightZero unhashed inline scripts/styles. XSS injection attempt blocked.
Performance budgetsLighthouse CIHard-fail if JS > 180KB (+20%), CSS > 60KB (+20%), LCP > 2.0s/2.5s
Matomo DNTPlaywrightDNT=1 header produces zero Matomo network requests
Silent authPlaywright E2EAT expiration + ITP-like scenario results in clean relog. prompt=none failure triggers modal.

Back-Office (Vitest + Playwright)

CategoryToolWhat to test
ComponentsTesting Library (Vitest)Rendering, props, events, slots
AccessibilityTesting LibraryAccessible forms, keyboard navigation, focus management
CSPPlaywrightHash-only enforcement, zero unhashed inline
Trusted TypesPlaywrightReport-only mode active (V0.1)
XSSPlaywrightInjection attempt produces 0 API calls
OpenAPI hashBuild stepBuild fails if local hash does not match /contract-hash
ETag UXPlaywright412/428 responses handled gracefully in UI

Integration Tests

CategoryWhat to test
CORSAllowed origins, exposed headers, preflight responses
VaryOrigin, Accept-Language, Accept-Encoding present on all responses
Authorization cachingGET with Authorization header returns Cache-Control: no-store
Edge strip/v1/public/* requests have Authorization stripped by edge nginx

E2E Smoke Tests (Playwright)

Front-Office Smoke

  • All locales render correctly (fr, en, nl, ar)
  • hreflang tags present and correct
  • Lazy images load on scroll
  • RTL layout renders correctly for ar

Back-Office Smoke

  • Real OIDC login (Keycloak, no mock) without Refresh Token
  • Minimal CRUD: create, read, update, delete an article
  • Preview one-time token: header-based, non-cacheable, single use

SLO Validation (k6)

MetricTarget
API p95 latency< 300ms
API p99 latency< 600ms
Error rate< 1%
Test seed3 tenants x 4 locales x 10,000 articles
Warm-up2 minutes before measurement