/** * Discovery script — logs in, captures the dashboard, and probes the sidebar * nav to learn the actual URLs of the sections referenced in our docs. * * Not committed for ongoing use; the canonical capture is run.ts. */ import { chromium, type Page } from 'playwright'; import { mkdir, writeFile } from 'node:fs/promises'; import { resolve, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const OUT_DIR = resolve(__dirname, '../../src/assets/screenshots/whp'); function need(name: string): string { const v = process.env[name]; if (!v) throw new Error(`missing env: ${name}`); return v; } const BASE = need('WHP_BASE'); const USER = need('WHP_USER'); const PASS = need('WHP_PASS'); async function login(page: Page): Promise { console.log(`navigating ${BASE}/login.php`); await page.goto(`${BASE}/login.php`, { waitUntil: 'domcontentloaded' }); console.log(`landed at ${page.url()}`); await page.fill('input[name="user"]', USER); await page.fill('input[name="password"]', PASS); await page.click('button[type="submit"]'); await page.waitForLoadState('networkidle'); console.log(`logged in, now at ${page.url()}`); } async function snapshotPage(page: Page, id: string): Promise { await mkdir(OUT_DIR, { recursive: true }); const path = resolve(OUT_DIR, `${id}.png`); await page.screenshot({ path, fullPage: false }); console.log(`captured ${id} -> ${path}`); } async function listNavLinks(page: Page): Promise<{ text: string; href: string | null }[]> { // Use locator API to collect all anchors with hrefs (no string-eval). const anchors = page.locator('a[href]'); const count = await anchors.count(); const out: { text: string; href: string | null }[] = []; for (let i = 0; i < count && out.length < 120; i++) { const a = anchors.nth(i); const href = await a.getAttribute('href'); if (!href || href.startsWith('#')) continue; const text = ((await a.textContent()) ?? '').trim().slice(0, 60); if (!text) continue; out.push({ text, href }); } return out; } async function probe(page: Page, label: string, hrefHint: string): Promise { const link = page.locator(`a[href*="${hrefHint}"]`).first(); if ((await link.count()) === 0) { console.log(` NO MATCH for "${label}" (hint=${hrefHint})`); return null; } const href = await link.getAttribute('href'); console.log(` ${label}: ${href}`); return href; } async function main(): Promise { const browser = await chromium.launch({ headless: true }); const ctx = await browser.newContext({ ignoreHTTPSErrors: true, viewport: { width: 1440, height: 900 }, }); const page = await ctx.newPage(); try { await login(page); await snapshotPage(page, '_discovery-dashboard'); const navLinks = await listNavLinks(page); await writeFile( resolve(__dirname, '_discovered-nav.json'), JSON.stringify(navLinks, null, 2), ); console.log(`wrote ${navLinks.length} nav links to _discovered-nav.json`); for (const [label, hint] of [ ['Domains', 'domain'], ['Sites', 'site'], ['Email', 'email'], ['Backups', 'backup'], ['Monitor', 'monitor'], ['Resources', 'resource'], ['Dashboard', 'dashboard'], ] as const) { await probe(page, label, hint); } } finally { await browser.close(); } } main().catch((err) => { console.error(err); process.exit(1); });