import { describe, expect, test } from 'bun:test' /** * Tests for the pendingPermissionHandlers cleanup pattern used in * useReplBridge.tsx. The handlers Map tracks in-flight permission * requests; the cleanup function must clear it on unmount to release * closures that capture React state. * * The actual hook is deeply integrated with React/bridge lifecycle, * so these tests validate the Map management pattern in isolation. */ type PermissionHandler = (response: { approved: boolean }) => void function createPermissionHandlersMap() { const handlers = new Map() return { handlers, onResponse(requestId: string, handler: PermissionHandler): () => void { handlers.set(requestId, handler) return () => { handlers.delete(requestId) } }, handleResponse(requestId: string, response: { approved: boolean }): boolean { const handler = handlers.get(requestId) if (!handler) return false handlers.delete(requestId) handler(response) return true }, cleanup(): void { handlers.clear() }, size(): number { return handlers.size }, } } describe('pendingPermissionHandlers cleanup pattern', () => { test('onResponse registers a handler', () => { const map = createPermissionHandlersMap() map.onResponse('req-1', () => {}) expect(map.size()).toBe(1) }) test('onResponse returns a cancel function', () => { const map = createPermissionHandlersMap() const cancel = map.onResponse('req-1', () => {}) expect(map.size()).toBe(1) cancel() expect(map.size()).toBe(0) }) test('handleResponse dispatches to handler and removes it', () => { const map = createPermissionHandlersMap() let received: { approved: boolean } | null = null map.onResponse('req-1', (resp) => { received = resp }) const dispatched = map.handleResponse('req-1', { approved: true }) expect(dispatched).toBe(true) expect(received as unknown as { approved: boolean }).toEqual({ approved: true }) expect(map.size()).toBe(0) }) test('handleResponse returns false for unknown requestId', () => { const map = createPermissionHandlersMap() const dispatched = map.handleResponse('unknown', { approved: true }) expect(dispatched).toBe(false) }) test('cleanup clears all registered handlers', () => { const map = createPermissionHandlersMap() map.onResponse('req-1', () => {}) map.onResponse('req-2', () => {}) map.onResponse('req-3', () => {}) expect(map.size()).toBe(3) map.cleanup() expect(map.size()).toBe(0) }) test('handlers are not dispatched after cleanup', () => { const map = createPermissionHandlersMap() let called = false map.onResponse('req-1', () => { called = true }) map.cleanup() // Late-arriving response after cleanup should not find a handler const dispatched = map.handleResponse('req-1', { approved: true }) expect(dispatched).toBe(false) expect(called).toBe(false) }) test('cancel function is a no-op after cleanup', () => { const map = createPermissionHandlersMap() const cancel = map.onResponse('req-1', () => {}) map.cleanup() // Should not throw expect(() => cancel()).not.toThrow() }) test('cleanup can be called multiple times safely', () => { const map = createPermissionHandlersMap() map.onResponse('req-1', () => {}) map.cleanup() map.cleanup() map.cleanup() expect(map.size()).toBe(0) }) })