sitespeedio/chrome-har

New HAR page doesn't appear to be created upon navigation

gitgrimbo opened this issue · 2 comments

This is the test code. It loads http://localhost:8080/ and then clicks on the only link on the page. The index.html page has one IMG tag, one IFRAME tag and one A tag.

const fs = require('fs');
const { promisify } = require('util');

const puppeteer = require('puppeteer');
const { harFromMessages } = require('chrome-har');

// list of events for converting to HAR
const events = [];

// event types to observe
const observe = [
  'Page.loadEventFired',
  'Page.domContentEventFired',
  'Page.frameStartedLoading',
  'Page.frameAttached',
  'Network.requestWillBeSent',
  'Network.requestServedFromCache',
  'Network.dataReceived',
  'Network.responseReceived',
  'Network.resourceChangedPriority',
  'Network.loadingFinished',
  'Network.loadingFailed',
];

function wait(ms) {
  return new Promise((resolve, reject) => setTimeout(resolve, ms));
}

(async () => {
  const launchOptions = {
    executablePath: "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe",
  };
  const browser = await puppeteer.launch(launchOptions);
  const page = await browser.newPage();

  // register events listeners
  const client = await page.target().createCDPSession();
  await client.send('Page.enable');
  await client.send('Network.enable');
  observe.forEach(method => {
    client.on(method, params => {
      events.push({ method, params });
    });
  });

  // perform tests

  await page.goto('http://localhost:8080/');

  (await page.waitForSelector('a', { visible: true })).click();

  await page.waitForNavigation({ waitUntil: 'networkidle2' });

  await wait(2000);

  await browser.close();

  // convert events to HAR file
  const har = harFromMessages(events);
  await promisify(fs.writeFile)('localhost.har', JSON.stringify(har));
})();

index.html

<p><img src="One_black_Pixel.png?index">
<p><iframe src="iframe.html"></iframe>
<p><a href="index2.html">Next</a>

iframe.html

<img src="One_black_Pixel.png?iframe">

index2.html

<p><img src="One_black_Pixel.png?index2">
<p><iframe src="iframe2.html"></iframe>

iframe2.html

<img src="One_black_Pixel.png?iframe2">

One_black_Pixel.png

Copied from here, https://en.wikipedia.org/wiki/File:One_black_Pixel.png.

HARs

The chrome-har captured HAR shows all the requests collected as a single page. But there should be two pages, one for index.html and one for index2.html.

image

The HAR captured from Chrome devtools after performing the test manually, correctly shows two pages (albeit in the wrong order here).

image

Hi @gitgrimbo can you try and see what you get from Browsertime against your test page, then we can see if it is a puppeteer issue as in #15 (comment) or an issue with the Chrome-har.

Thanks
Peter

I've not used Browsertime before, but I'll take a look when I can.

In the meantime, here are some console statements from making the following changes to index.js#L194..L200

      switch (message.method) {
        case 'Page.frameStartedLoading':
        case 'Page.frameScheduledNavigation':
          {
            // LOG
            console.log(message.method);

            const frameId = params.frameId;

            const rootFrame = rootFrameMappings.get(frameId) || frameId;

            // LOG
            pages.forEach((page, pageIdx) => console.log(pageIdx, "page.__frameId", page.__frameId, "rootFrame", rootFrame));
Page.frameStartedLoading
Page.frameStartedLoading
0 'page.__frameId' '92BFA1E5F88EEE8A84B8F410C5A9137B' 'rootFrame' '92BFA1E5F88EEE8A84B8F410C5A9137B'
Page.frameStartedLoading
0 'page.__frameId' '92BFA1E5F88EEE8A84B8F410C5A9137B' 'rootFrame' '92BFA1E5F88EEE8A84B8F410C5A9137B'
Page.frameStartedLoading
0 'page.__frameId' '92BFA1E5F88EEE8A84B8F410C5A9137B' 'rootFrame' '92BFA1E5F88EEE8A84B8F410C5A9137B'

It looks like there are four frameStartedLoading events, but only one page is added to the HAR because the frameId is matching.