Ctrl K
ComunidadGuías…

e2e/global-setup.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { chromium } from '@playwright/test';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import { mkdirSync, existsSync } from 'node:fs';

// Creates (or reuses) an authenticated session and saves it to .auth/admin.json
// for the authenticated projects. Idempotent: logs in if the account already
// exists, otherwise registers it first (registration auto-authenticates and the
// first user becomes admin).
//
// Env:
//   BASE_URL       target under test (default http://localhost:8095)
//   E2E_EMAIL      test account email    (default e2e-admin@actalog.local)
//   E2E_PASSWORD   test account password (default TestPass123!)
//   E2E_REGISTER   set to "false" to never register (use for prod: supply real creds)
export default async function globalSetup() {
  // Skip all auth setup — for running the anonymous render specs against a real
  // deployment (beta/prod) without creating accounts or spending rate-limit budget.
  if (process.env.E2E_SKIP_AUTH === '1') return;

  const BASE = process.env.BASE_URL || 'http://localhost:8095';
  const EMAIL = process.env.E2E_EMAIL || 'e2e-admin@actalog.local';
  const PASS = process.env.E2E_PASSWORD || 'TestPass123!';
  const allowRegister = process.env.E2E_REGISTER !== 'false';

  const dir = dirname(fileURLToPath(import.meta.url));
  const authDir = join(dir, '.auth');
  const statePath = join(authDir, 'admin.json');
  mkdirSync(authDir, { recursive: true });

  const browser = await chromium.launch();

  // The auth endpoints are rate-limited (5 requests / 15 min / IP). Reuse a
  // still-valid saved session so re-runs cost zero auth calls. Set E2E_FRESH_AUTH=1
  // to force a new login.
  if (existsSync(statePath) && process.env.E2E_FRESH_AUTH !== '1') {
    const ctx = await browser.newContext({ storageState: statePath });
    const page = await ctx.newPage();
    await page.goto(`${BASE}/dashboard`, { waitUntil: 'networkidle' }).catch(() => {});
    if (page.url().includes('/dashboard')) {
      await browser.close();
      return; // existing session still valid
    }
    await ctx.close();
  }

  const ctx = await browser.newContext();
  const page = await ctx.newPage();

  async function login() {
    await page.goto(`${BASE}/login`, { waitUntil: 'networkidle' });
    await page.getByLabel('Email').fill(EMAIL);
    await page.getByLabel('Password', { exact: true }).fill(PASS);
    await page.getByRole('button', { name: /sign in/i }).click();
    try {
      await page.waitForURL('**/dashboard', { timeout: 10_000 });
      return true;
    } catch {
      return false;
    }
  }

  let ok = await login();
  if (!ok && allowRegister) {
    await page.goto(`${BASE}/register`, { waitUntil: 'networkidle' });
    await page.getByLabel('Name').fill('E2E Admin');
    await page.getByLabel('Email').fill(EMAIL);
    await page.getByLabel('Password', { exact: true }).fill(PASS);
    await page.getByLabel('Confirm Password', { exact: true }).fill(PASS);
    await page.getByRole('button', { name: /sign up|register|create account/i }).click();
    // Register auto-authenticates AND shows an email hint; reset client state so
    // we get a clean, deterministic logged-in session via the login form.
    await page.waitForTimeout(1500);
    await ctx.clearCookies();
    await page.evaluate(() => { localStorage.clear(); sessionStorage.clear(); }).catch(() => {});
    ok = await login();
  }

  if (!ok) {
    await browser.close();
    throw new Error(
      `Could not authenticate against ${BASE} as ${EMAIL}. ` +
        `Set E2E_EMAIL/E2E_PASSWORD to a valid account (and E2E_REGISTER=false for prod).`
    );
  }

  await ctx.storageState({ path: join(authDir, 'admin.json') });
  await browser.close();
}