tests/e2e/neon-invite-session.spec.ts
Rama main · réplica de lectura del repositorio original.
import { randomUUID } from "node:crypto";
import { expect, test } from "@playwright/test";
import { Pool } from "pg";
import { buildE2EAuthHeaders } from "./helpers/auth";
// Explicit test DB only. Do not discover a production connection in .env.local.
const databaseUrl = process.env.DATABASE_URL;
test("Neon invitations use the current profile and preserve email-mismatch confirmation", async ({
page,
}) => {
test.skip(!databaseUrl, "An explicit DATABASE_URL test database is required");
const pool = new Pool({ connectionString: databaseUrl, max: 1 });
const profileId = randomUUID();
const teamId = randomUUID();
const inviteId = randomUUID();
const token = randomUUID();
const email = `invite-${profileId}@example.test`;
try {
await pool.query("insert into profiles (id, email) values ($1, $2)", [
profileId,
email,
]);
await pool.query(
"insert into teams (id, name, slug, owner_user_id) values ($1, 'Neon test team', $2, $3)",
// Keep the unique fixture slug within the schema's 39-character limit.
[teamId, `neon-${teamId.replaceAll("-", "")}`, profileId]
);
await pool.query(
"insert into team_invites (id, token, team_id, email, role) values ($1, $2, $3, $4, 'viewer')",
[inviteId, token, teamId, email]
);
await page.context().setExtraHTTPHeaders(buildE2EAuthHeaders(profileId));
await page.goto(`/invite/${token}`);
await expect(
page.getByRole("heading", { name: "Join Neon test team on Mogplex" })
).toBeVisible();
await expect(
page.getByRole("button", { name: "Accept invitation" })
).toBeEnabled();
await expect(page.getByRole("checkbox")).toHaveCount(0);
// Distinct auth and profile identities: the fixture has no Supabase auth
// user. Only the resolved profile id is allowed to select this email.
await pool.query(
"update team_invites set email = 'different@example.test' where id = $1",
[inviteId]
);
await page.reload();
await expect(
page.getByRole("button", { name: "Accept invitation" })
).toBeDisabled();
await expect(page.getByText(email, { exact: true })).toBeVisible();
await page.getByRole("checkbox").check();
await expect(
page.getByRole("button", { name: "Accept invitation" })
).toBeEnabled();
// No acceptance write: this test verifies rendering and identity only.
} finally {
await pool.query("delete from team_invites where id = $1", [inviteId]);
await pool.query("delete from teams where id = $1", [teamId]);
await pool.query("delete from profiles where id = $1", [profileId]);
await pool.end();
}
});