fix(test): await Client Console subscription delivery

This commit is contained in:
Tianyi Cui
2026-09-07 11:35:13 +08:00
parent f5302b2b4d
commit 64dfd7a425
3 changed files with 43 additions and 1 deletions
@@ -35,6 +35,8 @@ interface ClientFixtureRequest {
| 'refresh-tree'
| 'remove-fiber'
| 'set-global'
| 'set-ingest-paused'
readonly paused?: boolean
readonly name?: string
readonly value?: InspectorJsonValue
readonly marker?: string
@@ -106,6 +108,13 @@ async function dispatch(message: ClientFixtureRequest): Promise<unknown> {
return undefined
case 'get-tree':
return await service.cordis.getTree()
case 'set-ingest-paused': {
const socket = Reflect.get(source, 'socket') as WebSocket | undefined
if (socket === undefined) throw new Error('Inspector Client ingest socket is unavailable')
if (message.paused) socket.pause()
else socket.resume()
return undefined
}
case 'disconnect': {
const socket = Reflect.get(source, 'socket') as WebSocket | undefined
socket?.terminate()
@@ -98,6 +98,14 @@ export class InspectorClientFixture {
return await this.request({ op: 'get-tree' }) as CordisRuntimeTree
}
/**
* Pause or resume ingest reads without blocking the fixture MessagePort.
* @param paused - Whether incoming WebSocket frames must wait.
*/
async setIngestPaused(paused: boolean): Promise<void> {
await this.request({ op: 'set-ingest-paused', paused })
}
/** Break the active ingest socket while preserving the Client source. */
async disconnect(): Promise<void> {
await this.request({ op: 'disconnect' })
@@ -367,12 +367,27 @@ describe('experimental Inspector real Worker', () => {
client = await InspectorClientFixture.start(inspector.endpoint.client, { label: 'Console Client' })
cdp = await TestCdpClient.connect(inspector.endpoint.webSocketDebuggerUrl)
secondCdp = await TestCdpClient.connect(inspector.endpoint.webSocketDebuggerUrl)
await vi.waitFor(async () => {
const response = await cdp!.call('DSHInspector.getSources')
expect(recordArray(response.result?.sources).some(source => source.kind === 'client')).toBe(true)
})
// The MessagePort can deliver log requests before ingest receives Console subscriptions.
await client.setIngestPaused(true)
await Promise.all([cdp.call('Runtime.enable'), secondCdp.call('Runtime.enable')])
const firstContext = await clientContext(cdp)
const secondContext = await clientContext(secondCdp)
const value = { owner: 'client-console' }
const marker = 'client-console-event'
await client.log(value, marker)
const logged = (async () => {
// Both subscriptions precede this request on the same ingest WebSocket.
// A Client response, unlike Runtime.enable, acknowledges their delivery.
expect((await cdp.call('Runtime.evaluate', {
contextId: firstContext,
expression: 'void 0',
})).error).toBeUndefined()
await client.log(value, marker)
})()
await Promise.all([logged, client.setIngestPaused(false)])
let firstEvent: CdpMessage | undefined
let secondEvent: CdpMessage | undefined
await vi.waitFor(() => {
@@ -398,6 +413,16 @@ describe('experimental Inspector real Worker', () => {
expect((await cdp.call('Runtime.discardConsoleEntries')).error).toBeUndefined()
expect((await cdp.call('Runtime.getProperties', { objectId: firstObjectId })).error).toBeDefined()
expect((await secondCdp.call('Runtime.getProperties', { objectId: secondObjectId })).error).toBeUndefined()
await client.setIngestPaused(true)
await client.close()
client = undefined
await vi.waitFor(() => {
for (const [connection, contextId] of [[cdp!, firstContext], [secondCdp!, secondContext]] as const) {
expect(connection.events.some(event => event.method === 'Runtime.executionContextDestroyed'
&& event.params?.executionContextId === contextId)).toBe(true)
}
})
})
it('projects a chunked Client bundle as read-only Debugger source', async () => {