mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
fix(inspector): restore client console and response bodies
This commit is contained in:
@@ -117,19 +117,9 @@ export function installFetchObserver(
|
||||
responseClone.body,
|
||||
options.maxResponseBodyBytes,
|
||||
options.maxChunkBytes,
|
||||
AbortSignal.any([controller.signal, request.signal]),
|
||||
controller.signal,
|
||||
(data) => { publisher.publish('fetch/response-body-chunk', { requestId, data }) },
|
||||
).then((outcome) => {
|
||||
if (request.signal.aborted) {
|
||||
publisher.publish('fetch/error', {
|
||||
requestId,
|
||||
message: request.signal.reason === undefined
|
||||
? 'AbortError: request aborted during response body capture'
|
||||
: renderError(request.signal.reason),
|
||||
canceled: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
publisher.publish('fetch/end', {
|
||||
requestId,
|
||||
capturedBytes: outcome.capturedBytes,
|
||||
@@ -210,7 +200,7 @@ async function captureBody(
|
||||
}
|
||||
return { capturedBytes, truncated }
|
||||
} catch (error) {
|
||||
return { capturedBytes, truncated, captureError: renderError(error) }
|
||||
return { capturedBytes, truncated: true, captureError: renderError(error) }
|
||||
} finally {
|
||||
signal.removeEventListener('abort', abort)
|
||||
reader.releaseLock()
|
||||
|
||||
@@ -143,8 +143,6 @@ function assertClientEvaluationOptions(request: Parameters<RuntimeBackend['evalu
|
||||
if (request.throwOnSideEffect === true) throw new Error('Client Runtime does not support throwOnSideEffect')
|
||||
if (request.serializationOptions !== undefined) throw new Error('Client Runtime does not support serializationOptions')
|
||||
if (request.disableBreaks === true) throw new Error('Client Runtime does not support disableBreaks')
|
||||
if (request.replMode === true) throw new Error('Client Runtime does not support replMode')
|
||||
if (request.userGesture === true) throw new Error('Client Runtime does not support userGesture')
|
||||
if (request.allowUnsafeEvalBlockedByCSP === true) {
|
||||
throw new Error('Client Runtime cannot bypass the page Content Security Policy')
|
||||
}
|
||||
|
||||
@@ -147,8 +147,28 @@ describe.skipIf(!built)('Inspector built Client in Chromium', () => {
|
||||
const context = event.params?.context as Record<string, unknown> | undefined
|
||||
return String(context?.name).startsWith('Client —')
|
||||
})
|
||||
const contextId = (contextEvent.params?.context as Record<string, unknown>).id
|
||||
const context = contextEvent.params?.context as Record<string, unknown>
|
||||
const contextId = context.id
|
||||
const uniqueContextId = context.uniqueId
|
||||
expect(contextId).toBeTypeOf('number')
|
||||
expect(uniqueContextId).toBeTypeOf('string')
|
||||
|
||||
const evaluated = await cdp.call('Runtime.evaluate', {
|
||||
expression: 'globalThis.__inspectorConsoleEvaluation = { answer: 6 * 7 }',
|
||||
objectGroup: 'console',
|
||||
includeCommandLineAPI: true,
|
||||
silent: false,
|
||||
returnByValue: false,
|
||||
generatePreview: true,
|
||||
userGesture: true,
|
||||
awaitPromise: false,
|
||||
replMode: true,
|
||||
allowUnsafeEvalBlockedByCSP: false,
|
||||
uniqueContextId,
|
||||
})
|
||||
expect(evaluated.error).toBeUndefined()
|
||||
expect(asRecord(evaluated.result?.result).objectId).toMatch(/^runtime:/u)
|
||||
expect(await page.evaluate(() => Reflect.get(globalThis, '__inspectorConsoleEvaluation'))).toEqual({ answer: 42 })
|
||||
|
||||
await page.evaluate(() => {
|
||||
const value = { browser: true, nested: { ready: true } }
|
||||
|
||||
@@ -79,7 +79,7 @@ describe('full fetch observer', () => {
|
||||
expect(payload(records, 'fetch/end')).toMatchObject({ capturedBytes: 4, responseBodyTruncated: true })
|
||||
})
|
||||
|
||||
it('reports cancellation after response headers as a canceled request', async () => {
|
||||
it('retains a truncated response when the caller cancels after response headers', async () => {
|
||||
const records: InspectorRecordInput[] = []
|
||||
Object.defineProperty(globalThis, 'fetch', {
|
||||
value: vi.fn(async (request: Request) => new Response(new ReadableStream<Uint8Array>({
|
||||
@@ -103,9 +103,41 @@ describe('full fetch observer', () => {
|
||||
const response = await fetch('https://example.test/cancel-body', { signal: abort.signal })
|
||||
abort.abort()
|
||||
await expect(response.text()).rejects.toThrow()
|
||||
await vi.waitFor(() => { expect(records.some(record => record.topic === 'fetch/error')).toBe(true) })
|
||||
await vi.waitFor(() => { expect(records.some(record => record.topic === 'fetch/end')).toBe(true) })
|
||||
|
||||
expect(decodeChunks(records, 'fetch/response-body-chunk')).toBe('first')
|
||||
expect(payload(records, 'fetch/end')).toMatchObject({
|
||||
capturedBytes: 5,
|
||||
responseBodyTruncated: true,
|
||||
responseCaptureError: 'AbortError: aborted',
|
||||
})
|
||||
expect(records.some(record => record.topic === 'fetch/error')).toBe(false)
|
||||
})
|
||||
|
||||
it('reports a fetch rejected before response headers as a canceled request', async () => {
|
||||
const records: InspectorRecordInput[] = []
|
||||
Object.defineProperty(globalThis, 'fetch', {
|
||||
value: vi.fn(async (request: Request) => await new Promise<Response>((_resolve, reject) => {
|
||||
request.signal.addEventListener('abort', () => {
|
||||
reject(new DOMException('aborted', 'AbortError'))
|
||||
}, { once: true })
|
||||
})),
|
||||
writable: true,
|
||||
configurable: true,
|
||||
})
|
||||
observer = installFetchObserver({
|
||||
publish(topic: string, payload: InspectorJsonValue, monotonicMs = performance.now()) {
|
||||
records.push({ topic, payload, monotonicMs })
|
||||
},
|
||||
}, { maxRequestBodyBytes: 1_024, maxResponseBodyBytes: 1_024, maxChunkBytes: 4 })
|
||||
const abort = new AbortController()
|
||||
|
||||
const pending = fetch('https://example.test/cancel-before-response', { signal: abort.signal })
|
||||
abort.abort()
|
||||
await expect(pending).rejects.toThrow()
|
||||
|
||||
expect(payload(records, 'fetch/error')).toMatchObject({ canceled: true })
|
||||
expect(records.some(record => record.topic === 'fetch/response')).toBe(false)
|
||||
expect(records.some(record => record.topic === 'fetch/end')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user