Utilize cypress to analyze the loading time of a webpage

My current challenge involves using cypress to carry out website tests. I am looking for a reliable method to measure the duration it takes for certain cypress commands to load or execute. As an example:

//var startTime = SomeStopwatchFunction();
cy.visit("/a website");
cy.get("Some item");
//cy.log(SomeStopwatchFunction - startTime);

I attempted to utilize cy.clock(), but it consistently returns 0, indicating that I may be making a mistake there. While performance.now() seemed somewhat effective, it always yields the same value regardless of the loading time. Additionally, Date.getTime() also provides me with 0. The issue likely stems from how cypress executes the code, as none of these methods seem to deliver the desired outcome.

Answer №1

One of the easiest methods for timing the page load is by utilizing the events provided.

This approach eliminates the need to be concerned about hook codes such as before() or other setup commands that are typically required in testing scenarios.

cy.visit('http://localhost:3000/#/users', {
  onBeforeLoad: (win) => {
    win.t0 = performance.now()
  },
  onLoad: (win) => {
    t1 = performance.now()
    cy.log(`The page took ${t1 - win.t0} milliseconds to load.`)
  },
})

Answer №2

If you are measuring actions that occur asynchronously in Cypress, it is important to ensure your timing commands are placed in the queue using cy.wrap().

Otherwise, these commands may execute before the page fully loads, resulting in inaccurate measurements.

const startTime = performance.now()
cy.visit("/a website");
cy.get("Some item");
cy.wrap(performance.now()).then(endTime => {      
  cy.log(`Page load took ${endTime - startTime} milliseconds.`);
})

Answer №3

The solution provided by user9161752 in the accepted answer may produce unexpected outcomes. In my experience, the duration is consistently 5 seconds longer than expected. This discrepancy appears to stem from the fact that const t0 = performance.now() is being called prior to the execution of tasks within beforeEach, resulting in the inclusion of the login process duration in the final result.

To address this issue, it is necessary to set the start time asynchronously. The following approach worked for me:

let start = 0;
cy.then(() => {
    start = performance.now();
});
cy.visit("/desired-website");
cy.get("Specific element").then(() => {
    cy.log(`elapsed time: ${performance.now() - start} ms`);
});

Answer №4

For my specific situation, I needed to accurately measure the page load time immediately after a click event. To achieve this, I crafted the following script:

cy.get(loginLoginBtn).should('exist').then(() => {
        const startTime = performance.now();

        cy.get(loginLoginBtn)
        .click()
        .location('pathname').should('eq', '/package_selection')
        .wait('@recentProfiles').its('response.statusCode')
        .should('eq', 200)
        .then(() => {
            const endTime = performance.now();
            const pageLoadTime = ((endTime - startTime) / 1000);
            cy.log(`Page load took ${pageLoadTime} seconds.`)
            cy.writeFile(packagePageLoadFile, '[]', {flag: 'w+'});
            cy.readFile(packagePageLoadFile).then((writeTimeToFile) => {
                writeTimeToFile.push({dateOfExecution: executionDate, timeInSeconds: pageLoadTime});
                cy.writeFile(packagePageLoadFile, writeTimeToFile);
            });
            expect(pageLoadTime).to.be.lessThan(5);
        })
    }); 

Answer №5

Check out the cypress-timings tool for detailed timing information on each cypress command. Installation is simple - just add the code snippet below to your support/index.js:

import { commandTimings } from 'cypress-timings'
commandTimings()

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to upgrade Angular Header/Http/RequestOptions from deprecated in Angular 6.0 to Angular 8.0?

When working on http requests in Angular 6.0, I typically follow this block of code. https://i.sstatic.net/XsSv9.png I attempted to incorporate the newer features introduced in Angular 8.0 such as HttpClient, HttpResponse, and HttpHeaders. However, I fou ...

What steps can be taken to disable auto correction in ngx date picker?

In my application, I am utilizing ngx-datepicker with 'DD.MM.YYYY' as the dateInputFormat in the configuration settings of the date picker. The challenge arises when I manually input a date following the format 'YYYY.MM.DD', as the ente ...

Using INNER JOIN in MySQL queries tends to result in sluggish performance compared to using IN clauses

I have three database tables: product (10k records), product_attribute (4k records), and product_value (2m records). The product and product_attribute tables are linked via the product_value table. My goal is to retrieve specific information about a produc ...

Angular 9: Implementing a synchronous *ngFor loop within the HTML page

After receiving a list of subjects from the server, exercises are taken on each subject using the subject.id (from the server) and stored all together in the subEx variable. Classes are listed at the bottom. subjects:Subject[] temp:Exercise[] = [] s ...

Utilize a single function across multiple React components to interact with the Redux store, promoting code reusability and

Currently facing a dilemma. Here is a snippet of code that updates data in the redux store from a function, and it functions smoothly without any issues. const handleCBLabelText = (position: string, text: string) => { dispatch({ type: ' ...

Nullable Object in Vue 3 Composition API

I am utilizing the Vue 3 Composition api along with Typescript to create pinch zoom functionality using the HammerJS package. In my Vue application, I am attempting to replicate a functional example implemented in JavaScript from CodePen: https://codepen. ...

Encountering a Typescript issue when linking a class component with the reducer

Within my class component that is linked to the redux rootReducer, I am encountering a TypeScript error specifically related to the mapPropsToState section. The error message reads: Property 'unit' does not exist on type 'DefaultRootState&ap ...

Prompt user to save changes or cancel before closing modal (if closed by pressing ESC or clicking the backdrop)

When I manually close the modal, everything works fine. I just create a prompt and only call the BsModalRef.hide() method when the prompt (sweetalert) is closed. However, when the modal is closed using the ESC key or click-outside events provided by Boots ...

TypeScript shared configuration object utilizing type declarations

Currently, I am working on developing an API library and I have a question regarding how to approach the endpoint configuration issue in Node.js with TypeScript. My goal is to have all endpoint configurations contained within a single entity. The current ...

Using TypeScript's conditional types for assigning types in React

I'm tasked with creating a component that can belong to two different types. Let's call them Type A = { a: SomeCustomType } Type B = { b: SomeOtherDifferentType } Based on my understanding, I can define the type of this component as function C ...

Utilizing Vue and Typescript for efficient dependency injection

After attempting to use vue-injector, I encountered an issue as it was not compatible with my version of Vue (2.6.10) and Typescript (3.4.5). Exploring other alternatives, there seem to be limited options available. Within the realm of pure typescript, t ...

Struggling with implementing Angular and TypeScript in this particular method

I'm dealing with a code snippet that looks like this: myMethod(data: any, layerId: string, dataSubstrings): void { someObject.on('click', function(e) { this.api.getSomething(a).subscribe((result: any) => { // ERROR CALL 1. It ...

Obtain a string of characters from different words

I have been trying to come up with a unique code based on the input provided. Input = "ABC DEF GHI" The generated code would look like, "ADG" (first letter of each word) and if that is taken, then "ABDG" (first two letters o ...

Getting started with installing Bootstrap for your Next.Js Typescript application

I have been trying to set up Bootstrap for a Next.js Typescript app, but I'm having trouble figuring out the proper installation process. This is my first time using Bootstrap with Typescript and I could use some guidance. I've come across these ...

Learn how to use JavaScript to parse binary files

Is there a way to interpret this binary data below? Binary2 { sub_type: 0, buffer: Buffer(16) [ 12, 15, 64, 88, 174, 93, 16, 250, 162, 5, 122, 223, 16, 98, 207, 68 ], position: 16 } I've attempted different methods like using ...

Dealing with problematic hover behaviors in Cypress: A guide

I encountered an issue with Cypress hover functionality while trying to access a sub menu that appears after hovering over a main menu item. The error message I received was This element is not visible because it has CSS property: position: fixed and it&ap ...

Guide to generating a dropdown menu and linking it with data received from a server

I am completely new to Angular and recently received a project involving it. My task is to create a nested dropdown list for Json data retrieved from a server using Rest Api calls. The data contains a Level attribute that indicates the hierarchy level of ...

Errors occur with Metro bundler while utilizing module-resolver

Recently, I completed a project using the expo typescript template that runs on both iOS and Android platforms, excluding web. To enhance my development process, I established path aliases in the tsconfig.json file as shown below: "paths": { "@models/ ...

Combining various DTOs in a seamless manner for validation in TypeScript is made easy with the class-validator fusion technique

As I delved into my NestJS project, I found the class-validation aspect to be quite bothersome. It felt like I was constantly repeating the same classes with identical decorators. For example: export class DTO1 { @IsDefined() @IsString() name: ...

Dynamic Data Binding in Ionic 2

One challenge I am facing is with creating my own info window for a Google Maps marker. Whenever I click on the marker, a div is displayed but the information inside the div does not get updated. It seems like the event.title remains unchanged from its old ...