current commit
251124.3 · test: ensure assertions are reached on more tests
// Flags: --inspect=0 --experimental-network-inspection
'use strict';
const common = require('../common');

common.skipIfInspectorDisabled();

const inspector = require('node:inspector/promises');
const { Network } = require('node:inspector');
const test = require('node:test');
const assert = require('node:assert');
const { waitUntil } = require('../common/inspector-helper');
const { setTimeout } = require('node:timers/promises');

// The complete payload string received by the network agent
const payloadString = `Hello, world${'.'.repeat(4096)}`;

const session = new inspector.Session();
session.connect();
session.post('Network.enable');

async function triggerNetworkEvents(requestId, charset) {
  const url = 'https://example.com';
  Network.requestWillBeSent({
    requestId,
    timestamp: 1,
    wallTime: 1,
    request: {
      url,
      method: 'GET',
      headers: {
        mKey: 'mValue',
      },
    },
  });
  await setTimeout(1);

  Network.responseReceived({
    requestId,
    timestamp: 2,
    type: 'Fetch',
    response: {
      url,
      status: 200,
      statusText: 'OK',
      headers: {
        mKey: 'mValue',
      },
      charset,
    },
  });
  await setTimeout(1);

  const chunk1 = Buffer.from('Hello, ');
  Network.dataReceived({
    requestId,
    timestamp: 3,
    dataLength: chunk1.byteLength,
    encodedDataLength: chunk1.byteLength,
    data: chunk1,
  });
  await setTimeout(1);

  const chunk2 = Buffer.from('world');
  Network.dataReceived({
    requestId,
    timestamp: 4,
    dataLength: chunk2.byteLength,
    encodedDataLength: chunk2.byteLength,
    data: chunk2,
  });
  await setTimeout(1);

  // Test inspector binary conversions with large input
  const chunk3 = Buffer.allocUnsafe(4096).fill('.');
  Network.dataReceived({
    requestId,
    timestamp: 5,
    dataLength: chunk3.byteLength,
    encodedDataLength: chunk3.byteLength,
    data: chunk3,
  });
  await setTimeout(1);

  Network.loadingFinished({
    requestId,
    timestamp: 6,
  });
}

function assertNetworkEvents(session, requestId) {
  session.on('Network.requestWillBeSent', common.mustCall(({ params }) => {
    assert.strictEqual(params.requestId, requestId);
  }));
  session.on('Network.responseReceived', common.mustCall(({ params }) => {
    assert.strictEqual(params.requestId, requestId);
  }));
  const loadingFinishedFuture = waitUntil(session, 'Network.loadingFinished')
    .then(async ([{ params }]) => {
      assert.strictEqual(params.requestId, requestId);
    });

  return loadingFinishedFuture;
}

test('should stream Network.dataReceived with data chunks', async () => {
  session.removeAllListeners();

  const requestId = 'my-req-id-1';
  const chunks = [];
  let totalDataLength = 0;
  const loadingFinishedFuture = assertNetworkEvents(session, requestId);
  const responseReceivedFuture = waitUntil(session, 'Network.responseReceived')
    .then(async () => {
      const { bufferedData } = await session.post('Network.streamResourceContent', {
        requestId,
      });
      const data = Buffer.from(bufferedData, 'base64');
      totalDataLength += data.byteLength;
      chunks.push(data);
    });
  session.on('Network.dataReceived', common.mustCallAtLeast(({ params }) => {
    assert.strictEqual(params.requestId, requestId);
    totalDataLength += params.dataLength;
    chunks.push(Buffer.from(params.data, 'base64'));
  }));

  await triggerNetworkEvents(requestId);
  await responseReceivedFuture;
  await loadingFinishedFuture;

  const data = Buffer.concat(chunks);
  assert.strictEqual(data.byteLength, totalDataLength, data);
  assert.strictEqual(data.toString('utf8'), payloadString);
});

test('Network.streamResourceContent should send all buffered chunks', async () => {
  session.removeAllListeners();

  const requestId = 'my-req-id-2';
  const loadingFinishedFuture = assertNetworkEvents(session, requestId);
  session.on('Network.dataReceived', common.mustNotCall());

  await triggerNetworkEvents(requestId);
  await loadingFinishedFuture;
  const { bufferedData } = await session.post('Network.streamResourceContent', {
    requestId,
  });
  assert.strictEqual(Buffer.from(bufferedData, 'base64').toString('utf8'), payloadString);
});

test('Network.streamResourceContent should reject if request id not found', async () => {
  session.removeAllListeners();

  const requestId = 'unknown-request-id';
  await assert.rejects(session.post('Network.streamResourceContent', {
    requestId,
  }), {
    code: 'ERR_INSPECTOR_COMMAND',
  });
});

test('Network.getResponseBody should send all buffered binary data', async () => {
  session.removeAllListeners();

  const requestId = 'my-req-id-3';
  const loadingFinishedFuture = assertNetworkEvents(session, requestId);
  session.on('Network.dataReceived', common.mustNotCall());

  await triggerNetworkEvents(requestId);
  await loadingFinishedFuture;
  const { body, base64Encoded } = await session.post('Network.getResponseBody', {
    requestId,
  });
  assert.strictEqual(base64Encoded, true);
  assert.strictEqual(body, Buffer.from(payloadString).toString('base64'));
});

test('Network.getResponseBody should send all buffered text data', async () => {
  session.removeAllListeners();

  const requestId = 'my-req-id-4';
  const loadingFinishedFuture = assertNetworkEvents(session, requestId);
  session.on('Network.dataReceived', common.mustNotCall());

  await triggerNetworkEvents(requestId, 'utf-8');
  await loadingFinishedFuture;
  const { body, base64Encoded } = await session.post('Network.getResponseBody', {
    requestId,
  });
  assert.strictEqual(base64Encoded, false);
  assert.strictEqual(body, payloadString);
});