| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import * as Protocol from '../../generated/protocol.js'; |
| import * as TextUtils from '../../models/text_utils/text_utils.js'; |
| import {expectCookie} from '../../testing/Cookies.js'; |
| import {createTarget} from '../../testing/EnvironmentHelpers.js'; |
| import { |
| describeWithMockConnection, |
| setMockConnectionResponseHandler, |
| } from '../../testing/MockConnection.js'; |
| import * as Platform from '../platform/platform.js'; |
| |
| import * as SDK from './sdk.js'; |
| |
| const {urlString} = Platform.DevToolsPath; |
| |
| describe('NetworkRequest', () => { |
| it('can parse statusText from the first line of responseReceivedExtraInfo\'s headersText', () => { |
| assert.strictEqual( |
| SDK.NetworkRequest.NetworkRequest.parseStatusTextFromResponseHeadersText('HTTP/1.1 304 not modified'), |
| 'not modified'); |
| assert.strictEqual( |
| SDK.NetworkRequest.NetworkRequest.parseStatusTextFromResponseHeadersText('HTTP/1.1 200 OK'), 'OK'); |
| assert.strictEqual( |
| SDK.NetworkRequest.NetworkRequest.parseStatusTextFromResponseHeadersText('HTTP/1.1 200 OK\r\n\r\nfoo: bar\r\n'), |
| 'OK'); |
| }); |
| |
| it('parses response cookies from headers', () => { |
| const request = SDK.NetworkRequest.NetworkRequest.createWithoutBackendRequest( |
| 'requestId', urlString`url`, urlString`documentURL`, null); |
| request.addExtraResponseInfo({ |
| blockedResponseCookies: [], |
| responseHeaders: [{name: 'Set-Cookie', value: 'foo=bar'}, {name: 'Set-Cookie', value: 'baz=qux'}], |
| resourceIPAddressSpace: 'Public' as Protocol.Network.IPAddressSpace, |
| } as unknown as SDK.NetworkRequest.ExtraResponseInfo); |
| assert.lengthOf(request.responseCookies, 2); |
| expectCookie(request.responseCookies[0], {name: 'foo', value: 'bar', size: 8}); |
| expectCookie(request.responseCookies[1], {name: 'baz', value: 'qux', size: 7}); |
| }); |
| |
| it('infers status text from status code if none given', () => { |
| const fakeRequest = SDK.NetworkRequest.NetworkRequest.createWithoutBackendRequest( |
| 'fakeRequestId', |
| urlString`url1`, |
| urlString`documentURL`, |
| null, |
| ); |
| fakeRequest.statusCode = 200; |
| |
| assert.strictEqual(fakeRequest.statusText, ''); |
| assert.strictEqual(fakeRequest.getInferredStatusText(), 'OK'); |
| }); |
| |
| it('does not infer status text from unknown status code', () => { |
| const fakeRequest = SDK.NetworkRequest.NetworkRequest.createWithoutBackendRequest( |
| 'fakeRequestId', |
| urlString`url1`, |
| urlString`documentURL`, |
| null, |
| ); |
| fakeRequest.statusCode = 999; |
| |
| assert.strictEqual(fakeRequest.statusText, ''); |
| assert.strictEqual(fakeRequest.getInferredStatusText(), ''); |
| }); |
| |
| it('infers status text only when no status text given', () => { |
| const fakeRequest = SDK.NetworkRequest.NetworkRequest.createWithoutBackendRequest( |
| 'fakeRequestId', |
| urlString`url1`, |
| urlString`documentURL`, |
| null, |
| ); |
| fakeRequest.statusCode = 200; |
| fakeRequest.statusText = 'Prefer me'; |
| |
| assert.strictEqual(fakeRequest.statusText, 'Prefer me'); |
| assert.strictEqual(fakeRequest.getInferredStatusText(), 'Prefer me'); |
| }); |
| |
| it('includes partition key in response cookies', () => { |
| const request = SDK.NetworkRequest.NetworkRequest.createWithoutBackendRequest( |
| 'requestId', urlString`url`, urlString`documentURL`, null); |
| request.addExtraResponseInfo({ |
| blockedResponseCookies: [], |
| responseHeaders: |
| [{name: 'Set-Cookie', value: 'foo=bar'}, {name: 'Set-Cookie', value: 'baz=qux; Secure;Partitioned'}], |
| resourceIPAddressSpace: 'Public' as Protocol.Network.IPAddressSpace, |
| cookiePartitionKey: {topLevelSite: 'partitionKey', hasCrossSiteAncestor: false}, |
| } as unknown as SDK.NetworkRequest.ExtraResponseInfo); |
| assert.lengthOf(request.responseCookies, 2); |
| expectCookie(request.responseCookies[0], {name: 'foo', value: 'bar', size: 8}); |
| expectCookie(request.responseCookies[1], { |
| name: 'baz', |
| value: 'qux', |
| secure: true, |
| partitionKey: {topLevelSite: 'partitionKey', hasCrossSiteAncestor: false}, |
| size: 27, |
| }); |
| }); |
| |
| it('determines whether the response headers have been overridden', () => { |
| const request = SDK.NetworkRequest.NetworkRequest.createWithoutBackendRequest( |
| 'requestId', urlString`url`, urlString`documentURL`, null); |
| request.responseHeaders = [{name: 'foo', value: 'bar'}]; |
| |
| request.originalResponseHeaders = [{name: 'foo', value: 'baz'}]; |
| assert.isTrue(request.hasOverriddenHeaders()); |
| |
| request.originalResponseHeaders = []; |
| assert.isFalse(request.hasOverriddenHeaders()); |
| |
| request.originalResponseHeaders = [{name: 'Foo', value: 'bar'}]; |
| assert.isFalse(request.hasOverriddenHeaders()); |
| |
| request.originalResponseHeaders = [{name: 'Foo', value: 'Bar'}]; |
| assert.isTrue(request.hasOverriddenHeaders()); |
| |
| request.responseHeaders = [{name: 'one', value: 'first'}, {name: 'two', value: 'second'}]; |
| request.originalResponseHeaders = [{name: 'ONE', value: 'first'}, {name: 'Two', value: 'second'}]; |
| assert.isFalse(request.hasOverriddenHeaders()); |
| |
| request.originalResponseHeaders = [{name: 'one', value: 'first'}]; |
| assert.isTrue(request.hasOverriddenHeaders()); |
| |
| request.originalResponseHeaders = [{name: 'two', value: 'second'}, {name: 'one', value: 'first'}]; |
| assert.isFalse(request.hasOverriddenHeaders()); |
| |
| request.originalResponseHeaders = [{name: 'one', value: 'second'}, {name: 'two', value: 'first'}]; |
| assert.isTrue(request.hasOverriddenHeaders()); |
| |
| request.originalResponseHeaders = |
| [{name: 'one', value: 'first'}, {name: 'two', value: 'second'}, {name: 'two', value: 'second'}]; |
| assert.isTrue(request.hasOverriddenHeaders()); |
| }); |
| |
| it('considers duplicate headers which only differ in the order of their values as overridden', () => { |
| const request = SDK.NetworkRequest.NetworkRequest.createWithoutBackendRequest( |
| 'requestId', urlString`url`, urlString`documentURL`, null); |
| request.responseHeaders = [{name: 'duplicate', value: 'first'}, {name: 'duplicate', value: 'second'}]; |
| request.originalResponseHeaders = [{name: 'duplicate', value: 'second'}, {name: 'duplicate', value: 'first'}]; |
| assert.isTrue(request.hasOverriddenHeaders()); |
| }); |
| |
| it('can handle the case of duplicate cookies with only 1 of them being blocked', async () => { |
| const request = SDK.NetworkRequest.NetworkRequest.create( |
| 'requestId' as Protocol.Network.RequestId, urlString`url`, urlString`documentURL`, null, null, null); |
| request.addExtraResponseInfo({ |
| responseHeaders: [{name: 'Set-Cookie', value: 'foo=duplicate; Path=/\nfoo=duplicate; Path=/'}], |
| blockedResponseCookies: [{ |
| blockedReasons: [Protocol.Network.SetCookieBlockedReason.SameSiteNoneInsecure], |
| cookie: null, |
| cookieLine: 'foo=duplicate; Path=/', |
| }], |
| resourceIPAddressSpace: Protocol.Network.IPAddressSpace.Public, |
| statusCode: undefined, |
| cookiePartitionKey: undefined, |
| cookiePartitionKeyOpaque: undefined, |
| exemptedResponseCookies: undefined, |
| }); |
| |
| assert.deepEqual( |
| request.responseCookies.map(cookie => cookie.getCookieLine()), |
| ['foo=duplicate; Path=/', 'foo=duplicate; Path=/']); |
| assert.deepEqual(request.blockedResponseCookies(), [{ |
| blockedReasons: [Protocol.Network.SetCookieBlockedReason.SameSiteNoneInsecure], |
| cookie: null, |
| cookieLine: 'foo=duplicate; Path=/', |
| }]); |
| assert.deepEqual( |
| request.nonBlockedResponseCookies().map(cookie => cookie.getCookieLine()), ['foo=duplicate; Path=/']); |
| }); |
| |
| it('can handle the case of exempted cookies', async () => { |
| const request = SDK.NetworkRequest.NetworkRequest.create( |
| 'requestId' as Protocol.Network.RequestId, urlString`url`, urlString`documentURL`, null, null, null); |
| |
| const cookie = new SDK.Cookie.Cookie('name', 'value'); |
| cookie.addAttribute(SDK.Cookie.Attribute.SAME_SITE, 'None'); |
| cookie.addAttribute(SDK.Cookie.Attribute.SECURE, true); |
| cookie.setCookieLine('name=value; Path=/; SameSite=None; Secure;'); |
| request.addExtraResponseInfo({ |
| responseHeaders: [{name: 'Set-Cookie', value: cookie.getCookieLine() as string}], |
| blockedResponseCookies: [], |
| resourceIPAddressSpace: Protocol.Network.IPAddressSpace.Public, |
| statusCode: undefined, |
| cookiePartitionKey: undefined, |
| cookiePartitionKeyOpaque: undefined, |
| exemptedResponseCookies: [{ |
| cookie, |
| cookieLine: cookie.getCookieLine() as string, |
| exemptionReason: Protocol.Network.CookieExemptionReason.TPCDHeuristics, |
| }], |
| }); |
| |
| assert.deepEqual( |
| request.responseCookies.map(cookie => cookie.getCookieLine()), ['name=value; Path=/; SameSite=None; Secure;']); |
| assert.deepEqual( |
| request.nonBlockedResponseCookies().map(cookie => cookie.getCookieLine()), |
| ['name=value; Path=/; SameSite=None; Secure;']); |
| assert.deepEqual( |
| request.exemptedResponseCookies().map(cookie => cookie.cookie.getCookieLine()), |
| ['name=value; Path=/; SameSite=None; Secure;']); |
| assert.deepEqual( |
| request.exemptedResponseCookies().map(cookie => cookie.exemptionReason), |
| [Protocol.Network.CookieExemptionReason.TPCDHeuristics]); |
| |
| request.addExtraRequestInfo({ |
| blockedRequestCookies: [], |
| requestHeaders: [], |
| includedRequestCookies: [{exemptionReason: Protocol.Network.CookieExemptionReason.EnterprisePolicy, cookie}], |
| connectTiming: {requestTime: 0}, |
| }); |
| |
| assert.deepEqual( |
| request.includedRequestCookies().map(included => included.cookie.getCookieLine()), |
| ['name=value; Path=/; SameSite=None; Secure;']); |
| assert.deepEqual( |
| request.includedRequestCookies().map(included => included.exemptionReason), |
| [Protocol.Network.CookieExemptionReason.EnterprisePolicy]); |
| }); |
| |
| it('preserves order of headers in case of duplicates', () => { |
| const request = SDK.NetworkRequest.NetworkRequest.createWithoutBackendRequest( |
| 'requestId', urlString`url`, urlString`documentURL`, null); |
| const responseHeaders = [{name: '1ab', value: 'middle'}, {name: '1aB', value: 'last'}]; |
| request.addExtraResponseInfo({ |
| blockedResponseCookies: [], |
| responseHeaders, |
| resourceIPAddressSpace: 'Public' as Protocol.Network.IPAddressSpace, |
| } as unknown as SDK.NetworkRequest.ExtraResponseInfo); |
| assert.deepEqual(request.sortedResponseHeaders, responseHeaders); |
| }); |
| |
| it('treats multiple headers with the same name the same as single header with comma-separated values', () => { |
| const request = SDK.NetworkRequest.NetworkRequest.createWithoutBackendRequest( |
| 'requestId', urlString`url`, urlString`documentURL`, null); |
| request.responseHeaders = [{name: 'duplicate', value: 'first, second'}]; |
| request.originalResponseHeaders = [{name: 'duplicate', value: 'first'}, {name: 'duplicate', value: 'second'}]; |
| assert.isFalse(request.hasOverriddenHeaders()); |
| }); |
| }); |
| |
| describeWithMockConnection('NetworkRequest', () => { |
| let networkManagerForRequestStub: sinon.SinonStub; |
| let cookie: SDK.Cookie.Cookie; |
| let addBlockedCookieSpy: sinon.SinonSpy; |
| let target: SDK.Target.Target; |
| |
| beforeEach(() => { |
| target = createTarget(); |
| const networkManager = target.model(SDK.NetworkManager.NetworkManager); |
| assert.exists(networkManager); |
| networkManagerForRequestStub = sinon.stub(SDK.NetworkManager.NetworkManager, 'forRequest').returns(networkManager); |
| cookie = new SDK.Cookie.Cookie('name', 'value'); |
| addBlockedCookieSpy = sinon.spy(SDK.CookieModel.CookieModel.prototype, 'addBlockedCookie'); |
| }); |
| |
| afterEach(() => { |
| networkManagerForRequestStub.restore(); |
| }); |
| |
| it('adds blocked response cookies to - and removes exempted cookies from cookieModel', async () => { |
| const removeBlockedCookieSpy = sinon.spy(SDK.CookieModel.CookieModel.prototype, 'removeBlockedCookie'); |
| setMockConnectionResponseHandler('Network.getCookies', () => ({cookies: []})); |
| const cookieModel = target.model(SDK.CookieModel.CookieModel); |
| assert.exists(cookieModel); |
| const url = urlString`url`; |
| const request = SDK.NetworkRequest.NetworkRequest.create( |
| 'requestId' as Protocol.Network.RequestId, url, urlString`documentURL`, null, null, null); |
| |
| request.addExtraResponseInfo({ |
| responseHeaders: [{name: 'Set-Cookie', value: 'name=value; Path=/'}], |
| blockedResponseCookies: [{ |
| blockedReasons: [Protocol.Network.SetCookieBlockedReason.ThirdPartyPhaseout], |
| cookie, |
| cookieLine: 'name=value; Path=/', |
| }], |
| resourceIPAddressSpace: Protocol.Network.IPAddressSpace.Public, |
| statusCode: undefined, |
| cookiePartitionKey: undefined, |
| cookiePartitionKeyOpaque: undefined, |
| exemptedResponseCookies: undefined, |
| }); |
| assert.isTrue(addBlockedCookieSpy.calledOnceWith(cookie, [ |
| { |
| attribute: null, |
| uiString: |
| 'Setting this cookie was blocked either because of Chrome flags or browser configuration. Learn more in the Issues panel.', |
| }, |
| ])); |
| assert.deepEqual(await cookieModel.getCookiesForDomain(''), [cookie]); |
| |
| request.addExtraResponseInfo({ |
| responseHeaders: [{name: 'Set-Cookie', value: 'name=value; Path=/'}], |
| blockedResponseCookies: [], |
| resourceIPAddressSpace: Protocol.Network.IPAddressSpace.Public, |
| statusCode: undefined, |
| cookiePartitionKey: undefined, |
| cookiePartitionKeyOpaque: undefined, |
| exemptedResponseCookies: [{ |
| cookie, |
| cookieLine: cookie.getCookieLine() as string, |
| exemptionReason: Protocol.Network.CookieExemptionReason.TPCDHeuristics, |
| }], |
| }); |
| assert.isTrue(removeBlockedCookieSpy.calledOnceWith(cookie)); |
| assert.isEmpty(await cookieModel.getCookiesForDomain('')); |
| }); |
| }); |
| |
| describeWithMockConnection('ServerSentEvents', () => { |
| let target: SDK.Target.Target; |
| let networkManager: SDK.NetworkManager.NetworkManager; |
| |
| beforeEach(() => { |
| target = createTarget(); |
| networkManager = target.model(SDK.NetworkManager.NetworkManager) as SDK.NetworkManager.NetworkManager; |
| }); |
| |
| it('sends EventSourceMessageAdded events for EventSource text/event-stream', () => { |
| networkManager.dispatcher.requestWillBeSent({ |
| requestId: '1' as Protocol.Network.RequestId, |
| request: { |
| url: 'https://example.com/sse', |
| }, |
| type: 'EventSource', |
| } as Protocol.Network.RequestWillBeSentEvent); |
| networkManager.dispatcher.responseReceived({ |
| requestId: '1' as Protocol.Network.RequestId, |
| response: { |
| url: 'https://example.com/sse', |
| mimeType: 'text/event-stream', |
| } as Protocol.Network.Response, |
| } as Protocol.Network.ResponseReceivedEvent); |
| |
| const networkEvents: SDK.NetworkRequest.EventSourceMessage[] = []; |
| networkManager.requestForId('1')!.addEventListener( |
| SDK.NetworkRequest.Events.EVENT_SOURCE_MESSAGE_ADDED, ({data}) => networkEvents.push(data)); |
| |
| networkManager.dispatcher.eventSourceMessageReceived({ |
| requestId: '1' as Protocol.Network.RequestId, |
| timestamp: 21, |
| data: 'foo', |
| eventId: 'fooId', |
| eventName: 'fooName', |
| }); |
| networkManager.dispatcher.eventSourceMessageReceived({ |
| requestId: '1' as Protocol.Network.RequestId, |
| timestamp: 42, |
| data: 'bar', |
| eventId: 'barId', |
| eventName: 'barName', |
| }); |
| |
| assert.lengthOf(networkEvents, 2); |
| assert.deepEqual(networkEvents[0], {data: 'foo', eventId: 'fooId', eventName: 'fooName', time: 21}); |
| assert.deepEqual(networkEvents[1], {data: 'bar', eventId: 'barId', eventName: 'barName', time: 42}); |
| }); |
| |
| it('sends EventSourceMessageAdded events for raw text/event-stream', async () => { |
| setMockConnectionResponseHandler('Network.streamResourceContent', () => ({ |
| getError() { |
| return undefined; |
| }, |
| bufferedData: '', |
| })); |
| networkManager.dispatcher.requestWillBeSent({ |
| requestId: '1' as Protocol.Network.RequestId, |
| request: { |
| url: 'https://example.com/sse', |
| }, |
| type: 'Fetch', |
| } as Protocol.Network.RequestWillBeSentEvent); |
| networkManager.dispatcher.responseReceived({ |
| requestId: '1' as Protocol.Network.RequestId, |
| response: { |
| url: 'https://example.com/sse', |
| mimeType: 'text/event-stream', |
| } as Protocol.Network.Response, |
| } as Protocol.Network.ResponseReceivedEvent); |
| |
| const networkEvents: SDK.NetworkRequest.EventSourceMessage[] = []; |
| const {promise: twoEventsReceivedPromise, resolve} = Promise.withResolvers<void>(); |
| networkManager.requestForId('1')!.addEventListener( |
| SDK.NetworkRequest.Events.EVENT_SOURCE_MESSAGE_ADDED, ({data}) => { |
| networkEvents.push(data); |
| if (networkEvents.length === 2) { |
| resolve(); |
| } |
| }); |
| |
| const message = ` |
| id: fooId |
| event: fooName |
| data: foo |
| |
| id: barId |
| event: barName |
| data: bar\n\n`; |
| |
| // Send `message` piecemeal via dataReceived events. |
| let time = 0; |
| for (const c of message) { |
| networkManager.dispatcher.dataReceived({ |
| requestId: '1' as Protocol.Network.RequestId, |
| dataLength: 1, |
| encodedDataLength: 1, |
| timestamp: time++, |
| data: window.btoa(c), |
| }); |
| } |
| |
| await twoEventsReceivedPromise; |
| |
| // Omit time from expectation as the dataReceived loop is racing against the text decoder. |
| assert.lengthOf(networkEvents, 2); |
| assert.deepInclude(networkEvents[0], {data: 'foo', eventId: 'fooId', eventName: 'fooName'}); |
| assert.deepInclude(networkEvents[1], {data: 'bar', eventId: 'barId', eventName: 'barName'}); |
| }); |
| }); |
| |
| describeWithMockConnection('requestStreamingContent', () => { |
| let target: SDK.Target.Target; |
| let networkManager: SDK.NetworkManager.NetworkManager; |
| |
| beforeEach(() => { |
| target = createTarget(); |
| networkManager = target.model(SDK.NetworkManager.NetworkManager) as SDK.NetworkManager.NetworkManager; |
| }); |
| |
| it('retrieves the full response body for finished requests', () => { |
| networkManager.dispatcher.requestWillBeSent({ |
| requestId: '1' as Protocol.Network.RequestId, |
| request: { |
| url: 'https://example.com/index.html', |
| }, |
| type: 'Document', |
| } as Protocol.Network.RequestWillBeSentEvent); |
| networkManager.dispatcher.responseReceived({ |
| requestId: '1' as Protocol.Network.RequestId, |
| response: { |
| url: 'https://example.com/index.html', |
| mimeType: 'text/html', |
| } as Protocol.Network.Response, |
| } as Protocol.Network.ResponseReceivedEvent); |
| networkManager.dispatcher.loadingFinished({ |
| requestId: '1' as Protocol.Network.RequestId, |
| } as Protocol.Network.LoadingFinishedEvent); |
| |
| const responseBodySpy = sinon.spy(target.networkAgent(), 'invoke_getResponseBody'); |
| |
| void networkManager.requestForId('1')!.requestStreamingContent(); |
| |
| sinon.assert.calledOnce(responseBodySpy); |
| }); |
| |
| it('streams the full response body for in-flight requests', () => { |
| networkManager.dispatcher.requestWillBeSent({ |
| requestId: '1' as Protocol.Network.RequestId, |
| request: { |
| url: 'https://example.com/index.html', |
| }, |
| type: 'Document', |
| } as Protocol.Network.RequestWillBeSentEvent); |
| networkManager.dispatcher.responseReceived({ |
| requestId: '1' as Protocol.Network.RequestId, |
| response: { |
| url: 'https://example.com/index.html', |
| mimeType: 'text/html', |
| } as Protocol.Network.Response, |
| } as Protocol.Network.ResponseReceivedEvent); |
| |
| const responseBodySpy = sinon.spy(target.networkAgent(), 'invoke_streamResourceContent'); |
| |
| void networkManager.requestForId('1')!.requestStreamingContent(); |
| |
| sinon.assert.calledOnce(responseBodySpy); |
| }); |
| |
| it('sends ChunkAdded events when new data is received', async () => { |
| networkManager.dispatcher.requestWillBeSent({ |
| requestId: '1' as Protocol.Network.RequestId, |
| request: { |
| url: 'https://example.com/index.html', |
| }, |
| type: 'Document', |
| } as Protocol.Network.RequestWillBeSentEvent); |
| networkManager.dispatcher.responseReceived({ |
| requestId: '1' as Protocol.Network.RequestId, |
| response: { |
| url: 'https://example.com/index.html', |
| mimeType: 'text/html', |
| } as Protocol.Network.Response, |
| } as Protocol.Network.ResponseReceivedEvent); |
| |
| sinon.stub(SDK.NetworkManager.NetworkManager, 'streamResponseBody') |
| .returns(Promise.resolve(new TextUtils.ContentData.ContentData('Zm9v', true, 'text/html'))); |
| |
| const maybeStreamingContent = await networkManager.requestForId('1')!.requestStreamingContent(); |
| assert.isFalse(TextUtils.StreamingContentData.isError(maybeStreamingContent)); |
| const streamingContent = maybeStreamingContent as TextUtils.StreamingContentData.StreamingContentData; |
| const eventPromise = streamingContent.once(TextUtils.StreamingContentData.Events.CHUNK_ADDED); |
| |
| networkManager.dispatcher.dataReceived({ |
| requestId: '1' as Protocol.Network.RequestId, |
| data: 'YmFy', |
| dataLength: 4, |
| encodedDataLength: 4, |
| timestamp: 42, |
| }); |
| |
| const {chunk} = await eventPromise; |
| assert.strictEqual(chunk, 'YmFy'); |
| assert.strictEqual(streamingContent.content().text, 'foobar'); |
| }); |
| |
| it('waits for "responseReceived" event to construct the StreamingContentData', async () => { |
| networkManager.dispatcher.requestWillBeSent({ |
| requestId: '1' as Protocol.Network.RequestId, |
| request: { |
| url: 'https://example.com/index.html', |
| }, |
| type: 'Document', |
| } as Protocol.Network.RequestWillBeSentEvent); |
| sinon.stub(target.networkAgent(), 'invoke_streamResourceContent') |
| .returns(Promise.resolve({bufferedData: '', getError: () => undefined})); |
| |
| const streamingContentDataPromise = networkManager.requestForId('1')!.requestStreamingContent(); |
| |
| // Trigger the "responseReceived" on the next event loop tick. |
| setTimeout(() => { |
| networkManager.dispatcher.responseReceived({ |
| requestId: '1' as Protocol.Network.RequestId, |
| response: { |
| url: 'https://example.com/index.html', |
| mimeType: 'text/html', |
| } as Protocol.Network.Response, |
| } as Protocol.Network.ResponseReceivedEvent); |
| }, 0); |
| |
| const maybeStreamingContent = await streamingContentDataPromise; |
| assert.isFalse(TextUtils.StreamingContentData.isError(maybeStreamingContent)); |
| const streamingContent = maybeStreamingContent as TextUtils.StreamingContentData.StreamingContentData; |
| assert.strictEqual(streamingContent.mimeType, 'text/html'); |
| }); |
| }); |