### Install and Run Browsertime via NodeJS Source: https://github.com/sitespeedio/browsertime/blob/main/README.md Install the package globally and execute a basic performance test against a URL. ```shell npm install -g browsertime browsertime https://example.com ``` -------------------------------- ### Use Firefox Profile Template Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Start Firefox with a pre-configured profile by specifying a template directory using --firefox.profileTemplate. ```bash --firefox.profileTemplate ``` -------------------------------- ### Install Browsertime Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/08-Setting-Up-IntelliSense.md Install Browsertime as a developer dependency for your project using npm. ```bash npm install browsertime --save-dev ``` -------------------------------- ### Start and Stop Page Measurements Source: https://context7.com/sitespeedio/browsertime/llms.txt Use `commands.measure.start` to begin collecting metrics and `commands.measure.stop` to end. Aliases can be provided for reporting. Manual start/stop is useful for measuring specific user interactions. ```javascript await commands.measure.start('https://www.example.com'); ``` ```javascript await commands.measure.start('https://www.example.com/products', 'ProductsPage'); ``` ```javascript await commands.measure.start('LoginFlow'); // Start without URL ``` ```javascript await commands.measure.stop(); // Stop and collect metrics ``` ```javascript await commands.measure.start('https://www.example.com'); ``` ```javascript const customValue = await commands.js.run('return window.myApp.getMetric()'); ``` ```javascript commands.measure.add('myCustomMetric', customValue); ``` ```javascript commands.measure.addObject({ itemsLoaded: 42, apiResponseTime: 150 }); ``` ```javascript await commands.measure.start('https://www.example.com/checkout'); ``` ```javascript await commands.measure.stopAsError('Checkout page failed to load'); ``` -------------------------------- ### Start Gnirehtet Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Enable reverse tethering for Android devices by including the `--gnirehtet` flag. Ensure gnirehtet is in your system's PATH. ```bash --gnirehtet ``` -------------------------------- ### Test multiple URLs with custom configuration Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/09-Examples.md Iterates through a list of URLs, performing setup tasks like clearing cache between tests. ```JavaScript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ module.exports = async function (context, commands) { const urls = context.options.urls; for (let url of urls) { // Do the stuff for each url that you need to do // Maybe login a user or add a cookie or something // Then test the URL await commands.measure.start(url); // When the test is finished, clear the browser cache await commands.cache.clear(); // Navigate to a blank page so you kind of start from scratch for the next URL await commands.navigate('about:blank'); } }; ``` -------------------------------- ### Complete Login and Measurement Example Source: https://context7.com/sitespeedio/browsertime/llms.txt This script automates a login process, measures multiple page loads and user interactions, and adds custom metrics. It requires the Browsertime context and commands objects. Use this for complex user journey testing. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { const log = context.log; // Step 1: Navigate to login page (not measured) log.info('Navigating to login page'); await commands.navigate('https://www.example.com/login'); try { // Step 2: Fill login form await commands.addText.byId('testuser@example.com', 'email'); await commands.addText.byId('securePassword123', 'password'); // Step 3: Measure login action await commands.measure.start('Login'); await commands.click.byIdAndWait('loginButton'); // Wait for dashboard element to confirm login success await commands.wait.byId('dashboard-content', 10000); await commands.measure.stop(); // Step 4: Measure dashboard page await commands.measure.start('https://www.example.com/dashboard', 'Dashboard'); // Add custom metric: count of dashboard widgets const widgetCount = await commands.js.run( 'return document.querySelectorAll(".widget").length' ); commands.measure.add('dashboardWidgets', widgetCount); // Step 5: Navigate to products and measure await commands.measure.start('https://www.example.com/products', 'ProductsPage'); // Scroll to trigger lazy loading and measure CLS await commands.scroll.toBottom(200); await commands.wait.byTime(1000); // Step 6: Measure search interaction await commands.measure.start('ProductSearch'); await commands.addText.bySelector('laptop', 'input[type="search"]'); await commands.click.bySelectorAndWait('button[type="submit"]'); await commands.wait.bySelector('.search-results', 5000); await commands.measure.stop(); // Add search result count as metric const resultCount = await commands.js.run( 'return document.querySelectorAll(".search-result-item").length' ); commands.measure.add('searchResultCount', resultCount); log.info(`Test completed successfully. Found ${resultCount} search results.`); } catch (error) { log.error(`Test failed: ${error.message}`); await commands.markAsFailure(error.message); throw error; } } // Run: browsertime --video --visualMetrics -n 3 login-test.mjs ``` -------------------------------- ### Measure Multiple Pages with White Background Start Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/09-Examples.md This script measures multiple pages and ensures videos start with a white background by clearing the body content before each measurement. This can prevent layout shifts from being recorded in videos. ```JavaScript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.measure.start('https://www.sitespeed.io'); await commands.js.run('document.body.innerHTML = ""; document.body.style.backgroundColor = "white";'); await commands.measure.start('https://www.sitespeed.io/examples/'); await commands.js.run('document.body.innerHTML = ""; document.body.style.backgroundColor = "white";'); return commands.measure.start('https://www.sitespeed.io/documentation/'); }; ``` -------------------------------- ### Implementing Setup and Teardown Hooks Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/18-Tips-and-tricks.md Define lifecycle functions in CommonJS modules to execute code before and after the main test function. ```javascript async function setUp(context, commands) { // do some useful set up }; async function perfTest(context, commands) { // add your own code here }; async function tearDown(context, commands) { // do some cleanup here }; module.exports = { setUp: setUp, tearDown: tearDown, test: perfTest }; ``` -------------------------------- ### Install Python Dependencies for Visual Metrics Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Install the required Python dependencies, OpenCV-Python and Numpy, when running Browsertime directly with Node.js (not via Docker) to utilize the new Visual Metrics script. ```bash python -m pip install --user OpenCV-Python Numpy ``` -------------------------------- ### commands.navigate - Page Navigation API Source: https://context7.com/sitespeedio/browsertime/llms.txt Navigate to URLs without measuring, useful for setup steps like login or pre-warming. ```APIDOC ## commands.navigate - Page Navigation ### Description Navigates to URLs without measuring, useful for setup steps like login or pre-warming. ### Method POST (conceptual, as it's a command within a script) ### Endpoint N/A (command-line tool or programmatic API) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```javascript // Navigate without measuring (for setup steps) await commands.navigate('https://www.example.com/login'); // Do login steps... await commands.addText.byId('username', 'usernameField'); await commands.addText.byId('password', 'passwordField'); await commands.click.byIdAndWait('submitButton'); // Now measure the actual page of interest await commands.measure.start('https://www.example.com/dashboard'); ``` ### Response #### Success Response (200) Navigation is completed. #### Response Example None (typically returns void or a success indicator) ``` -------------------------------- ### Navigate Pages Without Measuring Source: https://context7.com/sitespeedio/browsertime/llms.txt Use `commands.navigate` for page navigation when measurement is not required, such as during setup or pre-warming phases. ```javascript await commands.navigate('https://www.example.com/login'); ``` ```javascript await commands.navigate('https://www.example.com/dashboard'); ``` -------------------------------- ### Basic Browsertime Script Template Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/08-Setting-Up-IntelliSense.md A template for starting a Browsertime script, including necessary JSDoc imports for context and commands. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { }; ``` -------------------------------- ### Simulate Login Step Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/09-Examples.md This script simulates a user login process. It navigates to a login page, enters credentials into input fields, starts measurement with an alias, clicks the submit button, and waits for the subsequent page load. Includes basic error handling. ```JavaScript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { // Navigate to a URL, but do not measure the URL await commands.navigate( 'https://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Main+Page' ); try { // Add text into an input field, finding the field by id await commands.addText.byId('login', 'wpName1'); await commands.addText.byId('password', 'wpPassword1'); // Start the measurement and give it the alias login // The alias will be used when the metrics is sent to // Graphite/InfluxDB await commands.measure.start('login'); // Find the submit button and click it and wait for the // page complete check to finish on the next loaded URL await commands.click.byIdAndWait('wpLoginAttempt'); // Stop and collect the metrics return commands.measure.stop(); } wcatch (e) { // We try/catch so we will catch if the the input fields can't be found // The error is automatically logged in Browsertime an rethrown here // We could have an alternative flow ... // else we can just let it cascade since it caught later on and reported in // the HTML throw e; } }; ``` -------------------------------- ### Run Browsertime on Android Source: https://github.com/sitespeedio/browsertime/blob/main/README.md Executes a performance test on an Android device using the specified package. Requires ADB installation and device preparation. ```bash $ browsertime --chrome.android.package com.android.chrome https://www.sitespeed.io --video --visualMetrics ``` -------------------------------- ### Measure Navigation with Interaction Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/03-Measurement-Commands.md Navigates to a page, starts a measurement, performs an interaction, and stops the measurement to capture performance metrics. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.navigate('https://www.sitespeed.io'); await commands.measure.start('Documentation'); // Using a xxxAndWait command will make the page wait for a navigation await commands.click.byLinkTextAndWait('Documentation'); return commands.measure.stop(); } ``` -------------------------------- ### Listen to CDP Network.responseReceived Events Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Use `commands.cdp.on` to listen for specific Chrome DevTools Protocol events. This example collects all network response parameters for a given URL. Ensure your browser supports CDP. ```javascript const responses = []; await commands.cdp.on('Network.responseReceived', params => { responses.push(params); }); await commands.measure.start('https://www.sitespeed.io/search/'); // Here you can check the array with all responses received ``` -------------------------------- ### Start and Stop Timer Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Use this command to measure time intervals within your tests. The measured time is added to the last tested URL's results. ```javascript const timer = commands.stopWatch.get('my_timer'); timer.start(); // Do something // Stop the timer and add the result to the last tested URL timer.stopAndAdd(); ``` -------------------------------- ### Programmatic API Usage with BrowsertimeEngine Source: https://context7.com/sitespeedio/browsertime/llms.txt Integrate Browsertime into custom Node.js applications using the `BrowsertimeEngine`. Configure options, start the engine, run tests on single or multiple URLs, and access results. Remember to always stop the engine. ```javascript import { BrowsertimeEngine, browserScripts } from 'browsertime'; async function runPerformanceTest() { // Configure the engine const options = { browser: 'chrome', iterations: 3, video: true, visualMetrics: true, resultDir: './results', connectivity: { profile: '3g' } }; // Create and start the engine const engine = new BrowsertimeEngine(options); try { await engine.start(); // Get default browser scripts for metric collection const scriptCategories = await browserScripts.allScriptCategories(); const scripts = await browserScripts.getScriptsForCategories(scriptCategories); // Run test on a single URL const result = await engine.run('https://www.example.com', scripts); // Access results console.log('Page load time:', result[0].browserScripts.timings.pageTimings); console.log('Visual metrics:', result[0].visualMetrics); // Run with multiple URLs const multiResult = await engine.runMultiple([ 'https://www.example.com', 'https://www.example.com/products' ], scripts); // Run with custom script const scriptResult = await engine.runMultiple([ ['my-script.mjs', myScriptFunction] ], scripts); return result; } finally { // Always stop the engine await engine.stop(); } } // Custom script function async function myScriptFunction(context, commands) { await commands.measure.start('https://www.example.com'); await commands.click.byLinkTextAndWait('Products'); return commands.measure.start('https://www.example.com/products'); } runPerformanceTest().catch(console.error); ``` -------------------------------- ### Get Selected Value by ID in JavaScript Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Use this command to get the value of the currently selected option in a select element identified by its ID. ```javascript select.getSelectedValueById(selectId) ``` -------------------------------- ### Run Basic URL Performance Tests via CLI Source: https://context7.com/sitespeedio/browsertime/llms.txt Execute performance tests on URLs with options for browser selection, iteration counts, video recording, and network throttling. ```bash # Test a single URL with default settings (Chrome, 3 iterations) browsertime https://www.example.com # Test with Firefox browsertime --browser firefox https://www.example.com # Run 5 iterations for statistical reliability browsertime -n 5 https://www.example.com # Record video and collect visual metrics (requires ffmpeg) browsertime --video --visualMetrics https://www.example.com # Test with network throttling (3G profile) browsertime --connectivity.profile 3g https://www.example.com # Run in headless mode browsertime --headless https://www.example.com # Docker usage with video recording docker run --rm -v "$(pwd)":/browsertime sitespeedio/browsertime \ --video --visualMetrics https://www.example.com ``` -------------------------------- ### Get Values by ID in JavaScript Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Use this command to retrieve all the values from a select element identified by its ID. ```javascript select.getValuesById(selectId) ``` -------------------------------- ### Configure Humble Connectivity Engine Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md To use Humble as the connectivity engine for mobile phone testing, ensure Humble is set up on a Raspberry Pi 4. Then, specify the engine and the URL to your Humble instance using these command-line options. ```bash --connectivity.engine humble --connectivity.humble.url http://raspberrypi.local:3000 ``` -------------------------------- ### Browsertime Script with Navigation and Measurement Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/01-Introduction.md This script demonstrates navigating to a URL and then measuring the performance of a different URL. It uses `await` to ensure sequential execution of asynchronous commands. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.navigate('https://www.sitespeed.io'); return commands.measure.start('https://www.sitespeed.io/documentation/'); } ``` -------------------------------- ### Get Firefox Performance Stats Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Collect internal Firefox performance statistics by enabling the `--firefox.perfStats` option. ```bash --firefox.perfStats ``` -------------------------------- ### Browsertime API - Connectivity Engine (Humble) Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Information on configuring and using the Humble connectivity engine for mobile phone testing. ```APIDOC ## Browsertime API - Connectivity Engine (Humble) ### Description Enables testing mobile phone connectivity using the Humble engine, typically run on a Raspberry Pi. ### Configuration - **Engine Selection**: Use `--connectivity.engine humble` to select the Humble engine. - **Humble URL**: Specify the URL of your Humble instance with `--connectivity.humble.url http://raspberrypi.local:3000`. ### Requirements - Humble must be set up on a Raspberry Pi 4. ### Example Configuration ```bash browsertime --url=https://www.example.com --connectivity.engine humble --connectivity.humble.url http://raspberrypi.local:3000 ``` ``` -------------------------------- ### Run Browsertime with Pre/Post Scripts Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Execute pre and post scripts before and after the main URL navigation. Ensure scripts are in the same directory or provide a full path. ```bash browsertime preScript.js https://www.sitespeed.io postScript.js ``` -------------------------------- ### Run Firefox Nightly with Visual Metrics Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Use this command to test Firefox Nightly with visual metrics. Adjust `--pageCompleteCheck` if the metric calculation time is an issue. ```bash browsertime --firefox.nightly https://www.wikipedia.org -n 1 ``` -------------------------------- ### Run Browsertime and sitespeed.io scripts Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/02-Running-Scripts.md Basic command-line execution for single and multiple script files. ```bash browsertime myScript.mjs ``` ```bash sitespeed.io myScript.mjs --multi ``` ```bash sitespeed.io login.mjs measureStartPage.mjs logout.mjs --multi ``` -------------------------------- ### Subscribe and listen to Bidi events Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/12-Bidi.md Demonstrates subscribing to network events and using onMessage to handle incoming event data. Ensure to unsubscribe when event monitoring is no longer required. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { // We want to to do something on all the requests that are sent await commands.bidi.subscribe('network.beforeRequestSent'); await commands.bidi.onMessage(function (event) { const myEvent = JSON.parse(Buffer.from(event.toString())); console.log(myEvent); }); await commands.navigate('https://www.sitespeed.io'); } ``` -------------------------------- ### commands.measure - Page Measurement API Source: https://context7.com/sitespeedio/browsertime/llms.txt The measure command starts and stops performance measurements, collecting timing metrics, HAR data, and visual metrics. ```APIDOC ## commands.measure - Page Measurement ### Description Starts and stops performance measurements, collecting timing metrics, HAR data, and visual metrics. ### Method POST (conceptual, as it's a command within a script) ### Endpoint N/A (command-line tool or programmatic API) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```javascript // Simple measurement await commands.measure.start('https://www.example.com'); // Measurement with alias await commands.measure.start('https://www.example.com/products', 'ProductsPage'); // Manual start/stop for measuring user interactions await commands.measure.start('LoginFlow'); await commands.navigate('https://www.example.com/login'); await commands.addText.byId('user@example.com', 'email'); await commands.addText.byId('password123', 'password'); await commands.click.byIdAndWait('loginButton'); await commands.measure.stop(); // Add custom metrics await commands.measure.start('https://www.example.com'); const customValue = await commands.js.run('return window.myApp.getMetric()'); commands.measure.add('myCustomMetric', customValue); commands.measure.addObject({ itemsLoaded: 42, apiResponseTime: 150 }); // Stop measurement as error try { await commands.measure.start('https://www.example.com/checkout'); } catch (e) { await commands.measure.stopAsError('Checkout page failed to load'); throw e; } ``` ### Response #### Success Response (200) Metrics collected during the measurement period. #### Response Example (Depends on collected metrics, typically HAR, timing, and visual data) ``` -------------------------------- ### Create a login script for pre-testing Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/09-Examples.md Defines a reusable login script that can be passed to the sitespeed.io CLI via the --preScript flag. ```JavaScript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.navigate( 'https://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Main+Page' ); try { await commands.addText.byId('login', 'wpName1'); await commands.addText.byId('password', 'wpPassword1'); // Click on the submit button with id wpLoginAttempt await commands.click.byIdAndWait('wpLoginAttempt'); // wait on a specific id to appear on the page after you logged in return commands.wait.byId('pt-userpage', 10000); } catch (e) { // We try/catch so we will catch if the the input fields can't be found // The error is automatically logged in Browsertime and re-thrown here // We could have an alternative flow ... // else we can just let it cascade since it caught later on and reported in // the HTML throw e; } }; ``` ```bash sitespeed.io --preScript login.mjs https://en.wikipedia.org/wiki/Barack_Obama ``` -------------------------------- ### Run WebPageReplay with Docker Source: https://github.com/sitespeedio/browsertime/blob/main/README.md Executes performance tests using WebPageReplay within a Docker container. Requires the NET_ADMIN capability and appropriate environment variables for latency and replay mode. ```bash docker run --cap-add=NET_ADMIN --rm -v "$(pwd)":/browsertime -e REPLAY=true -e LATENCY=100 sitespeedio/browsertime:20.0.0 https://en.wikipedia.org/wiki/Barack_Obama ``` ```bash docker run --cap-add=NET_ADMIN --rm -v "$(pwd)":/browsertime -e REPLAY=true -e LATENCY=100 sitespeedio/browsertime:20.0.0 -b firefox -n 11 --firefox.acceptInsecureCerts true https://en.wikipedia.org/wiki/Barack_Obama ``` ```bash docker run --privileged -v /dev/bus/usb:/dev/bus/usb -e START_ADB_SERVER=true --cap-add=NET_ADMIN --rm -v “$(pwd)“:/browsertime -e REPLAY=true -e LATENCY=100 sitespeedio/browsertime https://en.m.wikipedia.org/wiki/Barack_Obama --android --chrome.args ignore-certificate-errors-spki-list=PhrPvGIaAMmd29hj8BCZOq096yj7uMpRNHpn5PDxI6I= -n 11 --chrome.args user-data-dir=/data/tmp/chrome ``` -------------------------------- ### Add Firefox Arguments and Environment Variables Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Pass custom arguments and environment variables to Firefox using --firefox.args and --firefox.env. ```bash --firefox.args --firefox.env ``` -------------------------------- ### commands.addText - Text Input API Source: https://context7.com/sitespeedio/browsertime/llms.txt Provides methods to add text to input fields using different element selectors. It also includes an example of completing a form. ```APIDOC ## commands.addText - Text Input ### Description Add text to input fields using various element selectors. This command clears the field before adding new text. ### Methods - `byId(text, id)`: Adds text to an element identified by its ID. - `byName(text, name)`: Adds text to an element identified by its name attribute. - `bySelector(text, selector)`: Adds text to an element identified by a CSS selector. - `byXpath(text, xpath)`: Adds text to an element identified by an XPath expression. - `byClassName(text, className)`: Adds text to an element identified by its class name. ### Request Example (Conceptual) ```javascript await commands.addText.byId('user@example.com', 'emailInput'); await commands.addText.bySelector('Your message here', 'textarea.message-box'); ``` ### Response Example (Conceptual) No direct response is returned, but the text is entered into the specified element. ``` -------------------------------- ### Execute Selenium Actions Source: https://context7.com/sitespeedio/browsertime/llms.txt Use the Actions API for complex user interactions like dragging, hovering, and keyboard input. Always call clear() before starting a new sequence. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.navigate('https://www.example.com'); // Get the Actions builder const actions = commands.action.getActions(); // Click on an element const button = await commands.element.getById('submitBtn'); await actions.click(button).perform(); // Clear actions before building new sequence await actions.clear(); // Complex interaction: hover, then click const menu = await commands.element.getByCss('.dropdown-menu'); const menuItem = await commands.element.getByCss('.menu-item'); await actions .move({ origin: menu }) .pause(500) .click(menuItem) .perform(); // Drag and drop await actions.clear(); const source = await commands.element.getById('draggable'); const target = await commands.element.getById('droppable'); await actions.dragAndDrop(source, target).perform(); // Keyboard interactions await actions.clear(); const input = await commands.element.getById('searchInput'); await actions .click(input) .sendKeys('search query') .perform(); } ``` -------------------------------- ### Simple Browsertime Script Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/01-Introduction.md A basic script to measure the performance of a given URL. It uses the `measure.start` command to initiate the measurement. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { context.log.info('Start to measure my first URL'); return commands.measure.start('https://www.sitespeed.io'); } ``` -------------------------------- ### Record Firefox Window Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Use the --firefox.windowRecorder flag to record videos of the browser window. ```bash --firefox.windowRecorder ``` -------------------------------- ### Add Custom Metric: Blog Comments Count Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/09-Examples.md Collect custom metrics by running JavaScript to get an element's text, parsing it, and adding it as a metric. Ensure measurement is stopped before adding the metric. ```JavaScript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.measure.start('blog-post'); //alias is now blog-post await commands.navigate('https://www.exampleBlog/blog-post'); //use commands.js.run to return the element using pure javascript const element = await commands.js.run('return(document.getElementsByClassName("comment-count")[0].innerText)'); //parse out just the number of comments var elementMetric = element.match(/\d/)[0]; // need to stop the measurement before you can add it as a metric await commands.measure.stop(); // metric will now be added to the html and outpout to graphite/influx if you're using it await commands.measure.add('commentsCount', elementMetric); }; ``` -------------------------------- ### Run Browsertime via Docker Source: https://github.com/sitespeedio/browsertime/blob/main/README.md Execute a performance test using the official Docker image, mounting the current directory for output. ```shell docker run --rm -v "$(pwd)":/browsertime sitespeedio/browsertime https://www.sitespeed.io/ ``` -------------------------------- ### Handle complex login flows with frames Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/09-Examples.md Demonstrates handling iframes and waiting for dynamic elements during a complex authentication process. ```JavaScript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.navigate( 'https://example.org' ); try { // Find the sign in button and click it await commands.click.byId('sign_in_button'); // Wait some time for the page to open a new login frame await commands.wait.byTime(2000); // Switch to the login frame await commands.switch.toFrame('loginFrame'); // Find the username fields by xpath (just as an example) await commands.addText.byXpath( 'peter@example.org', '//*[@id="userName"]' ); // Click on the next button await commands.click.byId('verifyUserButton'); // Wait for the GUI to display the password field so we can select it await commands.wait.byTime(2000); // Wait for the actual password field await commands.wait.byId('password', 5000); // Fill in the password await commands.addText.byId('dejh8Ghgs6ga(1217)', 'password'); // Click the submit button await commands.click.byId('btnSubmit'); // In your implementation it is probably better to wait for an id await commands.wait.byTime(5000); // Measure the next page as a logged in user return commands.measure.start( 'https://example.org/logged/in/page' ); } catch(e) { // We try/catch so we will catch if the the input fields can't be found // We could have an alternative flow ... // else we can just let it cascade since it caught later on and reported in // the HTML throw e; } }; ``` -------------------------------- ### Send CDP Command and Get Result in Browsertime Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/11-Chrome-Devtools-Protocol.md Executes a Chrome DevTools Protocol command and retrieves the result. Useful for inspecting browser state, such as memory usage. Logs the result to the context's info logger. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.measure.start('https://www.sitespeed.io'); const domCounters = await commands.cdp.sendAndGet('Memory.getDOMCounters'); context.log.info('Memory.getDOMCounters %j', domCounters); } ``` -------------------------------- ### Clear HTML for White Background Between Pages Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/18-Tips-and-tricks.md Use this script to clear the HTML and set a white background when navigating between pages to ensure accurate visual metrics. It starts by measuring the first page, then clears the content before measuring the next. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.measure.start('https://www.sitespeed.io'); // Renove the HTML and make sure the background is white await commands.js.run('document.body.innerHTML = ""; document.body.style.backgroundColor = "white";'); return commands.measure.start('https://www.sitespeed.io/examples/'); }; ``` -------------------------------- ### Run Safari on iOS Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Execute Safari on iOS devices using the -b safari --ios command. ```bash -b safari --ios ``` -------------------------------- ### Hide HTML Before Clicking Link for Accurate Navigation Metrics Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/18-Tips-and-tricks.md This script hides page elements before clicking a link to prevent layout changes from affecting navigation metrics. It measures the initial page, hides content, starts a new measurement, clicks the link, and then stops the measurement. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.measure.start('https://www.sitespeed.io'); // Hide everything // We do not hide the body since the body needs to be visible when we do the magic to find the staret of the // navigation by adding a layer of orange on top of the page await commands.js.run('for (let node of document.body.childNodes) { if (node.style) node.style.display = "none";}'); // Start measurning await commands.measure.start(); // Click on the link and wait on navigation to happen await commands.click.bySelectorAndWait('body > nav > div > div > div > ul > li:nth-child(2) > a'); return commands.measure.stop(); }; ``` -------------------------------- ### Test Multiple Pages Sequentially Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Navigate through multiple URLs in a single run, keeping the browser open between tests. This is useful for testing user journeys. ```bash browsertime https://www.sitespeed.io https://www.sitespeed.io/documentation/ ``` -------------------------------- ### Configure Firefox-Specific Performance Options Source: https://context7.com/sitespeedio/browsertime/llms.txt Apply Firefox-specific settings including profiling, custom preferences, and mobile testing. ```bash # Use Firefox Nightly browsertime --firefox.nightly https://www.example.com # Collect Gecko Profiler data browsertime --browser firefox --firefox.geckoProfiler https://www.example.com # Set custom Firefox preferences browsertime --browser firefox \ --firefox.preference "network.http.max-connections:100" \ https://www.example.com # Accept insecure certificates browsertime --browser firefox --firefox.acceptInsecureCerts https://www.example.com # Test Firefox on Android browsertime --browser firefox \ --firefox.android.package org.mozilla.firefox https://www.example.com ``` -------------------------------- ### Execute JavaScript in Browser Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/04-Interact-with-the-page.md Shows how to run custom JavaScript within the browser context and retrieve return values. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { // We are in browsertime context so you can skip that from your options object const secretValue = await commands.js.run('return 12'); // if secretValue === 12 ... } ``` -------------------------------- ### Inject a preload script using Bidi Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/12-Bidi.md Uses the script.addPreloadScript method to execute JavaScript on every new document. Requires the Bidi protocol to be supported by the browser. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { const params = { method: 'script.addPreloadScript', params: { functionDeclaration: "function() {alert('hello');}" } }; await commands.bidi.send(params); await commands.measure.start('https://www.sitespeed.io'); } ``` -------------------------------- ### Run Browsertime with TCPdump and SSL Key Log Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Capture network traffic with tcpdump and log SSL keys by setting the SSLKEYLOGFILE environment variable. ```bash SSLKEYLOGFILE=/path/to/file browsertime --tcpdump https://www.sitespeed.io docker run --rm -v "$(pwd)":/browsertime -e SSLKEYLOGFILE=/browsertime/keylog.txt sitespeedio/browsertime https://www.sitespeed.io/ -n 1 --tcpdump ``` -------------------------------- ### Run multi-URL tests via CLI Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/09-Examples.md Executes the multi-URL script using the command line interface. ```bash sitespeed.io testMultipleUrls.js --multi --browsertime.urls https://www.sitespeed.io --browsertime.urls https://www.sitespeed.io/documentation -n 1 ``` -------------------------------- ### Run Firefox on Android Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Enable Firefox on Android using the -b firefox --android flags. Configure with specific Android parameters. ```bash -b firefox --android --firefox.android.package --firefox.android.activity --firefox.android.deviceSerial --firefox.android.intentArgument ``` -------------------------------- ### Configure Test Runs and Browser Source: https://github.com/sitespeedio/browsertime/blob/main/README.md Adjust the number of test iterations or specify the browser engine to use. ```shell browsertime -n 5 https://www.example.com ``` ```shell browsertime --browser firefox https://www.example.com ``` -------------------------------- ### Measure login and subsequent pages Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/09-Examples.md Automates a login process and measures multiple pages sequentially using Browsertime commands. ```JavaScript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { // We start by navigating to the login page. await commands.navigate( 'https://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Main+Page' ); // When we fill in a input field/click on a link we wanna // try/catch that if the HTML on the page changes in the feature // sitespeed.io will automatically log the error in a user friendly // way, and the error will be re-thrown so you can act on it. try { // Add text into an input field, finding the field by id await commands.addText.byId('login', 'wpName1'); await commands.addText.byId('password', 'wpPassword1'); // Start the measurement before we click on the // submit button. Sitespeed.io will start the video recording // and prepare everything. await commands.measure.start('login'); // Find the sumbit button and click it and then wait // for the pageCompleteCheck to finish await commands.click.byIdAndWait('wpLoginAttempt'); // Stop and collect the measurement before the next page we want to measure await commands.measure.stop(); // Measure the Barack Obama page as a logged in user await commands.measure.start( 'https://en.wikipedia.org/wiki/Barack_Obama' ); // And then measure the president page return commands.measure.start('https://en.wikipedia.org/wiki/President_of_the_United_States'); } catch (e) { // We try/catch so we will catch if the the input fields can't be found // The error is automatically logged in Browsertime and re-thrown here // We could have an alternative flow ... // else we can just let it cascade since it caught later on and reported in // the HTML throw e; } }; ``` -------------------------------- ### Measure Single Page Application Navigation Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/03-Measurement-Commands.md Demonstrates measuring soft navigations in an SPA using visual metrics. Requires the --spa flag during execution to adjust measurement triggers. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.measure.start('https://react.dev'); await commands.measure.start('Learn'); await commands.mouse.singleClick.byLinkTextAndWait('Learn'); return commands.measure.stop(); } ``` ```bash sitespeed.io react.mjs --multi --spa --video --visualMetrics ``` -------------------------------- ### Configure Chrome WebView on Android Source: https://github.com/sitespeedio/browsertime/blob/main/CHANGELOG.md Specify the Android Activity and process name for Chrome WebView using --chrome.android.activity and --chrome.android.process. ```bash --chrome.android.activity --chrome.android.process ``` -------------------------------- ### Configure Chrome-Specific Performance Options Source: https://context7.com/sitespeedio/browsertime/llms.txt Apply Chrome-specific settings including timeline tracing, mobile emulation, CPU throttling, and custom browser arguments. ```bash # Collect Chrome timeline/trace data browsertime --chrome.timeline https://www.example.com # Emulate a mobile device browsertime --chrome.mobileEmulation.deviceName "iPhone 6" https://www.example.com # Custom viewport with mobile emulation browsertime --chrome.mobileEmulation.width 360 \ --chrome.mobileEmulation.height 640 \ --chrome.mobileEmulation.pixelRatio 2.0 https://www.example.com # CPU throttling (2x slowdown) browsertime --chrome.CPUThrottlingRate 2 https://www.example.com # Add custom Chrome arguments browsertime --chrome.args="--no-sandbox" --chrome.args="--disable-gpu" https://www.example.com # Collect network log browsertime --chrome.collectNetLog https://www.example.com # Test on Android device browsertime --android --chrome.android.package com.android.chrome https://www.example.com ``` -------------------------------- ### commands.element Source: https://context7.com/sitespeedio/browsertime/llms.txt Methods for retrieving Selenium WebElement references for advanced interactions. ```APIDOC ## commands.element Methods ### Description Retrieves elements from the DOM using various selectors to be used with the Action API. ### Methods - **getByCss(selector)**: Get element by CSS selector. - **getById(id)**: Get element by ID. - **getByXpath(xpath)**: Get element by XPath. - **getByClassName(className)**: Get element by class name. - **getByName(name)**: Get element by name attribute. ``` -------------------------------- ### Measure a multi-step checkout process Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/09-Examples.md Automates a sequence of page navigations, interactions, and metric collection for a guest checkout flow. ```JavaScript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { // Start by measuring the first page of the shop await commands.measure.start('https://shop.example.org'); // Then the product page // Either your shop has a generic item used for testing that you can use // or in real life you maybe need to add a check that the item really exists in stock // and if not, try another product await commands.measure.start('https://shop.example.org/prodcucs/theproduct'); // Add the item to your cart await commands.click.bySelector('.add-to-cart'); // Go to the cart (and measure it) await commands.measure.start('https://shop.example.org/cart/'); // Checkout as guest but you could also login as a customer // We hide the HTML to avoid that the click on the link will // fire First Visual Change. Best case you don't need to but we // want an complex example await commands.js.run('for (let node of document.body.childNodes) { if (node.style) node.style.display = "none";}'); await commands.measure.start('CheckoutAsGuest'); await commands.click.bySelectorAndWait('.checkout-as-guest'); // Make sure to stop measuring and collect the metrics for the CheckoutAsGuest step await commands.measure.stop(); // Finish your checkout await commands.js.run('document.body.style.display = "none"'); await commands.measure.start('FinishCheckout'); await commands.click.bySelectorAndWait('.checkout-finish'); // And collect metrics for the FinishCheckout step return commands.measure.stop(); // In a real web shop you probably can't finish the last step or you can return the item // so the stock is correct. Either you do that at the end of your script or you // add the item id in the context object like context.itemId = yyyy. Then in your // postScript you can do what's needed with that id. }; ``` -------------------------------- ### Configure multi-URL tests via JSON Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/09-Examples.md Defines the list of URLs to test using a JSON configuration file. ```json { "browsertime": { "urls": ["url1", "url2", "url3"] } } ``` -------------------------------- ### Perform Selenium Actions in Browsertime Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/04-Interact-with-the-page.md Demonstrates chaining Selenium actions like moving to an element, typing, and clicking using the Browsertime action API. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { await commands.measure.start('https://www.wikipedia.org'); const searchBox = await commands.element.getById('searchInput'); const submitButton = await commands.element.getByClassName( 'pure-button pure-button-primary-progressive' ); await commands.measure.start('Search'); await commands.action .getActions() .move({ origin: searchBox }) .pause(1000) .press() .sendKeys('Hepp') .pause(200) .click(submitButton) .perform(); // If you would do more actions after calling .perform() // you manually need to clear the action API //await commands.action.clear(); await commands.wait.byPageToComplete(); return commands.measure.stop(); } ``` -------------------------------- ### Modularize Browsertime scripts Source: https://github.com/sitespeedio/browsertime/blob/main/jsdoc/tutorials/02-Running-Scripts.md Splitting logic into multiple files using ES modules. ```JavaScript export async function example() { console.log('This is my example function'); } ``` ```JavaScript import { example } from './exampleInclude.mjs'; export default async function (context, commands) { example(); } ``` -------------------------------- ### Measure Custom Intervals with Stopwatch Source: https://context7.com/sitespeedio/browsertime/llms.txt Track specific user flows by creating a stopwatch. Ensure commands.measure.start is called before adding custom metrics. ```javascript /** * @param {import('browsertime').BrowsertimeContext} context * @param {import('browsertime').BrowsertimeCommands} commands */ export default async function (context, commands) { // Measure a URL first (required before adding metrics) await commands.measure.start('https://www.example.com'); // Create a stopwatch for custom timing const watch = commands.stopWatch.get('loginProcess'); // The stopwatch starts automatically when created await commands.navigate('https://www.example.com/login'); await commands.addText.byId('user@test.com', 'email'); await commands.addText.byId('password123', 'password'); await commands.click.byIdAndWait('loginButton'); // Stop and automatically add the time as a metric const duration = watch.stopAndAdd(); context.log.info(`Login process took ${duration}ms`); // Alternative: stop without adding (manual control) const anotherWatch = commands.stopWatch.get('checkoutFlow'); await commands.navigate('https://www.example.com/checkout'); // ... checkout steps ... const checkoutTime = anotherWatch.stop(); // Manually add the metric if needed commands.measure.add('checkoutDuration', checkoutTime); } ```