import assert from 'node:assert/strict'; import test from 'node:test'; import {Machine10Client} from '../client/machine10.mjs'; test('client scopes Run Now and Main Machine requests to the app', async () => { const seen = []; const client = new Machine10Client({ appId: 'app id_dev', bearer: 'secret', grant: 'grant_1', gateway: 'https://example.test/api/', fetchImpl: async (url, init) => { seen.push({url, init}); return new Response(JSON.stringify({ok: true, accepted: true, machine: {generation: 0}}), { status: 202, headers: {'content-type': 'application/json'} }); } }); await client.run({programBase64: 'AA=='}); await client.trigger({occurrenceId: 'occ_1', kind: 'manual', payload: {ok: true}}); assert.deepEqual(seen.map(({url, init}) => [url, init.method]), [ ['https://example.test/api/apps/app%20id_dev/machine10/run', 'POST'], ['https://example.test/api/apps/app%20id_dev/machine10/main/events', 'POST'] ]); assert.ok(seen.every(({init}) => init.headers.authorization === 'Bearer secret')); assert.ok(seen.every(({init}) => init.headers['x-jmpkit-grant'] === 'grant_1')); }); test('client exposes structured HTTP errors', async () => { const client = new Machine10Client({ appId: 'app_dev', bearer: 'secret', fetchImpl: async () => new Response( JSON.stringify({error: 'machine unavailable', code: 'machine_unavailable'}), {status: 503} ) }); await assert.rejects(client.inspect(), (error) => { assert.equal(error.status, 503); assert.equal(error.code, 'machine_unavailable'); return true; }); }); test('client controls lifecycle, generations, and Origin fallback', async () => { const seen = []; const client = new Machine10Client({ appId: 'origin-app_dev', bearer: 'secret', gateway: 'https://example.test/api', fetchImpl: async (url, init) => { seen.push([url, init.method]); return new Response(JSON.stringify({ok: true, machine: {generation: 3}}), {status: 200}); } }); await client.replaceProgram({programBase64: 'AA=='}); await client.rollback(1); await client.pause(); await client.resume(); await client.stop(); await client.retry(); await client.generation(3); await client.enableOriginFallback(); await client.disableOriginFallback(); await client.delete(); assert.deepEqual(seen.map((entry) => entry[1]), [ 'PUT', 'POST', 'POST', 'POST', 'POST', 'POST', 'GET', 'PUT', 'DELETE', 'DELETE' ]); assert.equal(seen.at(-1)[0], 'https://example.test/api/apps/origin-app_dev/machine10/main'); }); test('waitForOccurrence observes a committed generation', async () => { let reads = 0; const client = new Machine10Client({ appId: 'wait-app', bearer: 'secret', fetchImpl: async () => { reads += 1; return new Response(JSON.stringify({ machine: { generation: reads, status: 'idle', generationHistory: reads > 1 ? [{generation: 2, occurrenceId: 'occ_wait_01'}] : [] } }), {status: 200}); } }); const machine = await client.waitForOccurrence('occ_wait_01', {timeoutMs: 1000, intervalMs: 1}); assert.equal(machine.generation, 2); });