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 (Parents Module)

Module QA specific to framework + shared 00-shared/10. Every check derives from a specific backend behavior so failure analysis is direct.


1. Functional

Profile CRUD

  • POST /parents with valid userId → 200/201 data parent doc (parent.service.ts:29-47).
  • Same userId again → 409 DUPLICATE_RESOURCE "Parent profile already exists for this user." (parent.service.ts:32-34).
  • GET /parents paginated: meta = page/limit/totalItems/totalPages/hasNext/hasPrevious; limit > 100 → 400 (pagination-query.dto.ts:17-19).
  • GET /parents?q=&sort= — confirm ignored server-side (expected today, parent.service.ts:58-61) — client filter must not pretend to search (OQ-7).
  • GET /parents/:id → 404 "Parent not found." for unknown id (parent.service.ts:51).
  • PATCH /parents/:id partial update; userId in body → silently ignored (no field in UpdateParentDto).
  • DELETE /parents/:id soft-delete: subsequent list/detail exclude it; isDeleted set (base.repository.ts:68-74).
  • Invalid ObjectId path param → 400 VALIDATION_ERROR "Invalid resource identifier." (http-exception.filter.ts:48,92).

Link validation

  • POST /parents/link/:studentId creates link with relationship, flags, emergencyPriority (student-parent-link.service.ts:16-32).
  • Known gap: link to a non-existent student succeeds (findById result discarded, student-parent-link.service.ts:27) — QA must record behavior; decide with product (OQ-3).
  • Known gap: duplicate (studentId, parentId) link succeeds (non-unique index, student-parent-link.schema.ts:46) — QA must decide client-block or server-fix (OQ-2).
  • Known gap: invalid relationship string → 500 (schema enum, no DTO enum, link-parent.dto.ts:19-20) — client must only send enum values (OQ-6).
  • GET /parents/link/student/:studentId returns all links for student; empty array when none (student-parent-link.repository.ts:20-22).
  • DELETE /parents/link/:linkId → 200; repeat → 404 "Link not found." (student-parent-link.service.ts:40).

Primary-guardian switches

  • Primary flag stored per link (isPrimaryGuardian, student-parent-link.schema.ts:27-29).
  • Known gap: two links for one student can both be primary (no exclusivity, OQ-5) — QA verifies client warning + documents server behavior.
  • Switch-primary flow (unlink old + recreate new, OQ-4) preserves all other flags and ordering; verify no partial state if second call fails (rollback handling in LinkCubit).
  • Unlink of primary guardian leaves student with zero primaries; warning shown (OQ-4).

Unlink with active links

  • Unlink does not delete the parent profile (parent.service.ts:89-100 vs student-parent-link.service.ts:38-41).
  • Parent with zero links still lists/opens fine (findLinks returns []).
  • Delete parent with active links: links remain, orphaned — children section must handle student-missing/parent-missing join gracefully (OQ-3).

Privacy: parent sees only own children

  • Cross-tenant: tenant A token listing parents → only tenant A docs (base.repository.ts:20-30).
  • Parent role: no my-children endpoint exists — UI must not fake it (OQ-1); when (planned) lands: verify parent sees exactly linked children, other children 404/absent.
  • Platform admin bypasses tenant scope (base.repository.ts:21-23) — verify intended.
  • No parent.* permission exists (permissions.constants.ts) — any JWT can create/delete parents today; QA flags this as known risk until RBAC (OQ-8).

Multi-child households

  • One parent linked to 3 students → 3 link rows; detail groups per child; GET /parents/:id/students returns all (parent.service.ts:69-72).
  • Two parents (mother+father) linked to same student → 2 rows with different relationships; per-link flags independent.
  • Student join: child cards render from GET /students/:id per link (OQ-10); archived/gone student handled.

2. Visual / layout

  • List/detail/forms dark-light parity; no hardcoded colors (00-shared/10 §6).
  • Long names + 3 children badges wrap at 200% text scale; EmergencyFlagsRow wraps.
  • Master-detail ≥ 840 dp; phone single pane; sheets full-height on keyboard.

3. Accessibility (00-shared/09)

  • TalkBack: list → detail → link sheet → unlink full journey without sight.
  • VoiceOver separately.
  • Keyboard-only desktop: Tab order, Enter submit, Esc closes sheet/dialog, N new.
  • Relationship chips + primary badge announced; switcher toggled semantics.
  • Flags never color-only (icon+label).
  • Contrast 4.5:1 text / 3:1 chrome; reduced-motion off (no shake/stagger).

4. Performance

  • List skeleton ≤ 200 ms; infinite scroll appends without duplicate parallel page requests (00-shared/10 §1).
  • Detail children join: N+1 bounded; no repeated fetches on rebuild (cache per parent).
  • No duplicate parallel requests for same student while joining (dedupe map in ParentDetailCubit).

5. Offline & network

  • Offline list → last-good cache + banner; writes blocked.
  • Link submit offline → blocked with guidance (no silent failure).
  • Network loss mid-submit → no duplicate rows on retry known risk (no idempotency, OQ-2) — QA: verify one retry creates one row only if first failed.

6. Tablet / desktop

  • Master-detail list+detail; hover states; right-click menus; Esc; breadcrumbs depth > 2 (00-shared/05 §3).

7. Localization

  • All strings i18n keys (parents.*); relationship labels localized; RTL-safe chips row.
  • Currency/income format via Intl; dates locale-aware.

8. Permissions

  • Today: JWT-only (documented risk, OQ-8). When RBAC lands: parent.read/create/update/delete/link gate each surface (04-Modules/Parents.md:64-70); self-service for parent role only (role.schema.ts:50-56).
  • Cross-tenant link creation impossible (tenantId injected, base.repository.ts:33-35).

9. Dark mode

  • Full visual pass; primary badge primaryContainer dark variant (TBD by designer, 00-shared/02 §1.4); banners readable.

10. Animations

  • Tokens only; reduced-motion; no flashes on unlink row removal.

11. Security

  • No PII logged client-side; tokens secure storage (00-shared/10 §3).
  • 404 vs 403 semantics: unknown parent → 404 (no existence leak across tenants — repository scoping returns empty → 404, parent.service.ts:49-53).
  • 5xx internals never surfaced (filter, http-exception.filter.ts:60-65).

12. Server-backed edge mirrors

  • emergencyPriority/annualIncome accept numbers only — client coerces; note DTO has no type decorators (create-parent.dto.ts:18-34).
  • pickupAllowed link default true vs pickupAuthorization profile default false — QA cross-checks display on both surfaces.
  • Event side effects: ParentCreated → in-app job; ParentUpdated/ParentDeleted → audit-write jobs (event-queue-map.ts:37-39); verify in-app notification appears (planned) UI.

QA scripts

  • Golden per module component (light/dark × phone/tablet/desktop × states) (07 §10).
  • E2E (P0): create user → create parent → link to student → set primary → unlink → delete parent (device-cloud).
  • Regression: duplicate-link, double-primary, orphan-link join cases recorded as known gaps with product decisions (OQ-2..OQ-6).