Skip to content

Releases: sitespeedio/browsertime

v27.0.2

02 May 20:27

Choose a tag to compare

Fixed

  • SPA scripts no longer drop a HAR page when Chrome's soft-navigation PerformanceObserver entry doesn't fire. #2438 gated HAR-page creation on Chrome detecting all three soft-navigation criteria (interaction + URL change + visible paint within a short window), but real SPAs like Grafana sometimes paint too late and Chrome never emits the entry — chrome-har then sees only Network.* events for that measurement and emits zero pages, breaking downstream per-iteration page indexing in sitespeed.io. When the measurement was started without a URL (commands.measure.start(alias) form) and no soft-nav entry was detected, fall back to a synthetic page anchored at the current location.href so each measure.start produces exactly one HAR page.

v27.0.1

02 May 09:12

Choose a tag to compare

Fixed

  • commands.click now falls back to a JavaScript click when the Actions API can't reach the element. Hidden elements have a zero-size bounding box, so the Actions API click that became the default in #2381 silently moved the pointer to (0,0) and clicked nothing instead of triggering the handler. The click command now pre-checks isDisplayed() and uses a JS click when the element isn't displayed, and otherwise catches any Actions API failure and retries with a JS click. Each fallback is logged at info level so it's visible without --verbose. Restores the documented "hide everything before clicking" pattern used by visual-metric scripts #2452.
  • engineDelegate.afterBrowserStopped() is no longer called twice per iteration on the happy path. #2432 added a safety-net cleanup call in the iteration finally block so failure paths still release long-lived helpers, but in the happy path _stopBrowser had already invoked the cleanup, so it ran twice. The visible symptom on Chrome was a spurious ENOENT error from the second cleanUserDataDir (the first call had already removed the directory). It could also double-terminate the iOS simulator's Safari and the ios-capture server. The safety-net now runs only when _stopBrowser didn't already reach the cleanup #2453.
  • cleanUserDataDir cleanup now uses rm(..., { recursive: true, force: true }) so a missing directory is treated as already-cleaned. Defense in depth alongside #2453: if anything in the future double-calls the Chrome cleanup, or if Chrome failed to create the directory in the first place, the cleanup stays quiet instead of logging a spurious ENOENT #2454.

v27.0.0

01 May 17:37

Choose a tag to compare

Highlights

This release is a big push on the scripting API and on iOS real-device testing. All old scripting commands will work but we have new and improveed
syntax that you can use if you follow our documentation. This release also tries to support the upcoming Chrome soft navigations.

  • Unified selector syntax across commands. All interaction commands now accept selectors directly (commands.click('#btn'), commands.addText('#input', 'text'), etc.) with optional id:/xpath:/text:/link:/name:/class: prefixes. The old AndWait family is deprecated in favour of { waitForNavigation: true }.
  • A much bigger convenience-command surface. New type, find, getText, getValue, isVisible, exists, clear, fill, getAttribute, isEnabled, isChecked, hover, press, getTitle, getUrl, check, uncheck, scrollIntoView, select.byText, waitForUrl, clickAndMeasure, click.byText, plus a full cookie command.
  • Chrome soft navigations. SPA route changes (React, Next.js, Vue, Turbo) now produce a HAR page and the standard FCP/LCP/CLS/INP metrics, using Chrome's PerformanceObserver soft-navigation entry type.
  • Safari on iOS over USB. HAR via ios_webkit_debug_proxy, plus video recording and visual metrics via a CoreMediaIO screen-capture helper.
  • TypeScript navigation scripts are now supported on Node.js 22.18.0+ via native type stripping.

Breaking

  • Changed default --timeouts.elementWait from 0 to 6000ms. All element commands (click, addText) now auto-wait up to 6 seconds for elements to appear. Set --timeouts.elementWait 0 to restore the old behavior #2389.
  • Click commands now use the Selenium Actions API for real OS-level mouse events instead of JavaScript .click(). Elements must be visible and interactable. If you need to click a hidden element, use commands.js.run() instead #2381.

Added

  • Unified selector syntax for all interaction commands. You can now call commands.click('#btn'), commands.addText('#input', 'text'), commands.wait('#el', { timeout: 5000 }), commands.select('#dropdown', 'value'), and commands.set('#field', 'value') directly. Supports prefixes: id:, xpath:, text:, link:, name:, class: — CSS selector is the default #2390 #2408.
  • The AndWait methods are deprecated in favour of { waitForNavigation: true } #2390 #2396.
  • Navigation methods (back, forward, refresh) now support { waitForNavigation: true } for consistency #2408.
  • Added commands.type(selector, text) as a shorthand for addText with a more conventional parameter order #2387.
  • Added commands.find(selector, options) helper that combines element lookup with optional waiting and visibility checks #2386.
  • Added commands.measure.clickAndMeasure(alias, selector) shortcut for the common measure.start/click/measure.stop pattern #2382.
  • Added commands.click.byText(text) to click any element by visible text, not just links #2384.
  • Added --timeouts.elementWait option for auto-waiting on elements before interaction #2383.
  • Added support for TypeScript scripts (.ts, .mts, .cts) using Node.js native type stripping (requires Node.js 22.18.0+) #2363.
  • Added commands.getText(selector), commands.getValue(selector), and commands.isVisible(selector) convenience methods #2411.
  • Added commands.exists(selector, { timeout }) for checking element presence without throwing #2412.
  • Added commands.clear(selector) to clear form element content #2413.
  • Added commands.fill({ selector: text, ... }) for filling multiple form fields at once #2414.
  • Added unified selector syntax to mouse commands: commands.mouse.singleClick(selector), commands.mouse.doubleClick(selector), commands.mouse.contextClick(selector), commands.mouse.moveTo(selector) #2415.
  • Added commands.cookie for managing browser cookies: get, getAll, set, delete, deleteAll #2420.
  • Added commands.getAttribute(selector, name), commands.isEnabled(selector), and commands.isChecked(selector) for element state queries #2421.
  • Added commands.hover(selector) as alias for mouse.moveTo, commands.press(key) for keyboard input, commands.getTitle() and commands.getUrl() for page info #2422.
  • Added commands.check(selector) and commands.uncheck(selector) for checkbox/radio interactions #2423.
  • Added commands.scrollIntoView(selector) to scroll elements into the viewport #2425.
  • Added commands.select.byText(selector, text) to select dropdown options by visible text #2426.
  • Added commands.waitForUrl(pattern, { timeout }) to wait for URL changes after navigation #2427.
  • Added video recording and visual metrics for Safari on iOS over USB. A native helper captures the device's screen via CoreMediaIO and pipes frames to ffmpeg. The device is woken into screen-capture mode automatically — no manual QuickTime step required #2432 #2436.
  • Added HAR capture for Safari on iOS via ios_webkit_debug_proxy. Browsertime starts and stops iwdp automatically and exits with a clear error if it isn't installed (brew install ios-webkit-debug-proxy). New --safari.includeResponseBodies CLI option. macOS Safari is unaffected #2431.
  • Added soft navigation support for Chrome. Single-page app route changes (React, Next.js, Vue, Turbo) now produce a HAR page and the standard FCP/LCP/CLS/INP metrics, using Chrome's PerformanceObserver soft-navigation entry type to confirm user interaction + URL change + visible paint #2438.
  • Updated dependencies to latest compatible versions: chrome-har 1.2.1, selenium-webdriver 4.43.0, execa 9.6.1, jimp 1.6.1 #2437.
  • Firefox 149 in the Docker container #2375.
  • Record the full Chrome/Edge configuration browsertime applied to the browser (args, preferences, mobile emulation, binary path, extensions count) under info.browser in the result JSON, not just what the user passed via --chrome.args #2447.
  • Record Firefox preferences and the resolved binary path under info.browser in the result JSON #2448.
  • Write long-task ranges and user-timing marks/measures into the HAR under pages[].pageTimings as _longTasks (array of [startMs, endMs] tuples) and _userTimings (object keyed by entry name → startTime), so downstream waterfall viewers can show what the browser was doing between requests #2449.
  • Added modern device profiles to the mobile emulation device list #2446.

Fixed

  • Pin the iOS Safari tab being measured so unrelated open tabs cannot clobber the active inspector target. The WebDriver tab is navigated to a sentinel URL and identified by it before iWDP messages are processed, otherwise an unrelated Target.targetCreated event could leave the HAR empty #2440.
  • Fixed drawtext failing on ffmpeg 8 by quoting font paths and forwarding ffmpeg stderr so font/filter errors are visible #2435.
  • Fixed Firefox network idle timeout on repeated iterations. The WebSocket message listener was never removed between iterations, causing the inflight counter to go negative #2391.
  • Fixed Firefox network idle timeout when no network events arrive. Timestamps were initialized as undefined causing the idle check to never trigger #2394.
  • Fixed intermittent crash when setting orange background before document.body exists on Edge/Windows #2393.
  • Element interaction error messages now include the current page URL for easier debugging #2385.
  • Added actions.clear() after perform() in all mouse commands to prevent pointer/key state leaking between actions #2406.
  • Standardized error handling in all command run() methods using executeCommand with UR...
Read more

v26.3.2

24 Jan 12:30

Choose a tag to compare

Fixed

  • Hello the new and fixed bidi-har 0.0.22 that fixes the response body #2361.

v26.3.1

11 Jan 14:12

Choose a tag to compare

Fixed

  • Reverting back to bidi-har 0.0.18. There where error/failures either in bidi har or in combination with browsertime in the latest release #2360

v26.3.0

09 Jan 21:34

Choose a tag to compare

Added

  • Get response bodies in the HAR for Firefox. Thank you Julian Descottes and the rest of the Mozilla team that made this possible in bidi-har-export. Added in #2359. The Firefox HAR has missed this functionality since we did the switch to bidi-har.

Fixed

  • Restructure server timings so the timing name does not get lost for InfluxDB/Graphite. Thank you Tim Oldenburg for PR #2358.
  • Add Simpleperf app_profiler options and use --android.simpleperf. Thank you Abhishek Nimalan for PR #2352

v26.2.0

18 Dec 08:58

Choose a tag to compare

Added

  • Updated Chromedriver and Edgedriver to 143 #2354 and#2355.
  • Updated webdriver to 4.39.0 #2356.

Fixed

  • Try to tune the XVFB handling to make it safer that xvfb is always stopped #2353.

v26.1.0

11 Dec 18:07

Choose a tag to compare

Added

  • Firefox 146 in the Docker container #2351.
  • Chrome 143 in the Docker container #2350.

Fixed

  • Make sure the user in the Docker container has the correct user rights #2349.

v26.0.1

10 Dec 18:22

Choose a tag to compare

Fixed

  • Remove extra console.log entry :)

v26.0.0

10 Dec 17:55

Choose a tag to compare

Breaking

  • We removed support for setting the compression level for png screenshots, see the added section why.

Added

  • Upgrade to support NodeJS 24 without warnings, include NodeJS 24 in the Docker container, and base the Docker container on Ubuntu 24.04. To make this work I needed to upgrade the Jimp library and then we lost the settings for png screenshots --screenshotParams.png.compressionLevel #2342.