cat / goq
clone

turns a linux box into a private steam streaming appliance: plug in, tap your key, play from another computer

1-n-sigls
goq / portal / connection-state.test.mjs
connection-state.test.mjs 8.7K
1import assert from 'node:assert/strict';2import test from 'node:test';34import {5 MEDIA_TRANSPORT_ALLOWLIST,6 newConnectionState,7 normalizeMediaTransport,8} from './connection-state.mjs';910function connectedResult(overrides = {}) {11 return {12 connected: true,13 media_generation: 1,14 audio_available: false,15 audio_generation: null,16 relative_pointer_available: false,17 pointer_position_feedback_available: false,18 absolute_pointer_available: false,19 keyboard_available: true,20 text_available: false,21 gamepad_available: false,22 control_available: true,23 media_transport: 'iroh-moq',24 development_mode: false,25 ...overrides,26 };27}2829function harness(results = [connectedResult()]) {30 const commands = [];31 const attempts = [];32 const statuses = [];33 const events = [];34 let nextResult = 0;35 const state = newConnectionState({36 invokeCommand: async (command, args) => {37 commands.push({ command, args });38 if (command === 'iroh_client_connect') return results[nextResult++];39 return undefined;40 },41 createChannel: class FakeChannel {},42 createAttempt: async ({ createChannel }) => {43 const attempt = {44 id: attempts.length + 1,45 connectionArgs: { frameChannel: new createChannel() },46 };47 attempts.push(attempt);48 events.push(`create:${attempt.id}`);49 return attempt;50 },51 validateConnectedResult: (_result, attempt) => events.push(`validate:${attempt.id}`),52 activateAttempt: (_result, attempt) => events.push(`activate:${attempt.id}`),53 closeAttempt: (attempt, context) => events.push(54 `close:${attempt?.id ?? 'none'}:${context.committed ? 'committed' : 'uncommitted'}`,55 ),56 teardownAttempt: async (attempt) => events.push(`teardown:${attempt?.id ?? 'none'}`),57 beforeDisconnect: async () => events.push('before-disconnect'),58 teardownConnection: async () => events.push('teardown-connection'),59 onStatus: (kind, detail) => statuses.push([kind, detail]),60 onConnected: async ({ attempt }) => events.push(`connected:${attempt.id}`),61 onDisconnected: async () => events.push('disconnected'),62 onFailure: ({ error }) => events.push(`failure:${error.message}`),63 });64 return { state, commands, attempts, statuses, events };65}6667test('pins every Rust diagnostic transport name including preferred iroh-moq', () => {68 assert.deepEqual([...MEDIA_TRANSPORT_ALLOWLIST], [69 'iroh-moq',70 'grouped-v3',71 ]);72 for (const transport of MEDIA_TRANSPORT_ALLOWLIST) {73 assert.equal(normalizeMediaTransport(transport), transport);74 }75 assert.equal(normalizeMediaTransport('iroh-moq'), 'iroh-moq');76 assert.equal(normalizeMediaTransport(null), 'unknown');77});7879test('production mode rejects an empty pin while development mode permits it', async () => {80 const production = harness();81 assert.equal(await production.state.connect({ pin: ' ' }), false);82 assert.deepEqual(production.commands, []);83 assert.deepEqual(production.statuses, [['err', 'enter pin']]);84 assert.equal(production.state.connecting, false);8586 const development = harness([connectedResult({ development_mode: true })]);87 development.state.setDevelopmentMode(true);88 assert.equal(await development.state.connect({ pin: ' ' }), true);89 assert.equal(development.commands[0].args.pin, '');90 assert.deepEqual(development.statuses, [91 ['pending', 'connecting...'],92 ['ok', 'connected · dev direct-node'],93 ]);94});9596test('connect is single-flight', async () => {97 let release;98 const pending = new Promise((resolve) => { release = resolve; });99 let connectCalls = 0;100 const state = newConnectionState({101 invokeCommand: async (command) => {102 if (command === 'iroh_client_connect') {103 connectCalls += 1;104 await pending;105 return connectedResult();106 }107 return undefined;108 },109 });110 const first = state.connect({ pin: '1234' });111 assert.equal(state.connecting, true);112 assert.equal(await state.connect({ pin: '1234' }), false);113 release();114 assert.equal(await first, true);115 assert.equal(connectCalls, 1);116});117118test('invalid connected generations close committed native state exactly once', async () => {119 for (const invalid of [120 connectedResult({ media_generation: 0 }),121 connectedResult({ audio_available: true, audio_generation: 0 }),122 ]) {123 const current = harness([invalid]);124 assert.equal(await current.state.connect({ pin: '1234' }), false);125 assert.deepEqual(current.commands.map(({ command }) => command), [126 'iroh_client_connect',127 'iroh_client_disconnect',128 ]);129 assert.ok(current.events.includes('close:1:committed'));130 assert.match(current.events.at(-1), /^failure:host returned an invalid/);131 }132});133134test('a rejected result tears down without disconnecting uncommitted native state', async () => {135 const current = harness([{ connected: false }]);136 assert.equal(await current.state.connect({ pin: '1234' }), false);137 assert.deepEqual(current.commands.map(({ command }) => command), ['iroh_client_connect']);138 assert.deepEqual(current.events, [139 'create:1',140 'validate:1',141 'close:1:uncommitted',142 'teardown:1',143 ]);144 assert.deepEqual(current.statuses.at(-1), ['err', 'failed']);145});146147test('successful connect normalizes capabilities and forces inconsistent control view-only', async () => {148 const current = harness([connectedResult({149 keyboard_available: false,150 control_available: true,151 })]);152 assert.equal(await current.state.connect({ pin: ' 1234 ' }), true);153 assert.deepEqual(current.state.inputCapabilities, {154 relativePointer: false,155 pointerPositionFeedback: false,156 absolutePointer: false,157 keyboard: false,158 text: false,159 gamepad: false,160 control: false,161 });162 assert.equal(current.state.mediaTransport, 'iroh-moq');163 assert.deepEqual(current.statuses, [164 ['pending', 'connecting...'],165 ['ok', 'connected · view only'],166 ]);167 assert.deepEqual(current.commands[0].args.pin, '1234');168});169170test('disconnect is single-flight and resets capabilities and transport', async () => {171 let release;172 const pending = new Promise((resolve) => { release = resolve; });173 const current = harness();174 assert.equal(await current.state.connect({ pin: '1234' }), true);175 current.events.length = 0;176177 const state = newConnectionState({178 invokeCommand: async (command) => {179 if (command === 'iroh_client_connect') return connectedResult();180 await pending;181 },182 });183 await state.connect({ pin: '1234' });184 const first = state.disconnect();185 assert.equal(state.disconnecting, true);186 assert.equal(await state.disconnect(), false);187 release();188 assert.equal(await first, true);189 assert.equal(state.connected, false);190 assert.equal(state.mediaTransport, 'unknown');191 assert.equal(state.inputCapabilities.control, false);192});193194test('connect disconnect connect creates fresh attempts and channels', async () => {195 const current = harness([connectedResult(), connectedResult({ media_generation: 2 })]);196 assert.equal(await current.state.connect({ pin: '1234' }), true);197 assert.equal(await current.state.disconnect(), true);198 assert.equal(await current.state.connect({ pin: '1234' }), true);199 assert.equal(current.attempts.length, 2);200 assert.notEqual(201 current.attempts[0].connectionArgs.frameChannel,202 current.attempts[1].connectionArgs.frameChannel,203 );204 assert.deepEqual(current.commands.map(({ command }) => command), [205 'iroh_client_connect',206 'iroh_client_disconnect',207 'iroh_client_connect',208 ]);209});210211test('connect failures clear connecting and report lifecycle order', async () => {212 const statuses = [];213 const events = [];214 const state = newConnectionState({215 invokeCommand: async () => { throw new Error('offline'); },216 createAttempt: async () => {217 events.push('create');218 return { connectionArgs: {} };219 },220 closeAttempt: () => events.push('close'),221 teardownAttempt: async () => events.push('teardown'),222 onFailure: ({ error }) => events.push(`failure:${error.message}`),223 onStatus: (kind, detail) => statuses.push(`${kind}:${detail}`),224 });225 assert.equal(await state.connect({ pin: '1234' }), false);226 assert.equal(state.connecting, false);227 assert.deepEqual(events, ['create', 'close', 'teardown', 'failure:offline']);228 assert.deepEqual(statuses, ['pending:connecting...', 'err:error']);229});230231test('connected and disconnected callbacks follow status and teardown boundaries', async () => {232 const current = harness();233 assert.equal(await current.state.connect({ pin: '1234' }), true);234 assert.deepEqual(current.events, ['create:1', 'validate:1', 'activate:1', 'connected:1']);235 current.events.length = 0;236 assert.equal(await current.state.disconnect(), true);237 assert.deepEqual(current.events, ['before-disconnect', 'teardown-connection', 'disconnected']);238 assert.deepEqual(current.statuses.at(-1), ['ok', 'connected']);239});