import { test, expect } from '@playwright/test'; const services = [ { name: 'Homepage', url: 'http://localhost:4000', contentCheck: 'tsys developer support stack', titleCheck: 'TSYS Developer Support Stack', }, { name: 'Pi-hole', url: 'http://localhost:4006/admin', contentCheck: 'pihole', }, { name: 'Dockhand', url: 'http://localhost:4007', contentCheck: 'sveltekit', }, { name: 'InfluxDB', url: 'http://localhost:4008', contentCheck: 'influxdb', }, { name: 'Grafana', url: 'http://localhost:4009', contentCheck: 'grafana', }, { name: 'Draw.io', url: 'http://localhost:4010', contentCheck: 'diagram', }, { name: 'Kroki', url: 'http://localhost:4011/health', contentCheck: 'kroki', }, { name: 'Atomic Tracker', url: 'http://localhost:4012', contentCheck: 'journal', }, { name: 'ArchiveBox', url: 'http://localhost:4013', contentCheck: 'archive', }, { name: 'Tube Archivist', url: 'http://localhost:4014', contentCheck: 'tubearchivist', }, { name: 'Wakapi', url: 'http://localhost:4015', contentCheck: 'wakapi', }, { name: 'MailHog', url: 'http://localhost:4017', contentCheck: 'mailhog', }, { name: 'Atuin', url: 'http://localhost:4018', contentCheck: 'version', }, ]; for (const svc of services) { test(`${svc.name} (${svc.url}) loads successfully`, async ({ page }) => { const response = await page.goto(svc.url, { waitUntil: 'domcontentloaded', timeout: 30000, }); expect(response).not.toBeNull(); expect(response!.status()).toBeLessThan(400); const body = await page.textContent('body').catch(() => ''); const title = await page.title().catch(() => ''); const combined = (body + ' ' + title).toLowerCase(); expect( combined, `${svc.name} should not show an error page` ).not.toContain('host validation failed'); expect( combined, `${svc.name} should not show a server error` ).not.toContain('internal server error'); expect( combined, `${svc.name} should contain expected content` ).toContain(svc.contentCheck.toLowerCase()); if (svc.titleCheck) { expect( title.toLowerCase(), `${svc.name} should have expected title` ).toContain(svc.titleCheck.toLowerCase()); } }); }