Progress Photos — QA Plan
1. Upload
| # | Scenario | Expected |
|---|---|---|
| 1.1 | Member uploads a portrait JPEG, ~3MB | 201; row inserted; thumbnail generated; presigned URL returns image |
| 1.2 | Member uploads a HEIC | If sharp handles HEIC (depends on build), 201; otherwise 500 — verify behavior |
| 1.3 | Member uploads a PDF | 400 — Progress photo must be an image |
| 1.4 | Upload arrives without prior staged-PUT | 404 from uploads.lookupStaged |
| 1.5 | Same uploadId posted twice | Second fails (already consumed) |
| 1.6 | Corrupt image bytes | sharp throws; 500; staged upload remains for janitor |
2. List
| # | Scenario | Expected |
|---|---|---|
| 2.1 | Member lists own with no params | Newest 50 returned; hasMore correct |
| 2.2 | Cursor pagination | Page 2 starts strictly older than page 1’s last createdAt |
| 2.3 | from/to date filter | Honors range |
| 2.4 | Soft-deleted row | Excluded |
| 2.5 | Presigned URLs work | Open in browser, image loads |
3. Staff access
| # | Scenario | Expected |
|---|---|---|
| 3.1 | Coach views member’s photos | 200; same list shape |
| 3.2 | Coach from another org tries | 404 (member not in org) |
| 3.3 | Coach lacking staff role (e.g. only member) | 403 |
4. Delete
| # | Scenario | Expected |
|---|---|---|
| 4.1 | Member deletes own | 200; deleted_at set |
| 4.2 | Member tries to delete another member’s photo | 403 |
| 4.3 | Staff tries DELETE /members/me/... against a member’s photo | 403 (route is self-scoped; staff has no delete-on-behalf path today) |
5. RTL UI
| # | Scenario | Expected |
|---|---|---|
| 5.1 | Member views gallery in he | Timeline reads right-to-left; date labels in Hebrew |
| 5.2 | Notes contain Hebrew | Renders correctly |
6. Privacy
| # | Scenario | Expected |
|---|---|---|
| 6.1 | Photo URL leaked to a third party | URL expires in 1h; subsequent fetch returns 403 from R2 |
| 6.2 | EXIF with GPS | Known gap: GPS coordinates persist in the binary in R2. Document for follow-up |
7. Smoke
- Upload from phone → coach sees in member detail.
- Thumbnail loads faster than the original (CDN cache OK).
- Delete then re-list excludes the row.