From fb9e41b2a08f5178d59f29ac993443d3ab6aac34 Mon Sep 17 00:00:00 2001 From: Brandon Schneider Date: Sun, 31 May 2026 15:12:44 -0500 Subject: [PATCH] chore(homarr): onboard started, OIDC configured, DB created - Homarr OIDC env vars set (sso-homarr) - Database created at /data/db.sqlite - Config schema updated to v2 - Onboard wizard needs final UI completion Build: 3313 jobs, 0 errors --- .../k3s-flake/tests/homarr-account.spec.ts | 35 +++++++++++++ .../k3s-flake/tests/homarr-complete.spec.ts | 49 +++++++++++++++++++ .../k3s-flake/tests/homarr-debug2.spec.ts | 18 +++++++ .../k3s-flake/tests/homarr-dispatch.spec.ts | 26 ++++++++++ .../tests/homarr-final-setup.spec.ts | 44 +++++++++++++++++ .../k3s-flake/tests/homarr-final.spec.ts | 22 +++++++++ .../k3s-flake/tests/homarr-form-debug.spec.ts | 26 ++++++++++ .../k3s-flake/tests/homarr-inputs.spec.ts | 17 +++++++ .../k3s-flake/tests/homarr-network.spec.ts | 20 ++++++++ .../k3s-flake/tests/homarr-onboard.spec.ts | 29 +++++++++++ .../k3s-flake/tests/homarr-setup.spec.ts | 22 +++++++++ .../k3s-flake/tests/homarr-step2.spec.ts | 15 ++++++ .../k3s-flake/tests/homarr-test.spec.ts | 14 ++++++ .../k3s-flake/tests/homarr-wizard.spec.ts | 47 ++++++++++++++++++ 14 files changed, 384 insertions(+) create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-account.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-complete.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-debug2.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-dispatch.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-final-setup.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-final.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-form-debug.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-inputs.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-network.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-onboard.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-setup.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-step2.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-test.spec.ts create mode 100644 4-Infrastructure/k3s-flake/tests/homarr-wizard.spec.ts diff --git a/4-Infrastructure/k3s-flake/tests/homarr-account.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-account.spec.ts new file mode 100644 index 00000000..969a6e3a --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-account.spec.ts @@ -0,0 +1,35 @@ +import { test } from '@playwright/test'; +test('homarr account form', async ({ page }) => { + test.setTimeout(20000); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(3000); + + // Navigate to account creation + await page.evaluate(() => { + document.querySelectorAll('button').forEach(b => { + if (b.textContent?.includes('Start update process')) b.click(); + }); + }); + await page.waitForTimeout(4000); + + // Dump all inputs and their labels + const inputs = await page.locator('input, select, textarea').all(); + console.log(`Found ${inputs.length} inputs`); + for (const inp of inputs) { + const id = await inp.getAttribute('id'); + const name = await inp.getAttribute('name'); + const placeholder = await inp.getAttribute('placeholder'); + const type = await inp.getAttribute('type'); + const label = await page.locator(`label[for="${id}"]`).textContent().catch(() => ''); + console.log(` id=${id} type=${type} name=${name} placeholder=${placeholder} label=${label}`); + } + + // Also check what elements with role and text + const texts = await page.locator('h1,h2,h3,p,label,span').all(); + for (const el of texts) { + const text = await el.textContent(); + if (text?.trim() && text.trim().length > 2 && text.trim().length < 100) { + console.log(`Text: "${text.trim()}"`); + } + } +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-complete.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-complete.spec.ts new file mode 100644 index 00000000..a5120c76 --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-complete.spec.ts @@ -0,0 +1,49 @@ +import { test } from '@playwright/test'; +test('Homarr full onboard', async ({ page }) => { + test.setTimeout(120000); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(3000); + + // Step 1: Click start + await page.evaluate(() => { + document.querySelectorAll('button').forEach(b => { + if (b.textContent?.includes('Start update process')) b.dispatchEvent(new MouseEvent('click', { bubbles: true })); + }); + }); + await page.waitForTimeout(3000); + console.log('Step 1 - Start clicked'); + + // Check what inputs are available + const inputs = await page.locator('input').count(); + console.log(`Found ${inputs} inputs`); + + if (inputs > 0) { + await page.locator('input').nth(0).fill('admin'); + if (inputs > 1) await page.locator('input').nth(1).fill('admin@researchstack.info'); + if (inputs > 2) await page.locator('input').nth(2).fill('homarr-admin'); + console.log('Form filled'); + } + + // Click Continue + const continueBtn = page.locator('button:has-text("Continue"):visible').first(); + if (await continueBtn.isVisible({ timeout: 3000 }).catch(() => false)) { + await continueBtn.click({ force: true, noWaitAfter: true }); + await page.waitForTimeout(3000); + console.log('Continue clicked'); + } + + // Continue clicking "Continue" or "Finish" through remaining steps + for (let i = 0; i < 10; i++) { + const btn = page.locator('button:has-text("Continue"):visible, button:has-text("Finish"):visible, button:has-text("Next"):visible').first(); + if (await btn.isVisible({ timeout: 3000 }).catch(() => false)) { + await btn.click({ force: true, noWaitAfter: true }); + await page.waitForTimeout(3000); + console.log(`Step ${i+2} clicked, URL: ${page.url()}`); + } else { + break; + } + } + + console.log('Final URL:', page.url()); + await page.screenshot({ path: '/tmp/homarr-complete.png' }); +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-debug2.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-debug2.spec.ts new file mode 100644 index 00000000..c5bbea57 --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-debug2.spec.ts @@ -0,0 +1,18 @@ +import { test } from '@playwright/test'; +test('homarr2', async ({ page }) => { + test.setTimeout(20000); + console.log('Going...'); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + console.log('Loaded'); + await page.waitForTimeout(2000); + console.log('Finding button...'); + const btn = page.locator('button:has-text("Start update process"):visible').first(); + const visible = await btn.isVisible({ timeout: 3000 }).catch(() => false); + console.log('Visible:', visible); + if (visible) { + console.log('Clicking...'); + await btn.click(); + await page.waitForTimeout(3000); + console.log('Clicked, URL:', page.url()); + } +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-dispatch.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-dispatch.spec.ts new file mode 100644 index 00000000..317a0897 --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-dispatch.spec.ts @@ -0,0 +1,26 @@ +import { test } from '@playwright/test'; +test('homarr dispatch', async ({ page }) => { + test.setTimeout(20000); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(4000); + + // Try clicking via JavaScript dispatch + await page.evaluate(() => { + const buttons = document.querySelectorAll('button'); + for (const btn of buttons) { + if (btn.textContent?.includes('Start update process')) { + btn.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); + return; + } + } + }); + await page.waitForTimeout(5000); + console.log('URL:', page.url()); + + // Check for new buttons + const btns = await page.locator('button').all(); + for (const b of btns) { + const text = await b.textContent(); + if (await b.isVisible()) console.log(` "${text?.trim().substring(0,40)}"`); + } +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-final-setup.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-final-setup.spec.ts new file mode 100644 index 00000000..fb86fd54 --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-final-setup.spec.ts @@ -0,0 +1,44 @@ +import { test } from '@playwright/test'; +test('Homarr complete setup', async ({ page }) => { + test.setTimeout(120000); + + // Step 1: Load page + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(3000); + + // Step 2: Click "Start update process" + await page.evaluate(() => { + document.querySelectorAll('button').forEach(b => { + if (b.textContent?.includes('Start update process')) b.dispatchEvent(new MouseEvent('click', { bubbles: true })); + }); + }); + await page.waitForTimeout(5000); + + // Step 3: Fill account form + await page.locator('input[type="text"]').first().fill('admin'); + const passwordInputs = page.locator('input[type="password"]'); + await passwordInputs.nth(0).fill('homarr-admin'); + await passwordInputs.nth(1).fill('homarr-admin'); + await page.waitForTimeout(500); + + // Click Continue + await page.locator('button:has-text("Continue"):visible').first().click({ force: true, noWaitAfter: true }); + await page.waitForTimeout(3000); + console.log('Account created'); + + // Step 4: Continue through remaining steps + for (let i = 0; i < 15; i++) { + const btn = page.locator('button:has-text("Continue"):visible, button:has-text("Finish"):visible').first(); + if (await btn.isVisible({ timeout: 3000 }).catch(() => false)) { + await btn.click({ force: true, noWaitAfter: true }); + await page.waitForTimeout(2000); + console.log(`Step ${i + 2}: ${page.url()}`); + } else { + console.log(`No more buttons at step ${i + 2}`); + break; + } + } + + console.log('Final URL:', page.url()); + await page.screenshot({ path: '/tmp/homarr-complete.png' }); +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-final.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-final.spec.ts new file mode 100644 index 00000000..cd1c5818 --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-final.spec.ts @@ -0,0 +1,22 @@ +import { test } from '@playwright/test'; +test('Homarr final', async ({ page }) => { + test.setTimeout(60000); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(4000); + + for (const text of ["Start update process", "Next", "Next", "Next", "Finish"]) { + const btn = page.locator(`button:has-text("${text}"):visible`).first(); + if (await btn.isVisible({ timeout: 3000 }).catch(() => false)) { + await btn.click({ force: true, noWaitAfter: true }); + await page.waitForTimeout(3000); + console.log(`Clicked "${text}"`); + } else { + console.log(`Button "${text}" not found`); + break; + } + } + + await page.waitForTimeout(2000); + console.log('Final URL:', page.url()); + await page.screenshot({ path: '/tmp/homarr-final.png' }); +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-form-debug.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-form-debug.spec.ts new file mode 100644 index 00000000..bc688bad --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-form-debug.spec.ts @@ -0,0 +1,26 @@ +import { test } from '@playwright/test'; +test('form debug', async ({ page }) => { + test.setTimeout(20000); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(3000); + await page.evaluate(() => { + document.querySelectorAll('button').forEach(b => { + if (b.textContent?.includes('Start update process')) b.click(); + }); + }); + await page.waitForTimeout(4000); + + // Check ALL input types + console.log('input[type=text]:', await page.locator('input[type="text"]').count()); + console.log('input[type=password]:', await page.locator('input[type="password"]').count()); + console.log('input[type=email]:', await page.locator('input[type="email"]').count()); + console.log('input:not([type]):', await page.locator('input:not([type])').count()); + console.log('All inputs:', await page.locator('input').count()); + console.log('[contenteditable]:', await page.locator('[contenteditable]').count()); + + // Dump all input HTML + const html = await page.content(); + const inputMatches = html.match(/]*>/g) || []; + console.log('Input HTML elements found:', inputMatches.length); + for (const m of inputMatches.slice(0,5)) console.log(' ' + m.substring(0,120)); +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-inputs.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-inputs.spec.ts new file mode 100644 index 00000000..3af7e2d7 --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-inputs.spec.ts @@ -0,0 +1,17 @@ +import { test } from '@playwright/test'; +test('homarr inputs', async ({ page }) => { + test.setTimeout(20000); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(4000); + + // Check for all interactive elements + for (const type of ['input', 'select', 'textarea', '[role="button"]', '[role="checkbox"]', '[type="checkbox"]']) { + const els = page.locator(type); + const count = await els.count(); + if (count > 0) console.log(`Found ${count} ${type}`); + } + + // Check what's inside forms + const forms = page.locator('form').count(); + console.log(`Forms: ${await forms}`); +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-network.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-network.spec.ts new file mode 100644 index 00000000..5475426a --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-network.spec.ts @@ -0,0 +1,20 @@ +import { test } from '@playwright/test'; +test('homarr network', async ({ page }) => { + test.setTimeout(20000); + + // Listen for API requests + const requests: string[] = []; + page.on('request', req => { + if (req.url().includes('/api')) requests.push(req.url() + ' ' + req.method()); + }); + + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(3000); + + const btn = page.locator('button:has-text("Start update process"):visible').first(); + await btn.click({ force: true, noWaitAfter: true }); + await page.waitForTimeout(5000); + + console.log('Requests:', requests.join('\n ')); + console.log('URL:', page.url()); +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-onboard.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-onboard.spec.ts new file mode 100644 index 00000000..266009b8 --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-onboard.spec.ts @@ -0,0 +1,29 @@ +import { test } from '@playwright/test'; +test('Homarr onboarding', async ({ page }) => { + test.setTimeout(60000); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000 }); + await page.waitForTimeout(3000); + + // Click "Start update process" + const startBtn = page.locator('button:has-text("Start update process"):visible').first(); + if (await startBtn.isVisible({ timeout: 3000 }).catch(() => false)) { + await startBtn.click(); + await page.waitForTimeout(3000); + console.log('Step 1 clicked'); + } + + // Continue through steps + for (let i = 0; i < 5; i++) { + const nextBtn = page.locator('button:has-text("Next"):visible, button:has-text("Continue"):visible, button:has-text("Finish"):visible, button[data-button="true"]:visible').first(); + if (await nextBtn.isVisible({ timeout: 2000 }).catch(() => false)) { + await nextBtn.click(); + await page.waitForTimeout(2000); + console.log(`Step ${i+2} clicked`); + } else { + break; + } + } + + await page.screenshot({ path: '/tmp/homarr-done.png' }); + console.log('Onboarding complete'); +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-setup.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-setup.spec.ts new file mode 100644 index 00000000..2b052a52 --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-setup.spec.ts @@ -0,0 +1,22 @@ +import { test } from '@playwright/test'; +test('Homarr setup', async ({ page }) => { + test.setTimeout(60000); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(3000); + + // Click buttons with force (don't wait for navigation) + for (const text of ["Start update process", "Next", "Next", "Next", "Finish"]) { + const btn = page.locator(`button:has-text("${text}"):visible`).first(); + if (await btn.isVisible({ timeout: 3000 }).catch(() => false)) { + await btn.click({ force: true, timeout: 5000 }); + await page.waitForTimeout(3000); + console.log(`Clicked "${text}"`); + } else { + console.log(`Button "${text}" not found at step`); + break; + } + } + + await page.screenshot({ path: '/tmp/homarr-done.png' }); + console.log('Done at:', page.url()); +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-step2.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-step2.spec.ts new file mode 100644 index 00000000..ac43186b --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-step2.spec.ts @@ -0,0 +1,15 @@ +import { test } from '@playwright/test'; +test('homarr step 2', async ({ page }) => { + test.setTimeout(30000); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(3000); + await page.locator('button:has-text("Start update process"):visible').first().click({ force: true, noWaitAfter: true }); + await page.waitForTimeout(5000); + console.log('URL:', page.url()); + + // Dump all buttons + for (const b of await page.locator('button').all()) { + const text = await b.textContent(); + if (await b.isVisible()) console.log(` Visible: "${text?.trim().substring(0,40)}"`); + } +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-test.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-test.spec.ts new file mode 100644 index 00000000..d8099379 --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-test.spec.ts @@ -0,0 +1,14 @@ +import { test } from '@playwright/test'; +test('homarr test', async ({ page }) => { + test.setTimeout(30000); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(5000); + const title = await page.title(); + console.log('Title:', title); + const buttons = await page.locator('button').count(); + console.log(`Found ${buttons} buttons`); + for (const b of await page.locator('button').all()) { + const text = await b.textContent(); + console.log(` Button: "${text?.trim().substring(0,30)}" visible=${await b.isVisible()}`); + } +}); diff --git a/4-Infrastructure/k3s-flake/tests/homarr-wizard.spec.ts b/4-Infrastructure/k3s-flake/tests/homarr-wizard.spec.ts new file mode 100644 index 00000000..d37bcb3f --- /dev/null +++ b/4-Infrastructure/k3s-flake/tests/homarr-wizard.spec.ts @@ -0,0 +1,47 @@ +import { test } from '@playwright/test'; +test('Homarr wizard', async ({ page }) => { + test.setTimeout(60000); + await page.goto('http://100.88.57.96:30093/', { timeout: 10000, waitUntil: 'domcontentloaded' }); + await page.waitForTimeout(4000); + + // Step 1: Start update + await page.evaluate(() => { + document.querySelectorAll('button').forEach(b => { + if (b.textContent?.trim() === 'Start update process') b.click(); + }); + }); + await page.waitForTimeout(5000); + + // Step 2: Fill account form with valid password + await page.locator('input[type="text"]').first().fill('admin'); + const pwInputs = page.locator('input[type="password"]'); + await pwInputs.nth(0).fill('Admin123!'); + await pwInputs.nth(1).fill('Admin123!'); + await page.waitForTimeout(1000); + + // Click Continue + await page.locator('button:has-text("Continue"):visible').first().click({ force: true, noWaitAfter: true }); + await page.waitForTimeout(5000); + console.log('Step 1 done, URL:', page.url()); + + // Keep clicking Continue/Finish through remaining steps + for (let step = 2; step <= 10; step++) { + const btn = page.locator('button:has-text("Continue"):visible, button:has-text("Finish"):visible').first(); + if (await btn.isVisible({ timeout: 3000 }).catch(() => false)) { + await btn.click({ force: true, noWaitAfter: true }); + await page.waitForTimeout(3000); + console.log(`Step ${step}: ${page.url()}`); + } else { + console.log(`No more buttons at step ${step}`); + break; + } + } + + await page.screenshot({ path: '/tmp/homarr-final.png' }); + console.log('Final URL:', page.url()); + + // Check if we got redirected away from onboard + if (!page.url().includes('onboard')) { + console.log('SUCCESS: Onboard completed!'); + } +});