From d7400d250be4bcc0bee9f6829393bfdfc30e4e4c Mon Sep 17 00:00:00 2001 From: Jinwoo-H Date: Mon, 7 Sep 2026 04:40:20 -0400 Subject: [PATCH] test(mobile): drop the collapsed host/shell roundtrip matrices Each `it.each([[true, true]])` ran a single case while advertising a matrix, and the branches guarded by `host && shell` were dead. Naming the case says what the test proves, and deleting the constant branches leaves only the lane that runs. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb --- ...ost-native-chat-mutation-roundtrip.test.ts | 38 ++++----- ...ile-web-host-native-chat-roundtrip.test.ts | 83 ++++++++----------- .../mobile-web-host-stream-roundtrip.test.ts | 60 ++++++-------- 3 files changed, 78 insertions(+), 103 deletions(-) diff --git a/mobile/src/mobile-web/mobile-web-host-native-chat-mutation-roundtrip.test.ts b/mobile/src/mobile-web/mobile-web-host-native-chat-mutation-roundtrip.test.ts index a9692ec3bf8..af2fcc1d27e 100644 --- a/mobile/src/mobile-web/mobile-web-host-native-chat-mutation-roundtrip.test.ts +++ b/mobile/src/mobile-web/mobile-web-host-native-chat-mutation-roundtrip.test.ts @@ -3,8 +3,8 @@ import { nativeChatBridgeFixture } from './mobile-web-host-native-chat-test-fixt afterEach(() => vi.restoreAllMocks()) -async function fixture(host = true, shell = true) { - const f = nativeChatBridgeFixture(host, shell) +async function fixture() { + const f = nativeChatBridgeFixture() const workspaceId = (await f.client.workspaceSnapshot({ limit: 10 })).workspaces[0]!.id const snapshot = await f.client.sessionSnapshot({ workspaceId }) const tab = snapshot.tabs.find((tab) => tab.type === 'terminal')! @@ -18,8 +18,8 @@ async function fixture(host = true, shell = true) { } } describe('generic native-chat actions', () => { - it.each([[true, true]])('host=%s shell=%s uses a compatible action lane', async (host, shell) => { - const f = await fixture(host, shell) + it('uses the generic mutate lane instead of terminal.send', async () => { + const f = await fixture() const result = await f.client.nativeChat.sendMessage( { ...f.payload, text: 'hello' }, undefined, @@ -28,23 +28,19 @@ describe('generic native-chat actions', () => { expect(result.outcome).toBe('accepted') expect( f.sendRequest.mock.calls.filter(([name]) => name === 'mobileWeb.nativeChat.mutate') - ).toHaveLength(host && shell ? 1 : 0) - expect(f.sendRequest.mock.calls.filter(([name]) => name === 'terminal.send')).toHaveLength( - host && shell ? 0 : 1 - ) - if (host && shell) { - expect(result).toMatchObject({ futureReceipt: { revision: 2 } }) - const [, params] = f.sendRequest.mock.calls.find( - ([name]) => name === 'mobileWeb.nativeChat.mutate' - )! - expect(params).toMatchObject({ - action: 'sendMessage', - text: 'hello', - resourceId: 'opaque-resource' - }) - expect(params).not.toHaveProperty('sessionId') - expect(params).not.toHaveProperty('deadline') - } + ).toHaveLength(1) + expect(f.sendRequest.mock.calls.filter(([name]) => name === 'terminal.send')).toHaveLength(0) + expect(result).toMatchObject({ futureReceipt: { revision: 2 } }) + const [, params] = f.sendRequest.mock.calls.find( + ([name]) => name === 'mobileWeb.nativeChat.mutate' + )! + expect(params).toMatchObject({ + action: 'sendMessage', + text: 'hello', + resourceId: 'opaque-resource' + }) + expect(params).not.toHaveProperty('sessionId') + expect(params).not.toHaveProperty('deadline') f.client.dispose() }) it.each(['respond', 'stop', 'prepareCommit'] as const)( diff --git a/mobile/src/mobile-web/mobile-web-host-native-chat-roundtrip.test.ts b/mobile/src/mobile-web/mobile-web-host-native-chat-roundtrip.test.ts index 8bf0aee7ecd..026b3f8a5c8 100644 --- a/mobile/src/mobile-web/mobile-web-host-native-chat-roundtrip.test.ts +++ b/mobile/src/mobile-web/mobile-web-host-native-chat-roundtrip.test.ts @@ -4,8 +4,8 @@ import { MOBILE_WEB_BRIDGE_ROUNDTRIP_CONTEXT } from './mobile-web-bridge-roundtr import { nativeChatBridgeFixture as fixture } from './mobile-web-host-native-chat-test-fixture' describe('native-chat generic read migration', () => { - it.each([[true, true]])('host=%s shell=%s', async (host, shell) => { - const f = fixture(host, shell) + it('reads native chat through the generic host lane', async () => { + const f = fixture() const workspaceId = (await f.client.workspaceSnapshot({ limit: 10 })).workspaces[0]!.id const session = await f.client.sessionSnapshot({ workspaceId }) const tab = session.tabs.find((tab) => tab.type === 'terminal')! @@ -17,43 +17,34 @@ describe('native-chat generic read migration', () => { tab.id ) expect(result.messages[0].blocks[0]).toMatchObject({ type: 'text', text: 'hello' }) - if (host && shell) { - const pageSession = boundDocument(f) - expect(result).toEqual(f.transcript) - expect(f.sendRequest).toHaveBeenCalledWith( - 'mobileWeb.nativeChat.bind', - { - worktree: 'id:host-workspace', - pageSession, - tabId: 'tab' - }, - expect.objectContaining({ beforeSend: expect.any(Function) }) - ) - expect(f.sendRequest).toHaveBeenCalledWith( - 'mobileWeb.nativeChat.read', - { - worktree: 'id:host-workspace', - pageSession, - resourceId: 'opaque-resource', - read: { limit: 20 } - }, - expect.objectContaining({ beforeSend: expect.any(Function) }) - ) - expect(f.sendRequest.mock.calls.some(([method]) => method === 'nativeChat.readSession')).toBe( - false - ) - } else { - expect( - f.sendRequest.mock.calls.some(([method]) => method === 'mobileWeb.nativeChat.bind') - ).toBe(false) - expect(f.sendRequest.mock.calls.some(([method]) => method === 'nativeChat.readSession')).toBe( - true - ) - } + const pageSession = boundDocument(f) + expect(result).toEqual(f.transcript) + expect(f.sendRequest).toHaveBeenCalledWith( + 'mobileWeb.nativeChat.bind', + { + worktree: 'id:host-workspace', + pageSession, + tabId: 'tab' + }, + expect.objectContaining({ beforeSend: expect.any(Function) }) + ) + expect(f.sendRequest).toHaveBeenCalledWith( + 'mobileWeb.nativeChat.read', + { + worktree: 'id:host-workspace', + pageSession, + resourceId: 'opaque-resource', + read: { limit: 20 } + }, + expect.objectContaining({ beforeSend: expect.any(Function) }) + ) + expect(f.sendRequest.mock.calls.some(([method]) => method === 'nativeChat.readSession')).toBe( + false + ) expect(JSON.stringify(f.shellMessages)).not.toContain('private-session') }) - it.each([[true, true]])('stream host=%s shell=%s', async (host, shell) => { - const f = fixture(host, shell) + it('streams native chat through the generic host lane', async () => { + const f = fixture() const workspaceId = (await f.client.workspaceSnapshot({ limit: 10 })).workspaces[0]!.id const session = await f.client.sessionSnapshot({ workspaceId }) const tab = session.tabs[0] @@ -68,21 +59,15 @@ describe('native-chat generic read migration', () => { vi.fn() ) await subscription.ready - const generic = host && shell - expect(f.subscribe.mock.calls[0][0]).toBe( - generic ? 'mobileWeb.nativeChat.subscribe' : 'nativeChat.subscribe' - ) + expect(f.subscribe.mock.calls[0][0]).toBe('mobileWeb.nativeChat.subscribe') const event = { type: 'snapshot', ...f.transcript } f.emit(event) await vi.waitFor(() => expect(onEvent).toHaveBeenCalledOnce()) - if (generic) { - const pageSession = boundDocument(f) - expect(onEvent).toHaveBeenCalledWith(event) - expect(f.subscribe.mock.calls[0][1]).toMatchObject({ - pageSession, - resourceId: 'opaque-resource' - }) - } + expect(onEvent).toHaveBeenCalledWith(event) + expect(f.subscribe.mock.calls[0][1]).toMatchObject({ + pageSession: boundDocument(f), + resourceId: 'opaque-resource' + }) subscription.unsubscribe() expect(f.unsubscribe).toHaveBeenCalledOnce() }) diff --git a/mobile/src/mobile-web/mobile-web-host-stream-roundtrip.test.ts b/mobile/src/mobile-web/mobile-web-host-stream-roundtrip.test.ts index 5c667534568..4b0c7e4c523 100644 --- a/mobile/src/mobile-web/mobile-web-host-stream-roundtrip.test.ts +++ b/mobile/src/mobile-web/mobile-web-host-stream-roundtrip.test.ts @@ -3,7 +3,7 @@ import type { RpcClient } from '../transport/rpc-client' import { createMobileWebBridgeRoundtripFixture } from './mobile-web-bridge-roundtrip-fixture' import { MOBILE_WEB_PRODUCTION_GRANTS } from './mobile-web-production-grants' -function fixture(catalogAvailable = true, genericShell = true) { +function fixture() { let emit: (event: unknown) => void = () => {} const unsubscribe = vi.fn() const subscribe = vi.fn((_method, _params, listener) => { @@ -21,44 +21,40 @@ function fixture(catalogAvailable = true, genericShell = true) { } } } - return catalogAvailable - ? { - ok: true, - result: { - grants: [ - { - method: 'mobileWeb.files.watch', - mode: 'subscription', - workspaceParam: 'worktree', - unsubscribeMethod: 'files.unwatch', - maxRequestBytes: 1024, - maxResponseBytes: 512 * 1024 - }, - { - method: 'future.events', - mode: 'subscription', - workspaceParam: 'scope', - unsubscribeMethod: 'future.release', - maxRequestBytes: 1024, - maxResponseBytes: 512 * 1024 - } - ] + return { + ok: true, + result: { + grants: [ + { + method: 'mobileWeb.files.watch', + mode: 'subscription', + workspaceParam: 'worktree', + unsubscribeMethod: 'files.unwatch', + maxRequestBytes: 1024, + maxResponseBytes: 512 * 1024 + }, + { + method: 'future.events', + mode: 'subscription', + workspaceParam: 'scope', + unsubscribeMethod: 'future.release', + maxRequestBytes: 1024, + maxResponseBytes: 512 * 1024 } - } - : { ok: false, error: { code: 'method_not_found', message: 'Old host' } } + ] + } + } }) const bridge = createMobileWebBridgeRoundtripFixture({ - grants: MOBILE_WEB_PRODUCTION_GRANTS.filter( - (grant) => genericShell || grant.operation !== 'hostSubscribe' - ), + grants: MOBILE_WEB_PRODUCTION_GRANTS, rpcClient: { sendRequest, subscribe } as unknown as RpcClient }) return { ...bridge, subscribe, unsubscribe, emit: (event: unknown) => emit(event) } } describe('generic subscription bridge compatibility', () => { - it.each([[true, true]])('source-control catalog=%s shell=%s', async (catalog, shell) => { - const f = fixture(catalog, shell) + it('subscribes to source control through the generic shell lane', async () => { + const f = fixture() const workspace = (await f.client.workspaceSnapshot({ limit: 10 })).workspaces[0]!.id const onEvent = vi.fn() const onError = vi.fn() @@ -68,11 +64,9 @@ describe('generic subscription bridge compatibility', () => { onError ) await subscription.ready - const generic = catalog && shell - expect(f.subscribe.mock.calls[0]?.[0]).toBe(generic ? 'mobileWeb.files.watch' : 'files.watch') + expect(f.subscribe.mock.calls[0]?.[0]).toBe('mobileWeb.files.watch') f.emit({ type: 'changed', - ...(generic ? {} : { worktree: 'id:host-workspace' }), events: [], futureField: 'new' })