Skip to content

Commit 034cec3

Browse files
GiniGini
authored andcommitted
test: execute generated app server fixture
1 parent 2c9e4f2 commit 034cec3

2 files changed

Lines changed: 33 additions & 0 deletions

File tree

docs/IMPLEMENTATION-LOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,4 @@
6868
- Added a read-only task Settings workspace tab. It gathers the runtime/boundary, gateway-attestation, approval, artifact-contract, and attached-context record in one reviewable place while deliberately excluding credentials, VTI Wallet keys, provider controls, and X11/VNC/CDP channels.
6969
- Modernized generated Website/App/Game projects with Tailwind 4’s Vite integration and a minimal typed component foundation (`Button` plus `cn`). Static validation now verifies the foundation is present; installing or running third-party dependencies remains reserved for a controlled sandbox build gate.
7070
- Extended App mode with a portable full-stack seed: a separately checked Node/TypeScript local server, a typed health contract shared with the client tree, and explicit server scripts. It deliberately creates no auth, connector, credential, or deployment behavior; those belong to the governed runtime/integration layers.
71+
- Added an isolated runtime test for the deterministic generated App scaffold: it starts the generated server and verifies its typed `/health` response. This validates the known fixture only; it does not execute arbitrary agent-created source or install third-party project dependencies on the host.

server/mode-artifacts.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { mkdtemp, rm } from 'node:fs/promises'
22
import { tmpdir } from 'node:os'
33
import path from 'node:path'
4+
import { spawn } from 'node:child_process'
45
import { afterEach, describe, expect, it } from 'vitest'
56

67
const temporaryRoots: string[] = []
@@ -53,6 +54,37 @@ describe('mode artifacts', () => {
5354
})
5455
})
5556

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+
5688
it('generates a playable interaction loop for game mode', async () => {
5789
const root = await mkdtemp(path.join(tmpdir(), 'onevibe-game-mode-'))
5890
temporaryRoots.push(root)

0 commit comments

Comments
 (0)