Research-Stack/4-Infrastructure/k3s-flake/tests/homarr-verify.spec.ts
2026-06-29 16:21:47 -05:00

118 lines
4.6 KiB
TypeScript

import { test, expect } from '@playwright/test';
test('Verify Homarr configured apps via SSO', async ({ page }) => {
test.setTimeout(60000);
console.log('Navigating to Homarr via domain...');
await page.goto('https://researchstack.info/', { timeout: 20000, waitUntil: 'domcontentloaded' });
await page.waitForTimeout(5000);
console.log('Current URL:', page.url());
await page.screenshot({ path: '/tmp/homarr-verify-1.png' });
// Check if we are on the Authentik login page
if (page.url().includes('auth.researchstack.info')) {
console.log('Authentik login detected. Step 1: Entering username...');
// Fill username
const usernameInput = page.locator('input[name="username"], input[type="text"]').first();
await usernameInput.fill('allaun');
// Click submit for username
const submitBtn1 = page.locator('button:has-text("Continue"), button:has-text("Log in"), button[type="submit"]').first();
await submitBtn1.click();
await page.waitForTimeout(3000);
console.log('Step 2: Entering password...');
// Fill password
const passwordInput = page.locator('input[name="password"], input[type="password"]').first();
await passwordInput.fill('Silverkitten14');
// Click submit for password
const submitBtn2 = page.locator('button:has-text("Continue"), button:has-text("Log in"), button[type="submit"]').first();
await submitBtn2.click();
await page.waitForTimeout(6000);
console.log('After login URL:', page.url());
await page.screenshot({ path: '/tmp/homarr-verify-2.png' });
}
// Handle Authentik consent/authorization screen if present
if (page.url().includes('consent') || page.url().includes('authorize')) {
console.log('Consent/Authorization screen detected. Clicking continue...');
const continueBtn = page.locator('button:has-text("Continue"), input[type="submit"], button[type="submit"]').first();
if (await continueBtn.isVisible()) {
await continueBtn.click();
await page.waitForTimeout(6000);
console.log('After consent URL:', page.url());
await page.screenshot({ path: '/tmp/homarr-verify-3.png' });
}
}
// Force NextAuth OIDC authentication by navigating to the login URL
console.log('Navigating directly to /auth/login to trigger OIDC session sync...');
await page.goto('https://researchstack.info/auth/login');
await page.waitForTimeout(6000);
// If Authentik consent/authorization screen appears after navigating to login
if (page.url().includes('consent') || page.url().includes('authorize') || page.url().includes('application/o/authorize')) {
console.log('Consent/Authorization screen detected. Clicking continue...');
const continueBtn = page.locator('button:has-text("Continue"), input[type="submit"], button[type="submit"]').first();
if (await continueBtn.isVisible({ timeout: 5000 }).catch(() => false)) {
await continueBtn.click();
await page.waitForTimeout(6000);
}
}
// Navigate back to the home board
console.log('Navigating back to home board...');
await page.goto('https://researchstack.info/');
await page.waitForTimeout(6000);
const title = await page.title();
console.log('Final Page Title:', title);
console.log('Final URL:', page.url());
await page.screenshot({ path: '/tmp/homarr-verify-final.png' });
// Extract all text content
const content = await page.evaluate(() => document.body.innerText);
console.log('Page text snapshot:');
console.log(content.slice(0, 1000));
// Find all links (a tags) and their href/text
const links = await page.evaluate(() => {
return Array.from(document.querySelectorAll('a')).map(a => ({
text: a.textContent?.trim(),
href: a.getAttribute('href')
}));
});
console.log('Links found in DOM:', JSON.stringify(links, null, 2));
// Check if any element has class grid-layout or board
const classes = await page.evaluate(() => {
return Array.from(document.querySelectorAll('div')).slice(0, 50).map(div => ({
class: div.getAttribute('class'),
id: div.getAttribute('id')
})).filter(x => x.class || x.id);
});
console.log('Top divs found:', JSON.stringify(classes, null, 2));
// Verify that our subdomains/apps are visible on the dashboard
const expectedApps = [
'Authentik',
'Navidrome',
'Audiobookshelf',
'Uptime Kuma',
'Credential Vault',
'Chat (Hermes)',
'Music Files',
'Music Player'
];
console.log('Verifying expected apps presence:');
for (const app of expectedApps) {
const isPresent = content.includes(app);
console.log(`- ${app}: ${isPresent ? 'PRESENT' : 'MISSING'}`);
expect(isPresent).toBe(true);
}
});