From 18e1fe6d4578b1eccbcfd923e722cb463b53ddbb Mon Sep 17 00:00:00 2001 From: Peter Hedenskog Date: Mon, 10 Aug 2026 07:19:31 +0200 Subject: [PATCH] Do not report failed iterations as HAR pages without an URL When an iteration fails (for example when the BiDi connection to Firefox dies mid test), browsertime adds an empty placeholder HAR so the run count stays intact. That placeholder page has no _url and no entries, so at the end of the run the fully loaded calculation logged a scary "There is an page without an URL in the HAR" error, pointing users at a HAR problem that does not exist. Skip pages without any requests when calculating fully loaded, matching how the main document helpers already handle incomplete pages. Co-authored-by: Claude Fable 5 noreply@anthropic.com Change-Id: I25860ab728d2a4ba6be02efc69074d708968d749 --- lib/support/har/index.js | 3 +++ test/unittests/harBuilderTest.js | 23 ++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/support/har/index.js b/lib/support/har/index.js index a9daa3d20..2d6e04099 100644 --- a/lib/support/har/index.js +++ b/lib/support/har/index.js @@ -319,6 +319,9 @@ export function getFullyLoaded(har) { let pageEntries = [...entries]; pageEntries = pageEntries.filter(entry => entry.pageref === pageId); + // Skip pages without any requests, like the empty HAR + // that is added for a failing iteration + if (pageEntries.length === 0) continue; let pageEnd = 0; for (let entry of pageEntries) { diff --git a/test/unittests/harBuilderTest.js b/test/unittests/harBuilderTest.js index 0c1b63395..bb97913d5 100644 --- a/test/unittests/harBuilderTest.js +++ b/test/unittests/harBuilderTest.js @@ -3,7 +3,9 @@ const { serial } = test; import { addCreator, mergeHars, - addExtraFieldsToHar + addExtraFieldsToHar, + getEmptyHAR, + getFullyLoaded } from '../../lib/support/har/index.js'; let har; @@ -311,6 +313,25 @@ test('Omit `_longTasks` entirely when pageinfo has no longTask field', t => { t.is(har.log.pages[0].pageTimings._longTasks, undefined); }); +test('Skip pages without entries when getting fully loaded', t => { + // A failing iteration adds an empty HAR (without _url) that + // should not end up as a page without an URL in the result + har.log.pages[0]._url = 'https://example.com'; + har.log.pages[0].startedDateTime = '2026-08-09T06:46:00.000Z'; + har.log.entries[0].startedDateTime = '2026-08-09T06:46:00.100Z'; + har.log.entries[0].time = 200; + + const merged = mergeHars([ + har, + getEmptyHAR('https://example.com', 'Firefox') + ]); + const fullyLoaded = getFullyLoaded(merged); + + t.is(fullyLoaded.length, 1); + t.is(fullyLoaded[0].url, 'https://example.com'); + t.is(fullyLoaded[0].fullyLoaded, 300); +}); + test('Tag the first entry of each page with `_documentURL`', t => { // Cross-origin tinting in waterfall-tools reads `entries[0]._documentURL` // to decide which request labels are third-party — without this, the