diff --git a/src/server/index.ts b/src/server/index.ts index f85bc52..42b4666 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -15,10 +15,9 @@ export async function startServer(cwd: string, options: { port?: number; host?: try { await app.listen({ port, host }); const address = app.server.address(); - const url = typeof address === 'string' - ? address - : `http://${host === '0.0.0.0' ? '127.0.0.1' : host}:${address?.port ?? port}`; - console.log(`AgentHub server listening on http://${host}:${port}`); + const actualPort = typeof address === 'string' ? port : (address?.port ?? port); + const url = `http://${host === '0.0.0.0' ? '127.0.0.1' : host}:${actualPort}`; + console.log(`AgentHub server listening on ${url}`); return { app, url }; } catch (err) { app.log.error(err); diff --git a/tests/e2e-network.test.ts b/tests/e2e-network.test.ts new file mode 100644 index 0000000..4a684cc --- /dev/null +++ b/tests/e2e-network.test.ts @@ -0,0 +1,48 @@ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import { mkdtempSync, rmSync } from 'fs'; +import { tmpdir } from 'os'; +import { join } from 'path'; +import { startServer } from '../src/server/index.js'; +import { remoteClient } from '../src/cli/remoteClient.js'; +import { init } from '../src/cli/commands/init.js'; + +describe('network e2e', () => { + let cwd: string; + let server: Awaited>; + + beforeEach(async () => { + cwd = mkdtempSync(join(tmpdir(), 'ah-net-')); + await init(cwd, { projectName: 'net-test', yes: true }); + server = await startServer(cwd, { host: '127.0.0.1', port: 0 }); + }); + + afterEach(async () => { + await server.app.close(); + rmSync(cwd, { recursive: true, force: true }); + }); + + it('creates a task remotely and reads it back', async () => { + const url = server.url; + const created = await remoteClient.createTask(url, { title: 'Remote', role: 'implementer' }); + expect(created.id).toBe('TSK-0001'); + + const tasks = await remoteClient.listTasks(url); + expect(tasks).toHaveLength(1); + + const { task } = await remoteClient.getTask(url, 'TSK-0001'); + expect(task.title).toBe('Remote'); + }); + + it('claims and completes a task remotely', async () => { + const url = server.url; + await remoteClient.createTask(url, { title: 'Remote', role: 'implementer' }); + const claimed = await remoteClient.claimTask(url, 'TSK-0001', 'codex'); + expect(claimed.status).toBe('in_progress'); + const done = await remoteClient.doneTask(url, 'TSK-0001'); + expect(done.status).toBe('done'); + }); + + it('returns a meaningful error when the server is unreachable', async () => { + await expect(remoteClient.listTasks('http://127.0.0.1:1')).rejects.toThrow(/Cannot reach AgentHub server/); + }); +});