PR #7335 — the profile-photo round trip
Upload → card + rail → another page → popover → Remove, driven through the real file input against the branch's own dev server, with the DOM checks each capture had to pass. Companion to pr-7335-account-settings-photo. PR: PropFlow-Technologies/propflowai#7335.
Before the upload
The smoke account has no photo: the Profile card and the rail both draw initials, the Photo row offers Upload photo only. This is also exactly what every existing account sees the day this ships — nothing changes until someone chooses a picture.
DOM checks this capture had to pass (4/4)
- title is Account Settings
- Photo row present
- no Remove before an upload
- rail shows initials
Upload — the card and the rail change together, no reload
A 900×600 two-tone PNG went through the real <input type=file>. The route normalised it to a 256×256 WebP (checked by fetching the served URL and reading its metadata), pointed the User row at it, and answered with the per-upload URL. The card re-rendered from that answer; the rail re-read /api/auth/me on the propflow:me-updated event and drew the same URL. Change photo and Remove replace Upload photo.
DOM checks this capture had to pass (6/6)
- toast says Photo updated
- card draws an image from /api/users/…/avatar?v=
- rail draws the SAME image without a reload
- Change photo + Remove now offered
- served object is a 256×256 WebP
- served with a day of private caching
Another page — the photo is on the row, not in page state
Navigating to Admin Settings, the rail's first read of /api/auth/me already carries the photo: it persisted on User.avatarKey, not in the account page's memory.
DOM checks this capture had to pass (2/2)
- Admin Settings page
- rail shows the photo here too
The ⋯ popover trigger is the same component
Open, the popover shows the account row (the way to Account Settings since #7324); the trigger behind it keeps drawing the photo — the rail's two tiers and the account page share one UserAvatar.
DOM checks this capture had to pass (2/2)
- popover open with the account row
- trigger still draws the photo
Remove — back to initials, and the old URL is gone
The pointer is cleared, the object deleted; the rail falls back in the same tab and the previous photo URL now answers 404 (briefly cached, so a thread with many of this person's messages costs one request). The smoke account is left exactly as it was found.
DOM checks this capture had to pass (4/4)
- toast says Photo removed
- card back to Upload photo, no Remove
- rail back to initials without a reload
- old photo URL is gone (404)