Skip to content
Merged
71 changes: 70 additions & 1 deletion tests/McpPage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {TextSnapshot} from '../src/TextSnapshot.js';
import type {TextSnapshotNode} from '../src/types.js';
import {createMockPuppeteerPage} from './mocks.js';
import {serverHooks} from './server.js';
import {html, withMcpContext} from './utils.js';
import {getMockRequest, html, withMcpContext} from './utils.js';

describe('replaceHtmlElementsWithUids', () => {
it('does nothing for boolean schemas', () => {
Expand Down Expand Up @@ -577,6 +577,75 @@ describe('McpPage', () => {
});
});

describe('getNetworkRequests', () => {
it('delegates to networkCollector.getData with includePreservedRequests', () => {
const {mcpPage} = createMcpPage();
const stub = sinon.stub(mcpPage.networkCollector, 'getData').returns([]);

mcpPage.getNetworkRequests(true);
sinon.assert.calledOnceWithExactly(stub, true);

mcpPage.getNetworkRequests(false);
sinon.assert.calledWithExactly(stub.secondCall, false);

mcpPage.getNetworkRequests();
sinon.assert.calledWithExactly(stub.thirdCall, undefined);
});
});

describe('getNetworkRequestById', () => {
it('delegates to networkCollector.getById', () => {
const {mcpPage} = createMcpPage();
const mockRequest = getMockRequest();
const stub = sinon
.stub(mcpPage.networkCollector, 'getById')
.returns(mockRequest);

const result = mcpPage.getNetworkRequestById(42);
sinon.assert.calledOnceWithExactly(stub, 42);
assert.strictEqual(result, mockRequest);
});
});

describe('network collection with redirects', () => {
const server = serverHooks();

it('collects real browser requests across server-side and client-side redirects', async () => {
server.addRoute('/redirect', async (_req, res) => {
res.writeHead(302, {
Location: server.getRoute('/redirected'),
});
res.end();
});

server.addHtmlRoute(
'/redirected',
html`<script>
document.location.href = '/redirected-page';
</script>`,
);

server.addHtmlRoute('/redirected-page', html`<main>Redirected</main>`);

await withMcpContext(async (_response, context) => {
const mcpPage = context.getSelectedMcpPage();
await mcpPage.setUpNetworkCollectorForTesting();
const page = mcpPage.pptrPage;

await page.goto(server.getRoute('/redirect'), {
waitUntil: 'networkidle0',
});

const requests = mcpPage.getNetworkRequests(true);
const urls = requests.map(req => req.url());

assert.ok(urls.some(url => url.includes('/redirect')));
assert.ok(urls.some(url => url.includes('/redirected')));
assert.ok(urls.some(url => url.includes('/redirected-page')));
});
});
});

describe('waitForTextOnPage()', () => {
it('finds text on the page', async () => {
await withMcpContext(async (_response, context) => {
Expand Down
26 changes: 26 additions & 0 deletions tests/McpResponse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
import {serverHooks} from './server.js';
import {loadTraceAsBuffer} from './trace-processing/fixtures/load.js';
import {
createHandlerMocks,
createMockAggregatedInfo,
createMockCSSMatchedStyles,
createMockCSSProperty,
Expand Down Expand Up @@ -440,6 +441,31 @@ describe('McpResponse', () => {
});
});

it('forwards includePreservedRequests to page.getNetworkRequests', async () => {
const {page, context} = createHandlerMocks();
page.emulationSettings = {};
page.getNetworkRequests.returns([]);

const responseWithPreserved = new McpResponse(createMockParsedArguments());
responseWithPreserved.setPage(page);
responseWithPreserved.setIncludeNetworkRequests(true, {
includePreservedRequests: true,
});
await responseWithPreserved.handle(context);

sinon.assert.calledOnceWithExactly(page.getNetworkRequests, true);

const responseDefault = new McpResponse(createMockParsedArguments());
responseDefault.setPage(page);
responseDefault.setIncludeNetworkRequests(true);
await responseDefault.handle(context);

sinon.assert.calledWithExactly(
page.getNetworkRequests.secondCall,
undefined,
);
});

it('add network request when attached with POST data', async t => {
await withMcpContext(async (response, context) => {
response.setIncludeNetworkRequests(true);
Expand Down
20 changes: 20 additions & 0 deletions tests/formatters/NetworkFormatter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,26 @@ describe('NetworkFormatter', () => {
),
);
});

it('handles missing response body when inline', async () => {
const response = getMockResponse();
response.buffer = () => Promise.reject(new Error('Evicted'));
const request = getMockRequest({response});

const formatter = await NetworkFormatter.from(request, {
requestId: 1,
fetchData: true,
saveFile: async () => ({filename: ''}),
redactNetworkHeaders: false,
});

const result = formatter.toStringDetailed();
assert.ok(result.includes(`### Response Body\n<not available anymore>`));
assert.strictEqual(
formatter.toJSONDetailed().responseBody,
'<not available anymore>',
);
});
});

describe('toJSON', () => {
Expand Down
49 changes: 0 additions & 49 deletions tests/tools/network.test.js.snapshot

This file was deleted.

Loading
Loading