Files
metabuilder/e2e/deployment-smoke.spec.ts
rw 504e4ecd2a refactor(deployment): consolidate compose files into single compose.yml
- Merge docker-compose.nexus.yml into compose.yml as --profile registry
- Drop docker-compose.smoke.yml, docker-compose.test.yml (deprecated), and docker-compose.stack.yml
- Rename to compose.yml (Docker Compose default; no -f flag needed)
- build apps / deploy now derive buildable services from compose.yml directly instead of hardcoded all_apps/service_map in commands.json — covers all 29 buildable services automatically

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 19:56:11 +00:00

90 lines
3.0 KiB
TypeScript

import { test, expect } from '@playwright/test'
/**
* Deployment smoke tests — validates all services are reachable
* through the nginx gateway on port 80.
*
* CI: The smoke stack (docker-compose.smoke.yml) provides nginx + admin tools.
* Playwright dev servers bind to 0.0.0.0 so nginx can proxy via host.docker.internal.
*
* Local:
* cd deployment && docker compose -f compose.yml up -d
* PLAYWRIGHT_BASE_URL=http://localhost/workflowui/ npx playwright test deployment-smoke
*/
const GATEWAY = 'http://localhost'
test.describe('Deployment Smoke Tests', () => {
test.describe('Web Applications', () => {
const apps = [
{ path: '/workflowui', name: 'WorkflowUI' },
{ path: '/codegen', name: 'CodeForge' },
{ path: '/pastebin', name: 'Pastebin' },
{ path: '/emailclient', name: 'Email Client' },
{ path: '/diagrams', name: 'Exploded Diagrams' },
{ path: '/storybook/', name: 'Storybook' },
{ path: '/app', name: 'Frontend App' },
]
for (const { path, name } of apps) {
test(`${name} loads via gateway (${path})`, async ({ page }) => {
const response = await page.goto(`${GATEWAY}${path}`, {
waitUntil: 'domcontentloaded',
timeout: 30000,
})
expect(response?.status()).toBeLessThan(500)
const body = page.locator('body')
await expect(body).not.toBeEmpty()
})
}
test('Postgres Dashboard redirects correctly', async ({ page }) => {
const response = await page.goto(`${GATEWAY}/postgres`, {
waitUntil: 'domcontentloaded',
timeout: 30000,
})
// 307/308 redirects are followed automatically by playwright
expect(response?.status()).toBeLessThan(500)
})
})
test.describe('API Services', () => {
test('DBAL health endpoint responds', async ({ request }) => {
const resp = await request.get(`${GATEWAY}/api/health`)
expect(resp.ok()).toBeTruthy()
})
test('DBAL version endpoint responds', async ({ request }) => {
const resp = await request.get(`${GATEWAY}/api/version`)
expect(resp.ok()).toBeTruthy()
})
})
test.describe('Portal', () => {
test('Portal index page loads', async ({ page }) => {
const response = await page.goto(GATEWAY, {
waitUntil: 'domcontentloaded',
})
expect(response?.status()).toBe(200)
await expect(page.locator('body')).toContainText('MetaBuilder')
})
})
test.describe('Admin Tools (direct ports)', () => {
test('phpMyAdmin responds', async ({ request }) => {
const resp = await request.get('http://localhost:8081')
expect(resp.status()).toBeLessThan(500)
})
test('Mongo Express responds', async ({ request }) => {
const resp = await request.get('http://localhost:8082')
expect(resp.status()).toBeLessThan(500)
})
test('RedisInsight responds', async ({ request }) => {
const resp = await request.get('http://localhost:8083')
expect(resp.status()).toBeLessThan(500)
})
})
})