14 - QA Checklist (Transport Module)
- 1. Core flows (must pass)
- 2. Validation & conflicts (negative paths)
- 3. Integrity gaps (flag to backend - NOT server-enforced)
- 4. Soft-delete & reference integrity
- 5. Multi-tenancy
- 6. UI/UX (manual + golden)
- 7. E2E regression seeds (manual fixtures)
Module-specific quality gates on top of 00-shared/10 (QA baseline: performance budgets, offline matrix, a11y, motion, security). Every item is testable and maps to source.
1. Core flows (must pass)
| # | Scenario | Expectation | Source |
|---|---|---|---|
| 1.1 | Create vehicle -> appears in list | POST 201, doc in GET list, sorted by plateNumber | transport.controller.ts:30-40, transport.service.ts:71 |
| 1.2 | Create route with 3 stops -> detail shows order 1,2,3 | stops array round-trips {name, order} | create-route.dto.ts:34-39, route.schema.ts:23-24 |
| 1.3 | Assign student -> student assignments shows populated route | POST + GET /assignments/:studentId | transport.controller.ts:120-130, route-assignment.repository.ts:20-24 |
| 1.4 | Soft delete vehicle -> list excludes it | isDeleted: true, filter base.repository.ts:20-30, 68-74 | transport.service.ts:100 |
| 1.5 | Update driver -> PATCH applies partial fields only | untouched fields unchanged | update-driver.dto.ts:4, transport.service.ts:224-238 |
2. Validation & conflicts (negative paths)
| # | Scenario | Expectation | Source |
|---|---|---|---|
| 2.1 | Create vehicle with duplicate plateNumber | 409, message verbatim Vehicle "<plate>" already exists. | transport.service.ts:38-45; index vehicle.schema.ts:50 |
| 2.2 | Create route with duplicate name | 409 Route "<name>" already exists. | transport.service.ts:113-116; index route.schema.ts:44 |
| 2.3 | Create driver with duplicate licenseNumber | 409 Driver with license ... | transport.service.ts:177-184; index driver.schema.ts:50 |
| 2.4 | Create driver with duplicate phone | 409 Driver with phone ... | transport.service.ts:185-190; index driver.schema.ts:51 |
| 2.5 | Assign same (route, student) twice | 409 Student already assigned to this route. | transport.service.ts:252-258; index route-assignment.schema.ts:42-45 |
| 2.6 | capacity = 0 or negative | 400 (DTO @Min(1)) | create-vehicle.dto.ts:14-17 |
| 2.7 | shift not in morning/evening/both | 400 (IsEnum) | assign-route.dto.ts:13-15 |
| 2.8 | PATCH with invalid type value | 400 (enum) | update-vehicle.dto.ts:4 -> create-vehicle.dto.ts:19-21 |
| 2.9 | Unauthenticated call | 401 | transport.controller.ts:23-26 |
3. Integrity gaps (flag to backend - NOT server-enforced)
| # | Gap | Client mitigation | Source |
|---|---|---|---|
| 3.1 | Capacity overflow: assignStudent never checks route vehicle capacity vs. count of students | client pre-check warn + QA manual test; server check (planned) | transport.service.ts:251-266, vehicle.schema.ts:27-28 |
| 3.2 | Assign to inactive route / maintenance vehicle / inactive driver not blocked | client filters inactive options; server (planned) | route.schema.ts:32-33, vehicle.schema.ts:33-34, driver.schema.ts:30-31 |
| 3.3 | Duplicate plate race (no DB unique index? index exists: {tenantId, plateNumber} unique - race window only via concurrent create) | rely on 409; retry UX | vehicle.schema.ts:50 |
| 3.4 | Updating a vehicle's plateNumber to an existing one -> 409 only via unique index (service check is create-only) | expect 409 from index; surface verbatim | transport.service.ts:84-91, vehicle.schema.ts:50 |
| 3.5 | Driver licenseExpiry in the past accepted | client warn; server (planned) | create-driver.dto.ts:27-29 |
4. Soft-delete & reference integrity
| # | Scenario | Expectation | Source |
|---|---|---|---|
| 4.1 | Delete vehicle referenced by a route | 409 Vehicle is assigned to a route. | transport.service.ts:94-99 |
| 4.2 | Delete driver referenced by a route | 409 Driver is assigned to a route. | transport.service.ts:241-246 |
| 4.3 | Delete route with active assignments | 409 Route has active student assignments. | transport.service.ts:168-171 |
| 4.4 | Delete already-deleted entity | 404 (scoped filter excludes deleted) | transport.service.ts:101, 173, 248, 290, base.repository.ts:20-30 |
| 4.5 | Delete assignment -> removed from student list | GET reflects | transport.service.ts:288-291 |
5. Multi-tenancy
| # | Scenario | Expectation | Source |
|---|---|---|---|
| 5.1 | Tenant B queries vehicles | sees only B's rows | base.repository.ts:20-30 |
| 5.2 | Cross-tenant duplicate plate allowed | yes - uniqueness is per tenant | vehicle.schema.ts:50 |
| 5.3 | tenantId from request body ignored | server never reads it from body | base.repository.ts:32-36, AGENTS.md |
6. UI/UX (manual + golden)
| # | Check |
|---|---|
| 6.1 | Pagination boundaries: page 1 Prev disabled; last page Next disabled (meta hasNext/hasPrevious) |
| 6.2 | 409 inline errors focus the offending field |
| 6.3 | Delete 409 dialog offers "View related" navigation |
| 6.4 | Stop reorder persists after save + reload |
| 6.5 | Offline: lists render cached + banner; mutations blocked (00-shared/10 §2) |
| 6.6 | Empty states for all 4 lists (vehicles/drivers/routes/assignments) |
| 6.7 | Permission gating: read-only role sees no FAB/menu; 403 copy on direct route |
| 6.8 | a11y: badges have semantics labels; dialogs trap focus (00-shared/09) |
| 6.9 | Skeleton < 200 ms, content < 2 s on network (00-shared/10 §1) |
7. E2E regression seeds (manual fixtures)
- 2 tenants with identical plate numbers (proves isolation, 5.2).
- Route with 20 stops (editor cap), 3 assignments on one route.
- One vehicle in
maintenance, one driveron_leave, one routeinactive. - Deleted vehicle referenced by a soft-deleted route (delete guard must still 409 while route visible to admin).