mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 05:42:19 +00:00
feat(api): publish the resolved notification preferences on the account payload
The medication detail's notification section decides between the server-side reminder switch and the client-managed chip on `notificationPrefs.medication.clientManaged`, read off `GET /api/auth/me`. That payload never carried the field — the preferences live on their own endpoint, which is not on the app-boot path — so the flag was `undefined` for every account: the chip never rendered, and a person whose phone owns the reminders was shown a switch that no longer decides anything. The write path and the dispatch gate were correct the whole time; only the web reflection was missing its end. The payload now carries the fully-resolved block from the same resolver the dedicated endpoint uses, so the two cannot disagree, and an account that never opted in reads `false` rather than absent. No extra query: the session already loads the row the column sits on. The pair guard over this payload gained the direction that could not see it. It asked that every published field has a reader; a reader with no field was invisible. It now also reads the response types clients declare for this endpoint and holds them against what the route publishes. A typed guard was tried first and does not work here — each consumer declares its own local interface, so the compiler checks every file against its own private claim and agrees with all of them.
This commit is contained in:
1 parent
f3321b8031
commit
fd6fa18913
5 files changed
+138
-21
No files matched your search
@@ -543,27 +543,18 @@ test.describe("notification preferences drive the dispatch decision", () => {
|
||||
expect(smtp.accepted()).toEqual([EMAIL_RECIPIENT]);
|
||||
});
|
||||
|
||||
/**
|
||||
* The web reflection of the opt-in, and the reason it is a test rather than a
|
||||
* screenshot: the section reads `notificationPrefs.medication.clientManaged`
|
||||
* off `/api/auth/me`, and that payload did not publish it until this branch.
|
||||
* The flag was `undefined` for every account, so the chip never rendered and
|
||||
* a person whose phone owned the reminders was shown a server-side switch
|
||||
* that decided nothing. Both halves are asserted — the chip appears AND the
|
||||
* switch row is gone — because either one alone passes on the wrong render.
|
||||
*/
|
||||
test("the client-managed opt-in is visible on the medication it silences", async ({
|
||||
page,
|
||||
}) => {
|
||||
test.skip(
|
||||
true,
|
||||
"The chip exists and is unreachable. " +
|
||||
"`src/components/medications/sections/notifications-section.tsx` " +
|
||||
"decides between the reminder switch and the client-managed chip on " +
|
||||
"`notificationPrefs.medication.clientManaged` read out of " +
|
||||
"`/api/auth/me` — a field that payload does not carry (the prefs live " +
|
||||
"on `/api/auth/me/notification-prefs`). So the flag reads as false for " +
|
||||
"every account, the chip never renders, and a person whose phone owns " +
|
||||
"the reminders is shown a server-side switch that no longer decides " +
|
||||
"anything. The write path and the dispatch decision are correct — the " +
|
||||
"two tests above prove both — only the web reflection is missing its " +
|
||||
"end. The account-payload guard cannot see this: it asks that every " +
|
||||
"field in the payload has a reader, and this is a reader with no " +
|
||||
"field. Kept at full strength rather than relaxed to match today's " +
|
||||
"render.",
|
||||
);
|
||||
|
||||
await configureChannels(page);
|
||||
await pinAccountClockToMidday(page);
|
||||
const medicationId = await createOverdueMedication(page);
|
||||
|
||||
Reference in new issue
Block a user