58 lines
3.1 KiB
JavaScript
58 lines
3.1 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import { spawn } from 'node:child_process'
|
|
import { once } from 'node:events'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { test } from 'node:test'
|
|
import { ChromeGatewayClient } from '../../desktop/electron/chrome-bridge.mjs'
|
|
|
|
test('real FastAPI/SQLite: valid bounded desktop pages, profile scope and empty states', {
|
|
skip: !process.env.AITURK_TEST_PYTHON && 'Set AITURK_TEST_PYTHON to run the real API contract',
|
|
timeout: 90000,
|
|
}, async t => {
|
|
// No credentials/config inherited by the disposable Python service.
|
|
const env = Object.fromEntries(['PATH', 'SYSTEMROOT', 'TEMP', 'TMP', 'USERPROFILE', 'LOCALAPPDATA', 'APPDATA']
|
|
.filter(key => process.env[key]).map(key => [key, process.env[key]]))
|
|
env.PYTHONUTF8 = '1'
|
|
const child = spawn(process.env.AITURK_TEST_PYTHON,
|
|
[fileURLToPath(new URL('./sessions-api-fixture.py', import.meta.url))], { env, windowsHide: true })
|
|
const exited = once(child, 'exit')
|
|
let stdout = '', stderr = ''
|
|
child.stderr.on('data', chunk => { stderr += chunk })
|
|
t.after(async () => { child.stdin.end(); await exited })
|
|
const port = await new Promise((resolve, reject) => {
|
|
const timer = setTimeout(() => reject(new Error(`Fixture startup timeout: ${stderr}`)), 45000)
|
|
child.once('error', error => { clearTimeout(timer); reject(error) })
|
|
child.once('exit', () => { clearTimeout(timer); reject(new Error(`Fixture exited: ${stderr}`)) })
|
|
child.stdout.on('data', chunk => {
|
|
stdout += chunk
|
|
const match = stdout.match(/READY (\d+)/)
|
|
if (match) { clearTimeout(timer); resolve(Number(match[1])) }
|
|
})
|
|
})
|
|
const baseUrl = `http://127.0.0.1:${port}`
|
|
const old = await fetch(`${baseUrl}/api/sessions?limit=200`, { headers: { 'X-Hermes-Session-Token': 'fixture-only' } })
|
|
assert.equal(old.status, 422, 'production validation reproduces the reported failure')
|
|
assert.ok((await old.json()).detail.some(error => error.loc.includes('limit')))
|
|
for (const [profile, expected, requests] of [['default', 200, 2], ['small', 3, 1], ['empty', 0, 1]]) {
|
|
const client = new ChromeGatewayClient(async () => ({ baseUrl, wsUrl: `${baseUrl.replace('http:', 'ws:')}/api/ws`,
|
|
token: 'fixture-only', mode: 'local', profile }), () => {})
|
|
const paths = []
|
|
const realRest = client.rest.bind(client)
|
|
client.rest = path => { paths.push(path); return realRest(path) }
|
|
try {
|
|
const result = await client.handle({ id: 'contract', action: 'sessions.list' })
|
|
assert.equal(result.sessions.length, expected)
|
|
assert.equal(new Set(result.sessions.map(row => row.id)).size, expected)
|
|
assert.ok(result.sessions.every(row => row.id.startsWith(`${profile}-desktop-`)))
|
|
assert.equal(result.profile, profile)
|
|
assert.equal(paths.length, requests)
|
|
for (const [index, path] of paths.entries()) {
|
|
const query = new URL(path, baseUrl).searchParams
|
|
assert.equal(query.get('offset'), String(index * 100))
|
|
assert.equal(query.get('source'), 'desktop')
|
|
assert.equal(query.get('profile'), profile)
|
|
}
|
|
} finally { client.close() }
|
|
}
|
|
})
|