14 — QA Checklist (Parents Module)
- 1. Functional
- 2. Visual / layout
- 3. Accessibility (00-shared/09)
- 4. Performance
- 5. Offline & network
- 6. Tablet / desktop
- 7. Localization
- 8. Permissions
- 9. Dark mode
- 10. Animations
- 11. Security
- 12. Server-backed edge mirrors
- QA scripts
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 /parentswith validuserId→ 200/201dataparent doc (parent.service.ts:29-47). -
Same
userIdagain → 409DUPLICATE_RESOURCE"Parent profile already exists for this user." (parent.service.ts:32-34). -
GET /parentspaginated: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/:idpartial update;userIdin body → silently ignored (no field inUpdateParentDto). -
DELETE /parents/:idsoft-delete: subsequent list/detail exclude it;isDeletedset (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/:studentIdcreates link withrelationship, 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
relationshipstring → 500 (schema enum, no DTO enum,link-parent.dto.ts:19-20) — client must only send enum values (OQ-6). -
GET /parents/link/student/:studentIdreturns 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-100vsstudent-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/studentsreturns 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/:idper 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,
Nnew. -
Relationship chips + primary badge announced; switcher
toggledsemantics. - 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/linkgate 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
primaryContainerdark 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/annualIncomeaccept numbers only — client coerces; note DTO has no type decorators (create-parent.dto.ts:18-34). -
pickupAllowedlink default true vspickupAuthorizationprofile 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).