From 665f223dc474abf09a706606f261532ef2624bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 6 Aug 2026 02:29:55 +0200 Subject: [PATCH] test: cover managed profile Guardian consent - Pin ordinary second-Guardian acceptance\n- Pin non-expiring accepted Guardian grants --- .../managed-profile-contract.test.ts | 10 +++- .../managed-profile-lifecycle.test.ts | 53 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/__tests__/managed-profile-contract.test.ts b/src/__tests__/managed-profile-contract.test.ts index 67ef25d37..a925ecf84 100644 --- a/src/__tests__/managed-profile-contract.test.ts +++ b/src/__tests__/managed-profile-contract.test.ts @@ -1,4 +1,4 @@ -import { readFile } from "node:fs/promises"; +import { readFile, readdir } from "node:fs/promises"; import path from "node:path"; import { describe, expect, it } from "vitest"; @@ -22,5 +22,13 @@ describe("managed-profile contract", () => { ); expect(source.toLowerCase()).not.toContain("emancipation"); + + const routes = await readdir( + path.join(root, "src/app/api/managed-profiles"), + { recursive: true }, + ); + expect( + routes.some((entry) => entry.toLowerCase().includes("emancip")), + ).toBe(false); }); }); diff --git a/tests/integration/managed-profile-lifecycle.test.ts b/tests/integration/managed-profile-lifecycle.test.ts index ad3071d87..cd2f47ff1 100644 --- a/tests/integration/managed-profile-lifecycle.test.ts +++ b/tests/integration/managed-profile-lifecycle.test.ts @@ -3,6 +3,12 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { cookieJar, headerJar } from "./mock-next-headers"; import { getPrismaClient, truncateAllTables } from "./setup"; +import { createManagedProfile } from "@/lib/managed-profiles/create"; +import { + acceptGrant, + findActiveGrant, + inviteGrant, +} from "@/lib/sharing/grants"; vi.mock("next/headers", async () => { const { cookieJar, headerJar } = await import("./mock-next-headers"); @@ -52,6 +58,16 @@ async function signInWithFreshMfa() { return guardian; } +async function makeAdult(label: string) { + const suffix = sequence++; + return getPrismaClient().user.create({ + data: { + username: `${label}-${suffix}`, + email: `${label}-${suffix}@example.test`, + }, + }); +} + function createRequest(body: unknown): NextRequest { return new NextRequest("http://localhost/api/managed-profiles", { method: "POST", @@ -157,4 +173,41 @@ describe("managed profile lifecycle (real Postgres)", () => { ).toBe(0); expect(await prisma.accountGrant.count()).toBe(0); }); + + it("second Guardian accepts through the ordinary invitation and does not expire", async () => { + const creator = await signInWithFreshMfa(); + const secondGuardian = await makeAdult("second-guardian"); + const { profile } = await createManagedProfile({ + creatorId: creator.id, + displayName: "Managed profile", + dateOfBirth: null, + locale: "en", + timezone: "UTC", + }); + const invitationExpiry = new Date(Date.now() + 60 * 60 * 1000); + + const invitation = await inviteGrant({ + grantorId: profile.id, + granteeId: secondGuardian.id, + access: "MANAGE", + scope: null, + expiresAt: invitationExpiry, + }); + expect(invitation.acceptedAt).toBeNull(); + expect(invitation.expiresAt).toEqual(invitationExpiry); + + const accepted = await acceptGrant({ + grantId: invitation.id, + granteeId: secondGuardian.id, + }); + expect(accepted.acceptedAt).not.toBeNull(); + expect(accepted.expiresAt).toBeNull(); + expect( + await findActiveGrant( + { grantorId: profile.id, granteeId: secondGuardian.id }, + getPrismaClient(), + new Date(Date.now() + 24 * 60 * 60 * 1000), + ), + ).not.toBeNull(); + }); });