Files
headlamp-polaris-plugin/e2e/auth.setup.ts
T
Chris Farhood 186f9ef380 feat: add Playwright E2E smoke tests and fix empty namespace crash
Fix getNamespaces() to skip cluster-scoped resources (Namespace: "")
that caused Router.createRouteURL to throw TypeError on the Namespaces
page. Add Playwright E2E smoke tests with Authentik OIDC auth for CI
and K8s token fallback for local dev. Add Gitea Actions E2E workflow,
vitest unit test infrastructure, and test-utils fixtures.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-07 18:53:40 -05:00

68 lines
2.4 KiB
TypeScript

import { test as setup, expect, Page } from '@playwright/test';
const AUTH_STATE_PATH = 'e2e/.auth/state.json';
async function authenticateWithOIDC(page: Page, username: string, password: string): Promise<void> {
// Navigate to login — Headlamp redirects / to /c/main/login
await page.goto('/');
await page.waitForURL('**/login');
// Click "Sign In" and capture the Authentik popup
const popupPromise = page.waitForEvent('popup');
await page.getByRole('button', { name: /sign in/i }).click();
const popup = await popupPromise;
// Authentik step 1: fill username
await popup.getByRole('textbox', { name: /email or username/i }).fill(username);
await popup.getByRole('button', { name: /log in/i }).click();
// Authentik step 2: fill password
await popup.getByRole('textbox', { name: /password/i }).fill(password);
await popup.getByRole('button', { name: /continue|log in/i }).click();
// Wait for the popup to close (Authentik redirects back, Headlamp processes callback)
await popup.waitForEvent('close', { timeout: 15_000 });
// Original page should now be authenticated — wait for sidebar
await expect(page.getByRole('navigation', { name: 'Navigation' })).toBeVisible({
timeout: 15_000,
});
}
async function authenticateWithToken(page: Page, token: string): Promise<void> {
// Navigate to login — Headlamp redirects / to /c/main/login
await page.goto('/');
await page.waitForURL('**/login');
// Click the token auth option
await page.getByRole('button', { name: /use a token/i }).click();
await page.waitForURL('**/token');
// Fill the "ID token" field and submit
await page.getByRole('textbox', { name: /id token/i }).fill(token);
await page.getByRole('button', { name: /authenticate/i }).click();
// Wait for the main UI to load
await expect(page.getByRole('navigation', { name: 'Navigation' })).toBeVisible({
timeout: 15_000,
});
}
setup('authenticate with Headlamp', async ({ page }) => {
const username = process.env.AUTHENTIK_USERNAME;
const password = process.env.AUTHENTIK_PASSWORD;
const token = process.env.HEADLAMP_TOKEN;
if (username && password) {
await authenticateWithOIDC(page, username, password);
} else if (token) {
await authenticateWithToken(page, token);
} else {
throw new Error(
'Set AUTHENTIK_USERNAME + AUTHENTIK_PASSWORD for OIDC auth, or HEADLAMP_TOKEN for token auth'
);
}
await page.context().storageState({ path: AUTH_STATE_PATH });
});