mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
Say what the level means on both screens that decide it
The invitation form gains the choice, and the option labels say what actually ships rather than the word "write": a delegate can add readings, results, observations, a medication and a marked dose, and can edit or delete nothing, including what they entered a moment ago. That gap between what "write access" sounds like and what it does is where a support case lives, so it is on the card rather than in a reply. The delegate reads the same thing before they accept. A pending write invitation states its level and one sentence about what accepting means, on the screen where they accept it, because acceptance is where the two consents meet and it happens once. Ending an access says what stays: the entries remain and the owner can remove any of them, and the activity view keeps saying who entered what for as long as the instance's audit window reaches. That number comes from the server, so an instance running ninety days says ninety, and a browser that has not been told says nothing rather than a made-up year. The browser journey now invites at the wider level and reads the posted body for it. That is the only check in the tree that can: the component convention is server-rendered only, so no test under src/ runs the form's submit path, and every one of them stays green with the control wired to a constant.
This commit is contained in:
1 parent
533400ce60
commit
d82e29737b
13 files changed
+451
-7
No files matched your search
@@ -208,6 +208,21 @@ test.describe("account sharing", () => {
|
||||
const chosenDay = isoDayFromNow(30);
|
||||
await lapse.fill(chosenDay);
|
||||
|
||||
// The level, through the real control and onto the real wire.
|
||||
//
|
||||
// Same class of gap as the lapse date above, and the reason it is checked
|
||||
// here rather than in a component test is worth stating: the project's
|
||||
// component convention is SSR-only, so no test under `src/` can run this
|
||||
// form's submit path at all. Wire the radio back to a constant and every
|
||||
// one of those stays green. Only the posted body can tell the level a
|
||||
// person picked from the level the card sends.
|
||||
const writeOption = ownerPage.locator(
|
||||
'[data-slot="grant-invite-access-option"][data-access="WRITE"]',
|
||||
);
|
||||
await expect(writeOption).toBeVisible();
|
||||
await writeOption.click();
|
||||
await expect(writeOption).toHaveAttribute("data-selected", "true");
|
||||
|
||||
const invitePost = ownerPage.waitForRequest(
|
||||
(req) =>
|
||||
req.method() === "POST" && req.url().endsWith("/api/account/grants"),
|
||||
@@ -215,6 +230,7 @@ test.describe("account sharing", () => {
|
||||
await submit.click();
|
||||
const posted = JSON.parse((await invitePost).postData() ?? "{}") as {
|
||||
expiresAt?: string | null;
|
||||
access?: string;
|
||||
};
|
||||
expect(
|
||||
posted.expiresAt,
|
||||
@@ -222,6 +238,10 @@ test.describe("account sharing", () => {
|
||||
).toBeTruthy();
|
||||
// End of the chosen day, not the midnight that starts it.
|
||||
expect(posted.expiresAt).toContain(chosenDay.slice(0, 8));
|
||||
expect(
|
||||
posted.access,
|
||||
"the invitation must carry the level the owner chose",
|
||||
).toBe("WRITE");
|
||||
|
||||
const row = ownerPage
|
||||
.locator('[data-slot="grants-given-list"] [data-slot="grant-row"]')
|
||||
@@ -229,6 +249,9 @@ test.describe("account sharing", () => {
|
||||
await expect(row).toBeVisible();
|
||||
// Pending, not active. The state is the server's answer, rendered.
|
||||
await expect(row).toHaveAttribute("data-grant-state", "PENDING");
|
||||
// And the level came back from the database on the list read, which is the
|
||||
// far end of the same wire: form → POST → row → GET → attribute.
|
||||
await expect(row).toHaveAttribute("data-grant-access", "WRITE");
|
||||
});
|
||||
|
||||
test("the delegate is offered nothing until they accept", async ({
|
||||
@@ -241,6 +264,12 @@ test.describe("account sharing", () => {
|
||||
.first();
|
||||
await expect(row).toBeVisible();
|
||||
await expect(row).toHaveAttribute("data-grant-state", "PENDING");
|
||||
// The delegate's half of the consent: what they are being offered, and
|
||||
// what accepting it will mean, on the screen where they accept it.
|
||||
await expect(row).toHaveAttribute("data-grant-access", "WRITE");
|
||||
await expect(
|
||||
row.locator('[data-slot="grant-write-consent"]'),
|
||||
).toBeVisible();
|
||||
|
||||
// No switcher yet: `accountAccess.canSwitch` is false while the only
|
||||
// grant is pending, and the menu binds that boolean.
|
||||
|
||||
Reference in new issue
Block a user