diff --git a/apps/waterfall-wiki/tests/creative-browser-diagnostics.test.ts b/apps/waterfall-wiki/tests/creative-browser-diagnostics.test.ts new file mode 100644 index 0000000..72a6b97 --- /dev/null +++ b/apps/waterfall-wiki/tests/creative-browser-diagnostics.test.ts @@ -0,0 +1,13 @@ +import {test} from 'node:test'; +import {verifyCanvasAgentUI} from './canvas-ui-integration'; +import {db} from '../src/lib/db'; +const originalFetch=globalThis.fetch; +globalThis.fetch=async(input,init)=>{ + const url=typeof input==='string'?input:input instanceof URL?input.href:input.url; + const path=new URL(url).pathname,started=Date.now(); + try{const response=await originalFetch(input,init);console.log('Diagnostic HTTP',JSON.stringify({path,method:init?.method||'GET',status:response.status,ms:Date.now()-started}));return response} + catch(error){console.error('Diagnostic HTTP failed',JSON.stringify({path,method:init?.method||'GET',ms:Date.now()-started,error:error instanceof Error?error.message:String(error)}));throw error} +}; +test('diagnose canvas navigation against prebuilt review images',{timeout:300000},async()=>{ + try{await verifyCanvasAgentUI(process.env.PROMPT_TEST_BASE_URL!)}finally{await db().end()} +}); diff --git a/compose.creative-diagnostics.yml b/compose.creative-diagnostics.yml index 803cd1e..572b3bf 100644 --- a/compose.creative-diagnostics.yml +++ b/compose.creative-diagnostics.yml @@ -3,3 +3,4 @@ services: tests: volumes: - ./apps/waterfall-wiki/tests/canvas-ui-integration.ts:/app/tests/canvas-ui-integration.ts:ro + - ./apps/waterfall-wiki/tests/creative-browser-diagnostics.test.ts:/app/tests/integration.test.ts:ro diff --git a/scripts/integration.sh b/scripts/integration.sh index 167fe7e..1a3e93c 100644 --- a/scripts/integration.sh +++ b/scripts/integration.sh @@ -14,7 +14,16 @@ if [[ -n "${STUDIO_REVIEW_IMAGE:-}" ]]; then fi if [[ "${CREATIVE_BROWSER_DIAGNOSTICS:-}" == "1" ]]; then COMPOSE_FILES+=(-f compose.creative-diagnostics.yml); fi compose(){ docker compose -p "$COMPOSE_PROJECT_NAME" --env-file "$TEST_ENV" "${COMPOSE_FILES[@]}" "$@"; } -cleanup(){ code=$?; if [ "$code" -ne 0 ]; then compose logs --tail 160 waterfall-wiki waterfall-wiki-worker "${STUDIO_SERVICES[@]}"; fi; compose down -v --remove-orphans; rm -f "$TEST_ENV"; } +diagnostic_state(){ + if [[ "${CREATIVE_BROWSER_DIAGNOSTICS:-}" != "1" ]]; then return; fi + local ids + ids=$(compose ps -aq) + if [[ -n "$ids" ]]; then + docker inspect --format '{{.Name}} OOMKilled={{.State.OOMKilled}} RestartCount={{.RestartCount}} ExitCode={{.State.ExitCode}}' $ids + docker stats --no-stream --format '{{.Name}} CPU={{.CPUPerc}} Memory={{.MemUsage}} PIDs={{.PIDs}}' $ids + fi +} +cleanup(){ code=$?; diagnostic_state || true; if [ "$code" -ne 0 ]; then compose logs --tail 160 waterfall-wiki waterfall-wiki-worker "${STUDIO_SERVICES[@]}"; fi; compose down -v --remove-orphans; rm -f "$TEST_ENV"; } trap cleanup EXIT # Random credentials exist only for this disposable stack; no host Node required. docker run --rm --entrypoint node "$WATERFALL_WIKI_IMAGE" -e "const c=require('crypto');const hex=()=>c.randomBytes(24).toString('hex');console.log('POSTGRES_PASSWORD='+hex()+'\nS3_ACCESS_KEY='+hex()+'\nS3_SECRET_KEY='+hex())" > "$TEST_ENV" @@ -24,6 +33,7 @@ if [[ -n "${STUDIO_REVIEW_IMAGE:-}" ]]; then printf '\nACCOUNT_PUBLIC_ORIGIN=htt compose up -d --no-build --wait --wait-timeout 120 postgres objects compose run --rm --no-deps migrate compose up -d --no-build --wait --wait-timeout 150 waterfall-wiki waterfall-wiki-worker "${STUDIO_SERVICES[@]}" +diagnostic_state # The test runner calls the actual non-root production web/worker containers. compose run --rm --no-deps tests compose exec -T waterfall-wiki node container-health.mjs