/** * Live login helper — runs the real Keycloak OAuth flow in the current context. * * We use this instead of `storageState` because Supabase JS v2's async * `_recoverAndRefresh` doesn't reliably re-fire `onAuthStateChange`/INITIAL_SESSION * when the browser context is built from a saved localStorage snapshot. Doing the * full login for each test adds ~2–3 seconds but produces deterministic state. */ import type { Page } from '@playwright/test'; import type { USERS } from './users.js'; export async function loginAs(page: Page, user: (typeof USERS)[keyof typeof USERS]): Promise { await page.goto('/'); await page.waitForURL(/\/realms\/colectivo\/protocol\/openid-connect\/auth/, { timeout: 15_000 }); await page.fill('#username', user.email); await page.fill('#password', user.password); await page.click('#kc-login'); // Wait until we're redirected OFF the callback page. The root layout's // post-login routing sends the user to /lists (or /onboarding) only after // the deferred loadUserCollectives call resolves, so we can't call the // login done until we've left /auth/callback. await page.waitForURL( (url) => url.origin === 'http://localhost:5173' && !url.pathname.startsWith('/auth/callback'), { timeout: 20_000 } ); await page.waitForFunction( () => Object.keys(window.localStorage).some( (k) => k.startsWith('sb-') && k.endsWith('-auth-token') ), null, { timeout: 15_000 } ); }