()
| 25 | // Stub iOS StateServer running on loopback. Mimics the real Swift server's |
| 26 | // behavior for the integration test. |
| 27 | function startStubStateServer(): Promise<{ server: Server; port: number; receivedRequests: Array<{ method: string; path: string; headers: Record<string, string | string[] | undefined>; body: string }> }> { |
| 28 | return new Promise((resolve) => { |
| 29 | const received: Array<{ method: string; path: string; headers: Record<string, string | string[] | undefined>; body: string }> = []; |
| 30 | const server = createServer((req, res) => { |
| 31 | const chunks: Buffer[] = []; |
| 32 | req.on('data', (c) => chunks.push(c)); |
| 33 | req.on('end', () => { |
| 34 | const body = Buffer.concat(chunks).toString('utf-8'); |
| 35 | received.push({ method: req.method ?? '', path: req.url ?? '', headers: req.headers, body }); |
| 36 | |
| 37 | const auth = req.headers['authorization']; |
| 38 | // Validate the bearer is our rotated token. |
| 39 | if (!auth || auth !== `Bearer ${STATE_SERVER_TOKEN}`) { |
| 40 | res.writeHead(401, { 'content-type': 'application/json' }); |
| 41 | res.end(JSON.stringify({ error: 'unauthorized' })); |
| 42 | return; |
| 43 | } |
| 44 | |
| 45 | if (req.url === '/healthz') { |
| 46 | res.writeHead(200, { 'content-type': 'application/json' }); |
| 47 | res.end(JSON.stringify({ version: '1.0.0' })); |
| 48 | return; |
| 49 | } |
| 50 | if (req.url === '/screenshot') { |
| 51 | res.writeHead(200, { 'content-type': 'application/json' }); |
| 52 | res.end(JSON.stringify({ png_base64: 'abc=' })); |
| 53 | return; |
| 54 | } |
| 55 | if (req.url === '/tap') { |
| 56 | res.writeHead(200, { 'content-type': 'application/json' }); |
| 57 | res.end(JSON.stringify({ ok: true, op: 'tap' })); |
| 58 | return; |
| 59 | } |
| 60 | res.writeHead(404, { 'content-type': 'application/json' }); |
| 61 | res.end(JSON.stringify({ error: 'not_found' })); |
| 62 | }); |
| 63 | }); |
| 64 | server.listen(0, '127.0.0.1', () => { |
| 65 | const addr = server.address(); |
| 66 | const port = typeof addr === 'object' && addr ? addr.port : 0; |
| 67 | resolve({ server, port, receivedRequests: received }); |
| 68 | }); |
| 69 | }); |
| 70 | } |
| 71 | |
| 72 | async function fetchWith(method: string, url: string, init: { headers?: Record<string, string>; body?: string } = {}): Promise<{ status: number; bodyText: string }> { |
| 73 | const res = await fetch(url, { method, headers: init.headers, body: init.body }); |
no test coverage detected