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

Feature-level QA for the Rooms module, derived from the implemented backend (src/modules/rooms/**) and the design docs 01–13. Server gaps are marked (planned); tests that would fail today are marked KNOWN-GAP. Baseline: 00-shared/10 (QA Baseline), 00-shared/09 (Accessibility).


1. CRUD — create (E1)

#CheckExpectedSource
1.1POST with valid full payload201, doc with injected tenantId, defaults applied (type=classroom, isDeleted=false, version=0)rooms.service.ts:18-23; room.schema.ts:27-28; base.repository.ts:32-36
1.2POST missing name400 VALIDATION_ERRORcreate-room.dto.ts:12-14
1.3POST missing code400create-room.dto.ts:16-18
1.4POST duplicate code in same tenant409 "Room code "X" already exists."rooms.service.ts:19-21
1.5POST same code in different tenant201 (per-tenant uniqueness)room.schema.ts:38 ({tenantId, code} index)
1.6POST invalid type400 (enum)create-room.dto.ts:25-28
1.7POST capacity: 0 / -5 / 2.5KNOWN-GAP: accepted (no bounds — OQ-7); client blocks <1 (proposed); server @Min(1) (planned)create-room.dto.ts:20-23
1.8POST body includes tenantId/isDeletedignored — overridden by context/scope (never trust body)base.repository.ts:32-36
1.9POST without JWT401rooms.controller.ts:19

2. CRUD — list (E2)

#CheckExpectedSource
2.1GET with defaults200, data ≤ 20, meta {page:1,limit:20,totalItems,totalPages,hasNext,hasPrevious}rooms.controller.ts:32; rooms.service.ts:29-33; pagination-query.dto.ts:32-39
2.2page=2, limit=10correct slice; hasNext reflects remainderrooms.service.ts:29-32
2.3page=0 / negativeKNOWN-GAP: no DTO validation on this route — raw Number() cast (rooms.controller.ts:32-33); page=0skip=-10 (Mongoose clamps, but contract unguarded). Shared DTO caps 1–100, not applied here (OQ-3). Server validation (planned)rooms.controller.ts:32-33; pagination-query.dto.ts:5-19
2.4sort / q paramsKNOWN-GAP: ignored — list is Mongo natural order (OQ-3)rooms.controller.ts:32
2.5Deleted rooms in listexcluded (isDeleted:false scope)base.repository.ts:20-30
2.6Cross-tenant rowsnever visible (tenant scope)base.repository.ts:24-29
2.7Empty tenant200, data: [], totalItems: 0rooms.service.ts:29-33

3. CRUD — get (E3)

#CheckExpectedSource
3.1Existing id200 full docrooms.service.ts:36-40
3.2Unknown / soft-deleted id404 "Room not found."rooms.service.ts:38; base.repository.ts:20-30
3.3Other tenant's id404 (no leak)base.repository.ts:24-29
3.4Malformed id (not ObjectId)400 VALIDATION_ERRORshared CastError filter

4. CRUD — update (E4)

#CheckExpectedSource
4.1PATCH full valid body200 updated doc, version +1base.repository.ts:57-66
4.2PATCH partial body (only building)KNOWN-GAP: 400 — CreateRoomDto requires name+code on PATCH (OQ-6, rooms.controller.ts:44); true partial DTO (planned)rooms.controller.ts:44
4.3PATCH code → existing codeKNOWN-GAP: 500 (E11000) — no service pre-check (OQ-1); 409 (planned)rooms.service.ts:42-46; room.schema.ts:38
4.4PATCH unknown id404rooms.service.ts:44
4.5PATCH type invalid400create-room.dto.ts:25-28
4.6Update reflection in list/detailfresh GET shows change (no stale cache server-side)base.repository.ts:57-66

5. CRUD — delete (E5)

#CheckExpectedSource
5.1DELETE existing200, no payload; doc isDeleted=true, deletedAt set, version +1rooms.service.ts:48-51; base.repository.ts:68-74
5.2GET after delete404 (soft-deleted hidden)base.repository.ts:20-30
5.3DELETE twicesecond → 404rooms.service.ts:50
5.4DELETE unknown / other-tenant id404rooms.service.ts:50; base.repository.ts:24-29
5.5DELETE room referenced by timetable/bookingKNOWN-GAP: succeeds — no in-use guard (OQ-4); guard (planned)rooms.service.ts:48-51
5.6Re-create same code after delete201 (unique index only blocks live docs; isDeleted doc remains)room.schema.ts:38; base.repository.ts:20-30

6. Duplicates (create-path contract)

#CheckExpected
6.1Same code, same tenant, different case (LAB-02 vs lab-02)KNOWN-GAP: both persist — index is case-sensitive; client uppercases (proposed); normalized index (planned) (OQ-5/1)
6.2Trimmed equality (" A-1 " vs "A-1")both persist (trim happens at write: room.schema.ts:21-22 — DB stores trimmed; two docs only if created pre-trim) — verify via API

7. Capacity validation

#CheckExpected
7.1Client input < 1blocked with hint (proposed) (OQ-7)
7.2Client non-numericblocked via numeric keyboard + regex (proposed)
7.3Server accepts negative todayKNOWN-GAP (documented; @Min(1) (planned))
7.4Absent capacityno badge shown; never "Cap 0"

8. Permission & isolation

#CheckExpected
8.1rooms.read/create/update/delete present in permission catalogyes — permissions.constants.ts:50-53
8.2Server enforces themKNOWN-GAP: only JwtAuthGuard (OQ-2, rooms.controller.ts:19); RBAC guard (planned)
8.3Client hides create/edit/delete without permsyes (proposed) — per 12's client contract
8.4Tenant isolation on all 5 endpointsstructural (scope in base.repository.ts:20-30) — test with two tenants
8.5Platform admin scope bypassintentional (base.repository.ts:21-23) — platform-only tooling

9. UX / offline / edge

#CheckExpected
9.1Infinite scroll dedupeno duplicate rows across pages (dedupe by _id)
9.2Pull-to-refresh bypasses cachefresh page=1
9.3Offline listcached rows + banner; load-more blocked
9.4Offline submitblocked + draft kept
9.5404 on detail"Room not found" state, not generic error
9.6Empty list"No rooms yet" + create CTA (gated)
9.7Filter no-match"No rooms match your filters" + clear
9.8Delete typed-confirm mismatchbutton disabled until exact name match
9.9Discard dirty formconfirm dialog; no silent data loss

10. Accessibility (spot; full baseline 00-shared/09)

#Check
10.1RoomCard single semantics label; chips labeled
10.2Field errors in live regions; focus first invalid
10.3Contrast on chips/badges ≥ 4.5:1; touch targets ≥ 44 dp
10.4disableAnimations honored (no essential motion)

11. Performance (budgets 00-shared/10 §1)

#CheckTarget
11.1List p95 (server)< 300 ms (find + count on indexed scope)
11.2Detail p95< 250 ms
11.3Infinite scroll jankno layout jank; ListView.builder
11.4Debouncessearch + code-hint 300 ms

12. Regression suite (minimum)

  • Unit: RoomsService — dup create (409), 404s (findById/update/remove), pagination math (buildPaginationMetapagination-query.dto.ts:41-54).
  • E2E: create → list → get → update → delete → get(404) → list excludes; two-tenant isolation; duplicate code 409.
  • Widget (proposed): list load/empty/error, editor 409 inline, delete typed-confirm, permission-gated FAB.