index.test.ts68 lines · main
| 1 | import { afterEach, describe, expect, test } from 'bun:test'; |
| 2 | |
| 3 | import { createBrivenClient } from './index.js'; |
| 4 | |
| 5 | const realFetch = globalThis.fetch; |
| 6 | |
| 7 | afterEach(() => { |
| 8 | globalThis.fetch = realFetch; |
| 9 | }); |
| 10 | |
| 11 | function client() { |
| 12 | return createBrivenClient({ projectId: 'p_test', apiOrigin: 'https://api.test' }); |
| 13 | } |
| 14 | |
| 15 | describe('invoke() never throws — always returns an InvokeFrame', () => { |
| 16 | test('non-JSON gateway body (502 HTML) → network_error frame, not a SyntaxError', async () => { |
| 17 | globalThis.fetch = (async () => |
| 18 | new Response('<html>502 Bad Gateway</html>', { |
| 19 | status: 502, |
| 20 | headers: { 'content-type': 'text/html' }, |
| 21 | })) as typeof fetch; |
| 22 | |
| 23 | const frame = await client().invoke('listNotes'); |
| 24 | expect(frame.ok).toBe(false); |
| 25 | if (!frame.ok) { |
| 26 | expect(frame.code).toBe('network_error'); |
| 27 | expect(typeof frame.message).toBe('string'); |
| 28 | expect(frame.durationMs).toBe(0); |
| 29 | } |
| 30 | }); |
| 31 | |
| 32 | test('a valid JSON error frame (422) is returned as-is', async () => { |
| 33 | globalThis.fetch = (async () => |
| 34 | new Response(JSON.stringify({ ok: false, code: 'validation_failed', message: 'bad', durationMs: 3 }), { |
| 35 | status: 422, |
| 36 | headers: { 'content-type': 'application/json' }, |
| 37 | })) as typeof fetch; |
| 38 | |
| 39 | const frame = await client().invoke('createTodo', {}); |
| 40 | expect(frame.ok).toBe(false); |
| 41 | if (!frame.ok) { |
| 42 | expect(frame.code).toBe('validation_failed'); |
| 43 | expect(frame.message).toBe('bad'); |
| 44 | } |
| 45 | }); |
| 46 | |
| 47 | test('a network failure (fetch throws) → network_error frame', async () => { |
| 48 | globalThis.fetch = (async () => { |
| 49 | throw new TypeError('Failed to fetch'); |
| 50 | }) as typeof fetch; |
| 51 | |
| 52 | const frame = await client().invoke('listNotes'); |
| 53 | expect(frame.ok).toBe(false); |
| 54 | if (!frame.ok) expect(frame.code).toBe('network_error'); |
| 55 | }); |
| 56 | |
| 57 | test('a valid success frame passes through', async () => { |
| 58 | globalThis.fetch = (async () => |
| 59 | new Response(JSON.stringify({ ok: true, value: [1, 2, 3], durationMs: 5 }), { |
| 60 | status: 200, |
| 61 | headers: { 'content-type': 'application/json' }, |
| 62 | })) as typeof fetch; |
| 63 | |
| 64 | const frame = await client().invoke('listNotes'); |
| 65 | expect(frame.ok).toBe(true); |
| 66 | if (frame.ok) expect(frame.value).toEqual([1, 2, 3]); |
| 67 | }); |
| 68 | }); |