|
1 | 1 | import { mkdtemp, rm } from 'node:fs/promises' |
2 | 2 | import { tmpdir } from 'node:os' |
3 | 3 | import path from 'node:path' |
| 4 | +import { spawn } from 'node:child_process' |
4 | 5 | import { afterEach, describe, expect, it } from 'vitest' |
5 | 6 |
|
6 | 7 | const temporaryRoots: string[] = [] |
@@ -53,6 +54,37 @@ describe('mode artifacts', () => { |
53 | 54 | }) |
54 | 55 | }) |
55 | 56 |
|
| 57 | + it('runs the deterministic generated App server health endpoint', async () => { |
| 58 | + const root = await mkdtemp(path.join(tmpdir(), 'onevibe-app-server-')) |
| 59 | + temporaryRoots.push(root) |
| 60 | + const { TaskStore } = await import('./store.js') |
| 61 | + const { writeModeArtifacts } = await import('./mode-artifacts.js') |
| 62 | + const store = new TaskStore(root) |
| 63 | + await store.initialize() |
| 64 | + const task = await store.createTask('Run generated app server', 'demo', 'app') |
| 65 | + await writeModeArtifacts(task, store) |
| 66 | + const port = 48_000 + Math.floor(Math.random() * 1_000) |
| 67 | + const appRoot = store.workspacePath(task.id, 'app') |
| 68 | + const command = path.resolve(process.cwd(), 'node_modules/.bin/tsx') |
| 69 | + const child = spawn(command, ['server/src/index.ts'], { cwd: appRoot, env: { ...process.env, PORT: String(port) }, stdio: ['ignore', 'pipe', 'pipe'] }) |
| 70 | + try { |
| 71 | + await new Promise<void>((resolve, reject) => { |
| 72 | + const timeout = setTimeout(() => reject(new Error('Generated app server did not start')), 5_000) |
| 73 | + child.once('error', (error) => { clearTimeout(timeout); reject(error) }) |
| 74 | + child.stdout.on('data', (chunk: Buffer) => { |
| 75 | + if (!chunk.toString().includes('Generated app server listening')) return |
| 76 | + clearTimeout(timeout); resolve() |
| 77 | + }) |
| 78 | + child.stderr.on('data', (chunk: Buffer) => { clearTimeout(timeout); reject(new Error(chunk.toString())) }) |
| 79 | + }) |
| 80 | + const response = await fetch(`http://127.0.0.1:${port}/health`) |
| 81 | + expect(response.status).toBe(200) |
| 82 | + await expect(response.json()).resolves.toEqual({ status: 'ok', service: 'onevibe-generated-app' }) |
| 83 | + } finally { |
| 84 | + child.kill() |
| 85 | + } |
| 86 | + }) |
| 87 | + |
56 | 88 | it('generates a playable interaction loop for game mode', async () => { |
57 | 89 | const root = await mkdtemp(path.join(tmpdir(), 'onevibe-game-mode-')) |
58 | 90 | temporaryRoots.push(root) |
|
0 commit comments