14 — QA Checklist (Settings Module)
- 1. Functional
- 2. Tenancy & security
- 3. Visual / layout
- 4. Accessibility (00-shared/09)
- 5. Performance
- 6. Offline & network (00-shared/10 §2)
- 7. Tablet / desktop
- 8. Localization
- 9. Dark mode / animations
- 10. Server-backed edge mirrors
- QA scripts
Module QA specific to the framework + shared 00-shared/10. Every check derives from a specific backend behavior so failure analysis is direct.
1. Functional
-
GET /settingsreturns a bare array (nometa) sortedgroup,key(settings.service.ts:10-12;response-envelope.interceptor.ts:25-32). -
GET /settings?group=attendancereturns only that group; invalid group value → 400VALIDATION_ERRORwithdetails(settings.controller.ts:26-28;update-setting.dto.ts:14). -
GET /settings/:key→ 200 doc; unknown key → 404Setting "«key»" not found.(settings.service.ts:20). -
PUT /settingsupsert: new key creates; existing key replaces value (verify a nested object field dropped from payload is gone after save —setting.repository.ts:37); response is the saved doc (new: true). -
PUT /settingsomittinggroupkeeps existing group; sendinggroupmoves the key. -
label/descriptionsent inPUT /settingsare not persisted (verify DB —settings.service.ts:25). -
PUT /settings/bulksaves all; response array order matches input order (settings.service.ts:28-34). -
Boolean value round-trips as JSON
true/false; number stays number; numeric string stays string (no coercion). -
DELETE /settings/:key→ 200; second delete → 404 (settings.service.ts:40). - Re-create a deleted key → expect E11000 → 500 (OQ-5) — QA documents current behavior; UI shows the soft-delete banner.
-
Soft-deleted doc stays in DB with
isDeleted:true, deletedAt(base.repository.ts:68-74). - Bulk with a duplicate key inside the batch → last item wins (client dedupes first).
2. Tenancy & security
-
Tenant A's token can never read/write tenant B's settings (unique index
{tenantId,key},setting.schema.ts:38;scopedFilter,base.repository.ts:20-30). -
No
tenantIdaccepted from the body — only from token (repo injects,setting.repository.ts:34). -
Platform admin token →
GET /settingsreturns cross-tenant rows (scope bypassbase.repository.ts:21-23) — UI labels this mode; QA confirms no accidental write to wrong tenant. -
Permission matrix: any authenticated user can currently CRUD settings (no
@Permissionson controller, OQ-2). QA verifies client guard behavior (hidden routes); flag server enforcement as pending.
3. Visual / layout
- Long keys wrap without clipping at 200% text scale; preview ellipsis only.
- JSON values render truncated preview + expand into editor prefilled (never blank).
-
Dark-light parity: dirty tint
primaryContainer, JSON editor fill, chips. - Master-detail ≥840 dp; batch bar respects nav bar height on phone.
4. Accessibility (00-shared/09)
- TalkBack: browse → edit → save → delete fully operable without sight.
- VoiceOver separately.
-
Keyboard-only desktop: search (
Ctrl+F), Enter saves, Esc closes, focus ring visible. - Dirty rows announced ("unsaved"); JSON parse errors announced on focus.
- Group chips announce selected state; type chips are labeled (no color-only status).
- Contrast: body 4.5:1, icons/chips 3:1; reduced-motion honored.
5. Performance
- List first frame ≤ 300 ms (cache) / skeleton ≤ 200 ms, content ≤ 2 s (network).
- No duplicate parallel requests (group switch cancels in-flight previous fetch).
-
ListView.builderonly; no full-page rebuild on row save. - Memory stable over 20-min session (100+ keys).
6. Offline & network (00-shared/10 §2)
- Offline open → cached rows + banner; editors disabled with guidance.
- Slow network: row spinner; retry works; no silent double-write (idempotent PUT — two same payloads ⇒ one final value).
- Mid-bulk failure → "Saved N of M" + per-row retry sends full dirty set.
7. Tablet / desktop
- Master-detail two-pane; hover row tint; right-click row menu.
-
Ctrl/Cmd+Entersaves JSON editor;N/+new setting; Esc exits batch mode.
8. Localization
-
All strings via i18n; group labels localized (
attendance→ "Attendance"); enum values are the wire values (never translated in requests). -
RTL: group chips scroll direction, JSON editor LTR-aligned (
monoblock).
9. Dark mode / animations
- Full visual pass both modes; tokens only; motion tokens only; reduced-motion pass.
10. Server-backed edge mirrors
- 400 group enum details rendered inline.
- 404 detail/delete treated as removed.
- 500 (missing key/value, E11000) → generic + requestId, form kept, banner for soft-delete case (OQ-3, OQ-5).
- 429 → countdown, no auto-retry.
QA scripts
- Golden per component (light/dark × phone/tablet/desktop × dirty/saving/error states).
- E2E (device-cloud P0): list → group filter → edit string → toggle bool → batch save → delete (device-cloud; mock/seed tenant with ~20 keys across all 6 groups).
- Tenancy smoke: second tenant token → expect 404/empty, never other tenant's rows.
- Upsert idempotency smoke: same PUT twice → identical
versionincrement pattern (second call may bump version — verify no duplicate key rows).