diff --git a/tests/utils/groups.ts b/tests/utils/groups.ts index 8e648d28..51c904e7 100644 --- a/tests/utils/groups.ts +++ b/tests/utils/groups.ts @@ -1,31 +1,4 @@ -import { TEST_CONFIG } from "../config/test-env"; - -const ADMIN_HEADERS = { - "Content-Type": "application/json", - apikey: TEST_CONFIG.SUPABASE_SERVICE_ROLE_KEY, - Authorization: `Bearer ${TEST_CONFIG.SUPABASE_SERVICE_ROLE_KEY}`, -}; - -async function getUserIdByEmail(email: string): Promise { - const response = await fetch( - `${TEST_CONFIG.SUPABASE_URL}/rest/v1/profiles?email=eq.${encodeURIComponent(email)}&select=id`, - { headers: ADMIN_HEADERS }, - ); - - if (!response.ok) { - throw new Error( - `Failed to look up profile for ${email}: ${response.status}`, - ); - } - - const [profile] = (await response.json()) as { id: string }[]; - - if (!profile) { - throw new Error(`No profile found for ${email}`); - } - - return profile.id; -} +import { adminClient } from "./supabaseAdmin"; // Creates a group and adds the given user as its sole member, so // single-group auto-activation kicks in for them. @@ -35,38 +8,26 @@ export async function createGroupWithMember( ): Promise<{ groupId: string; groupName: string }> { const userId = await getUserIdByEmail(email); - const groupResponse = await fetch( - `${TEST_CONFIG.SUPABASE_URL}/rest/v1/groups`, - { - method: "POST", - headers: { ...ADMIN_HEADERS, Prefer: "return=representation" }, - body: JSON.stringify({ - name: groupName, - slug: groupName.toLowerCase().replace(/[^a-z0-9]+/g, "-"), - created_by: userId, - }), - }, - ); - - if (!groupResponse.ok) { - throw new Error(`Failed to create test group: ${groupResponse.status}`); + const { data: group, error: groupError } = await adminClient + .from("groups") + .insert({ + name: groupName, + slug: groupName.toLowerCase().replace(/[^a-z0-9]+/g, "-"), + created_by: userId, + }) + .select("id") + .single(); + + if (groupError) { + throw new Error(`Failed to create test group: ${groupError.message}`); } - const [group] = (await groupResponse.json()) as { id: string }[]; - - const memberResponse = await fetch( - `${TEST_CONFIG.SUPABASE_URL}/rest/v1/group_members`, - { - method: "POST", - headers: { ...ADMIN_HEADERS, Prefer: "return=minimal" }, - body: JSON.stringify({ group_id: group.id, user_id: userId }), - }, - ); + const { error: memberError } = await adminClient + .from("group_members") + .insert({ group_id: group.id, user_id: userId }); - if (!memberResponse.ok) { - throw new Error( - `Failed to add test group member: ${memberResponse.status}`, - ); + if (memberError) { + throw new Error(`Failed to add test group member: ${memberError.message}`); } return { groupId: group.id, groupName }; @@ -79,18 +40,29 @@ export async function addMemberToGroup( ): Promise { const userId = await getUserIdByEmail(email); - const memberResponse = await fetch( - `${TEST_CONFIG.SUPABASE_URL}/rest/v1/group_members`, - { - method: "POST", - headers: { ...ADMIN_HEADERS, Prefer: "return=minimal" }, - body: JSON.stringify({ group_id: groupId, user_id: userId }), - }, - ); + const { error } = await adminClient + .from("group_members") + .insert({ group_id: groupId, user_id: userId }); + + if (error) { + throw new Error(`Failed to add test group member: ${error.message}`); + } +} + +async function getUserIdByEmail(email: string): Promise { + const { data: profile, error } = await adminClient + .from("profiles") + .select("id") + .eq("email", email) + .maybeSingle(); + + if (error) { + throw new Error(`Failed to look up profile for ${email}: ${error.message}`); + } - if (!memberResponse.ok) { - throw new Error( - `Failed to add test group member: ${memberResponse.status}`, - ); + if (!profile) { + throw new Error(`No profile found for ${email}`); } + + return profile.id; } diff --git a/tests/utils/linkWizardArtist.ts b/tests/utils/linkWizardArtist.ts index bc705523..b72d4af8 100644 --- a/tests/utils/linkWizardArtist.ts +++ b/tests/utils/linkWizardArtist.ts @@ -1,11 +1,4 @@ -import { createClient } from "@supabase/supabase-js"; -import type { Database } from "../../src/integrations/supabase/types"; -import { TEST_CONFIG } from "../config/test-env"; - -const adminClient = createClient( - TEST_CONFIG.SUPABASE_URL, - TEST_CONFIG.SUPABASE_SERVICE_ROLE_KEY, -); +import { adminClient } from "./supabaseAdmin"; // Seeded via supabase/seed.sql: festival "test", edition "2025" ("Boom Festival 2025"), // stage "Club Stage". diff --git a/tests/utils/login.ts b/tests/utils/login.ts index f1b71b8b..6e9a2034 100644 --- a/tests/utils/login.ts +++ b/tests/utils/login.ts @@ -1,6 +1,7 @@ import { Page, expect } from "@playwright/test"; import { TEST_CONFIG } from "../config/test-env"; import { fetchOtpCode } from "./otp"; +import { adminClient } from "./supabaseAdmin"; // Signs in via the OTP flow, pre-onboarding the voter so onboarding never shows here. export async function signIn(page: Page, email = generateTestEmail()) { @@ -85,63 +86,46 @@ export function generateTestEmail( return `${TEST_CONFIG.TEST_USER_EMAIL_BASE}-${suffix}@${TEST_CONFIG.TEST_USER_EMAIL_DOMAIN}`; } -const ADMIN_HEADERS = { - "Content-Type": "application/json", - apikey: TEST_CONFIG.SUPABASE_SERVICE_ROLE_KEY, - Authorization: `Bearer ${TEST_CONFIG.SUPABASE_SERVICE_ROLE_KEY}`, -}; - // Pre-creates an already-onboarded voter via the admin API so OTP sign-in never shows onboarding. async function createPreOnboardedUser(email: string): Promise { const username = email.split("@")[0]; - const createResponse = await fetch( - `${TEST_CONFIG.SUPABASE_URL}/auth/v1/admin/users`, - { - method: "POST", - headers: ADMIN_HEADERS, - body: JSON.stringify({ - email, - email_confirm: true, - user_metadata: { username }, - }), - }, - ); - - if (!createResponse.ok) { + const { data, error: createError } = await adminClient.auth.admin.createUser({ + email, + email_confirm: true, + user_metadata: { username }, + }); + + if (createError) { throw new Error( - `Failed to pre-create onboarded test user ${email}: ${createResponse.status}`, + `Failed to pre-create onboarded test user ${email}: ${createError.message}`, ); } - const { id } = (await createResponse.json()) as { id: string }; + const { error: updateError } = await adminClient + .from("profiles") + .update({ completed_onboarding: true }) + .eq("id", data.user.id); - await fetch(`${TEST_CONFIG.SUPABASE_URL}/rest/v1/profiles?id=eq.${id}`, { - method: "PATCH", - headers: { ...ADMIN_HEADERS, Prefer: "return=minimal" }, - body: JSON.stringify({ completed_onboarding: true }), - }); + if (updateError) { + throw new Error( + `Failed to mark test user ${email} onboarded: ${updateError.message}`, + ); + } - return id; + return data.user.id; } async function grantAdminRole(userId: string): Promise { - const response = await fetch( - `${TEST_CONFIG.SUPABASE_URL}/rest/v1/admin_roles`, - { - method: "POST", - headers: { ...ADMIN_HEADERS, Prefer: "return=minimal" }, - body: JSON.stringify({ - user_id: userId, - role: "admin", - created_by: userId, - }), - }, - ); - - if (!response.ok) { + const { error } = await adminClient.from("admin_roles").insert({ + user_id: userId, + role: "admin", + created_by: userId, + }); + + if (error) { throw new Error( - `Failed to grant admin role to test user ${userId}: ${response.status} ${await response.text()}`, + `Failed to grant admin role to test user ${userId}: ${error.message}`, ); } } diff --git a/tests/utils/supabaseAdmin.ts b/tests/utils/supabaseAdmin.ts new file mode 100644 index 00000000..bf2cbb60 --- /dev/null +++ b/tests/utils/supabaseAdmin.ts @@ -0,0 +1,8 @@ +import { createClient } from "@supabase/supabase-js"; +import type { Database } from "../../src/integrations/supabase/types"; +import { TEST_CONFIG } from "../config/test-env"; + +export const adminClient = createClient( + TEST_CONFIG.SUPABASE_URL, + TEST_CONFIG.SUPABASE_SERVICE_ROLE_KEY, +);