Research-Stack/4-Infrastructure/k3s-flake/tests/check-outpost.spec.ts
Brandon Schneider 9e80ac68ca feat(infra): Jellyfin wizard complete, SSO-Auth plugin files deployed
- Jellyfin setup wizard completed, admin account created (admin/jellyfin-admin)
- SSO-Auth plugin v4.0.0.3 downloaded and placed in plugins directory
- Authentik OIDC provider for Jellyfin updated with correct redirect URI
- All services verified running

Build: 3313 jobs, 0 errors (lake build Compiler)
2026-05-31 14:14:20 -05:00

77 lines
3.6 KiB
TypeScript

import { test, expect } from '@playwright/test';
test('Check and Configure Authentik Outpost', async ({ browser }) => {
const context = await browser.newContext();
const page = await context.newPage();
console.log('Navigating to Authentik admin outposts...');
await page.goto('https://auth.researchstack.info/if/admin/#/apps/outposts');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(4000);
// Robust login detection: check if "Log in" button or username field is visible
const loginInput = page.locator('input[placeholder*="Username"], input[name="uid"], input[type="text"]').first();
if (await loginInput.isVisible()) {
console.log('Login form detected. Logging in...');
await loginInput.fill('akadmin');
await page.screenshot({ path: 'authentik-login-step1.png' });
const continueBtn = page.locator('button:has-text("Log in"), button:has-text("Continue"), input[type="submit"]').first();
await continueBtn.click();
await page.waitForTimeout(2000);
const passwordInput = page.locator('input[name="password"], input[type="password"]').first();
await passwordInput.fill('authentik');
await page.screenshot({ path: 'authentik-login-step2.png' });
await continueBtn.click();
await page.waitForTimeout(6000);
console.log('Logged in. Current URL:', page.url());
}
// Double check we are on the outposts page
if (!page.url().includes('/apps/outposts')) {
console.log('Navigating to outposts page directly...');
await page.goto('https://auth.researchstack.info/if/admin/#/apps/outposts');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(4000);
}
await page.screenshot({ path: 'authentik-outposts-page.png' });
console.log('Outposts URL:', page.url());
// Wait, the page is built using web components, so finding elements might require waiting or shadow DOM piercing
// Let's dump all text on the page to see if "authentik Embedded Outpost" is visible
const pageText = await page.evaluate(() => document.body.innerText);
console.log('Outposts Page text:', pageText.slice(0, 1500));
// Let's find the edit button. In Authentik, it is often a button inside a table row.
// We can search for edit buttons and click the first one if there is only one outpost, or find one near "Embedded Outpost"
// Let's locate the edit button and click it
console.log('Looking for Edit button...');
const editBtn = page.locator('ak-table-row:has-text("authentik Embedded Outpost") button[title*="Edit"], button:has-text("Edit"), button[aria-label*="Edit"]').first();
if (await editBtn.isVisible()) {
console.log('Edit button is visible. Clicking...');
await editBtn.click();
await page.waitForTimeout(3000);
await page.screenshot({ path: 'authentik-outpost-edit-modal.png' });
// Let's see if we can find selected apps
const modalText = await page.evaluate(() => document.querySelector('div[role="dialog"], ak-modal-dialog')?.innerText || 'No modal');
console.log('Modal text:', modalText);
} else {
console.log('Edit button is NOT visible directly. Let us click on any edit button on the page.');
const anyEditBtn = page.locator('button[title*="Edit"], button:has-text("Edit")').first();
if (await anyEditBtn.isVisible()) {
await anyEditBtn.click();
await page.waitForTimeout(3000);
await page.screenshot({ path: 'authentik-outpost-edit-modal.png' });
} else {
console.log('Could not find any Edit button at all.');
}
}
await context.storageState({ path: 'auth-state.json' });
await context.close();
});