Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

14 — QA Checklist (Settings Module)

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 /settings returns a bare array (no meta) sorted group,key (settings.service.ts:10-12; response-envelope.interceptor.ts:25-32).
  • GET /settings?group=attendance returns only that group; invalid group value → 400 VALIDATION_ERROR with details (settings.controller.ts:26-28; update-setting.dto.ts:14).
  • GET /settings/:key → 200 doc; unknown key → 404 Setting "«key»" not found. (settings.service.ts:20).
  • PUT /settings upsert: 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 /settings omitting group keeps existing group; sending group moves the key.
  • label/description sent in PUT /settings are not persisted (verify DB — settings.service.ts:25).
  • PUT /settings/bulk saves 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 tenantId accepted from the body — only from token (repo injects, setting.repository.ts:34).
  • Platform admin token → GET /settings returns cross-tenant rows (scope bypass base.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 @Permissions on 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.builder only; 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+Enter saves 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 (mono block).

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 version increment pattern (second call may bump version — verify no duplicate key rows).