|
| 1 | +import { expect, test, vi } from 'vitest'; |
| 2 | +import { managedLocalRuntimeOwner } from '@agent-device/contracts/platform-runtime'; |
| 3 | +import { withManagedDeviceScope } from '@agent-device/provision-kit/managed-device-scope'; |
| 4 | +import { IOS_SIMULATOR } from './__tests__/device-fixtures.ts'; |
| 5 | +import { ensureBootedSimulator } from './core/simulator.ts'; |
| 6 | +import { createLocalAppleToolProvider, withAppleToolProvider } from './core/tool-provider.ts'; |
| 7 | +import { bindSimulatorReadiness } from './runtime-simulator-readiness.ts'; |
| 8 | + |
| 9 | +test('ordinary simulator operations preserve their binding without a readiness override', () => { |
| 10 | + const operations = { ensureBootedSimulator }; |
| 11 | + expect(bindSimulatorReadiness(operations)).toBe(operations); |
| 12 | +}); |
| 13 | + |
| 14 | +test('bound simulator readiness captures authority and refuses mismatches or failures before local boot', async () => { |
| 15 | + await withAppleToolProvider( |
| 16 | + createLocalAppleToolProvider({ |
| 17 | + runCommand: async () => { |
| 18 | + throw new Error('Unexpected local readiness'); |
| 19 | + }, |
| 20 | + }), |
| 21 | + async () => { |
| 22 | + const device = { ...IOS_SIMULATOR, simulatorSetPath: '/managed/set' }; |
| 23 | + const ensureReady = vi.fn(async () => {}); |
| 24 | + const operations = await withManagedDeviceScope( |
| 25 | + { |
| 26 | + device, |
| 27 | + owner: managedLocalRuntimeOwner('allocator'), |
| 28 | + fence: { token: 'fence', generation: 1 }, |
| 29 | + ensureReady, |
| 30 | + run: async <T>(task: () => Promise<T>) => await task(), |
| 31 | + }, |
| 32 | + async () => bindSimulatorReadiness(Object.freeze({ ensureBootedSimulator })), |
| 33 | + ); |
| 34 | + await operations.ensureBootedSimulator(device); |
| 35 | + expect(ensureReady).toHaveBeenCalledOnce(); |
| 36 | + await expect( |
| 37 | + operations.ensureBootedSimulator({ ...device, simulatorSetPath: undefined }), |
| 38 | + ).rejects.toMatchObject({ details: { reason: 'managed-device-transport-mismatch' } }); |
| 39 | + expect(ensureReady).toHaveBeenCalledOnce(); |
| 40 | + const abort = new AbortController(); |
| 41 | + abort.abort(new Error('cancelled')); |
| 42 | + await expect( |
| 43 | + operations.ensureBootedSimulator(device, { signal: abort.signal }), |
| 44 | + ).rejects.toThrow('cancelled'); |
| 45 | + expect(ensureReady).toHaveBeenCalledOnce(); |
| 46 | + ensureReady.mockRejectedValueOnce(new Error('lease fenced')); |
| 47 | + await expect(operations.ensureBootedSimulator(device)).rejects.toThrow('lease fenced'); |
| 48 | + expect(ensureReady).toHaveBeenCalledTimes(2); |
| 49 | + }, |
| 50 | + ); |
| 51 | +}); |
0 commit comments