Enhancing Web Testing with Playwright’s Evaluate Method

Cerosh Jacob
3 min readSep 18


Photo by John Schnobrich on Unsplash

In the early days of test automation, JavaScript was commonly used to execute custom functions, while VBScript was popular for test automation, especially with Internet Explorer as the dominant web browser. However, these methods were not always user-friendly and were prone to errors. Despite their limitations, they were the best options available at that time.

In recent years, new test automation frameworks have emerged, making it easier to execute custom JavaScript functions on web pages. These frameworks often use a CSS selector syntax to identify elements on the page, simplifying the process of writing and maintaining test cases.

The evaluate() method allows executing code within the context of a web page. If the function returns a Promise, the evaluate() method will wait for the Promise to resolve before returning. In the playwright, the evaluate() function can be written as either an arrow function or a regular function. It takes two arguments: a function to be executed within the web page's context, and an optional argument that can be passed to the function. This feature is useful for various tasks, such as:

1. Manipulating the DOM of a web page

Text boxes can come in different types, such as input elements or divs. In certain cases, the structure of the page might not include text or input elements, but rather divs. In such situations, if you need to change the inner HTML of a div using Playwright, you might face a challenge. However, there is a solution to this. You can rely on Typescript using the evaluate command. This way, you can manipulate the content of the div and achieve the desired result.

const element = page.getByTestId('option-list-edit-price');
await element.evaluate((e1)=>{
e1.innerHTML = "100"

Be careful when using the evaluate() method to modify the DOM of a web page. If you make changes to the DOM, you may need to wait for the page to reload before continuing with your test.

2. Executing custom JavaScript functions

Another use case for the “evaluate” function is to validate the border style by extracting the computed border width and style, ensuring they match the expected style, and throwing an error if a discrepancy is detected.

import { expect } from 'chai'; // Make sure you have 'chai' installed
const EXPECTED_BORDER_STYLE = '2px dashed';

validateBorderOutline = async (): Promise<void> => {
const element = this.unCategorisedSection.last();
if (!element) {
throw new Error('Element not found');
const borderStyle = await element.evaluate((el) => {
const computedStyle = getComputedStyle(el);
return `${computedStyle.borderWidth} ${computedStyle.borderStyle}`;
expect(borderStyle).to.equal(EXPECTED_BORDER_STYLE, `Unexpected border style. Expected: ${EXPECTED_BORDER_STYLE}, Actual: ${borderStyle}`);

3. Accessing and modifying global variables

You can use the evaluate() method to access and modify global variables. For example, you could use the evaluate() method to set the value of the document.location property to navigate to a different web page.


In Cypress, the cy.task() function allows you to execute code in the browser context and return the result to the test runner. It is asynchronous, meaning that the test can continue executing while the task is running.

On the other hand, the evaluate() function is synchronous and will block the execution of the test until it returns. It can only be used to execute code in the current page.

Additionally, the cy.task() function can return multiple values, while the evaluate() function can only return a single value.

Another difference is that the cy.task() function can execute functions that are defined in the test runner, whereas the evaluate() function cannot.