/** * Auth helper for Playwright e2e tests. * * Logs in via the actual UI (rather than minting a JWT directly) for two * reasons: * 1. The CC keeps the access token in memory + uses an httpOnly refresh * cookie. The cleanest way to exercise that flow is the real form. * 2. It tests the login page implicitly — if the form breaks, every * downstream test fails fast and obviously. * * If/when login becomes the bottleneck, swap this for a fixture that calls * `POST /internal/auth/login` once per worker and replays the cookie via * `context.addCookies(...)`. */ import { expect } from '@playwright/test' const TEST_EMAIL = process.env.CC_TEST_EMAIL || 'test-operator@example.com' const TEST_PASSWORD = process.env.CC_TEST_PASSWORD || 'changeme' /** * Navigates to /login, fills the form, submits, and waits for the post-login * redirect (defaults to /dashboard via App.jsx Navigate). * * @param {import('@playwright/test').Page} page * @param {{ email?: string, password?: string }} [overrides] */ export async function loginAsOperator(page, overrides = {}) { const email = overrides.email ?? TEST_EMAIL const password = overrides.password ?? TEST_PASSWORD await page.goto('/login') await page.getByLabel('Email').fill(email) await page.getByLabel('Password').fill(password) await page.getByRole('button', { name: /Masuk/i }).click() // App.jsx redirects authenticated users from `/` to `/dashboard`. // Wait for the URL to leave /login as the success signal. await page.waitForURL((url) => !url.pathname.startsWith('/login'), { timeout: 10_000, }) } /** * Convenience: assert the current page is a logged-in CC page (i.e. NOT * /login). Useful as a sanity-check at the top of a test. * * @param {import('@playwright/test').Page} page */ export async function expectLoggedIn(page) { await expect(page).not.toHaveURL(/\/login/) }