Playwright JavaScript Execution

This chapter introduces how to execute JavaScript code in Playwright, including page context execution, parameter passing, and initial script injection.


page.evaluate() Page Context Execution

page.evaluate()Execute code in the page's JavaScript environment, with access to the DOM and page global variables.

Example

test('Get page data', async ({ page }) => {
  await page.goto('https://www.example.com/');

  // Get the page title (executed in page context)
  const title = await page.evaluate(() => {
    return document.title;
  });
  console.log('Page title:', title);

  // Get the number of all links on the page
  const linkCount = await page.evaluate(() => {
    return document.querySelectorAll('a').length;
  });
  console.log('Number of links:', linkCount);

  // Get the page scroll position
  const scrollY = await page.evaluate(() => {
    return window.scrollY;
  });
});

Passing Parameters to evaluate

page.evaluate()Its second parameter is passed to the function inside the page.

Example

test('Pass parameters to the page', async ({ page }) => {
  await page.goto('https://www.example.com/');

  // Pass a single parameter
  const result1 = await page.evaluate((name) => {
    return `Hello, ${name}!`;
  }, 'EXAMPLE');

  // Pass an object parameter
  const userInfo = { name: 'example', role: 'admin' };
  const result2 = await page.evaluate((user) => {
    return `${user.name}Its role is ${user.role}`;
  }, userInfo);

  // Pass multiple parameters (using destructuring)
  const result3 = await page.evaluate(
    ({ x, y }) => {
      return x + y;
    },
    { x: 10, y: 20 }
  );
  console.log('10 + 20 =', result3); // 30
});

The passed parameters are JSON-serialized and sent to the page context, so objects that cannot be serialized, such as functions and DOM elements, cannot be passed.

The returned value is also serialized.


locator.evaluate() Element Context Execution

locator.evaluate()Execute code in the context of the matched element; the parameter includes a reference to that element's DOM node.

Example

test('Get the DOM attributes of the element', async ({ page }) => {
  await page.goto('https://www.example.com/');

  // Get the textContent of a specific element
  const text = await page
    .getByRole('heading', { name: 'EXAMPLE' })
    .evaluate(node => node.textContent);

  // Get the style attribute of the element
  const color = await page
    .getByRole('button', { name: 'Search' })
    .evaluate(node => getComputedStyle(node).backgroundColor);
});

locator.evaluateAll() Iterating Over All Matching Elements

evaluateAll()Executes the same code for all matched elements and returns an array.

Example

test('Get the text of all list items', async ({ page }) => {
  await page.goto('https://www.example.com/');

  // Get the text of all menu items
  const menuItems = await page
    .getByRole('navigation')
    .locator('a')
    .evaluateAll(links => links.map(link => link.textContent));

  console.log('Menu items:', menuItems);
  // ['Home', 'Tutorial', 'Tools', ...]
});

page.addInitScript() Injecting Initial Scripts

addInitScript()Inject JavaScript code before the page loads, which canbefore the page scripts executemodify the browser environment.

Example

test('Inject initial script', async ({ page }) => {
  // Modify the navigator property before the page loads
  await page.addInitScript(() => {
    // Override WebDriver detection
    Object.defineProperty(navigator, 'webdriver', {
      get: () => false,
    });

    // Mock global variables on window
    window.EXAMPLE_CONFIG = {
      env: 'test',
      version: '1.0.0',
    };
  });

  await page.goto('https://www.example.com/');

  // Verify that the injected variables take effect
  const config = await page.evaluate(() => window.EXAMPLE_CONFIG);
  console.log(config); // { env: 'test', version: '1.0.0' }
});

addInitScript()Common use cases:

Use caseDescription
Mock browser APIOverridenavigator.webdriver、navigator.languagewait
Inject custom configurationSet test environment variables, mock data sources, etc.
Disable featuresTurn off Service Worker, disable logging, etc.
PolyfillAdd functionality that the page depends on but is missing in the test environment.

Uses and Limitations of ElementHandle

ElementHandle is a direct reference to a DOM element and was widely used in early versions of Playwright.

In most scenarios now, you should useLocatorinstead of ElementHandle.

Example

// ElementHandle approach (old style, not recommended)
const handle = await page.$('.my-element');
await handle.click();

// Locator approach (new style, recommended)
await page.locator('.my-element').click();

ElementHandle is only used when you need to getboundingBox()or when performing complex DOM operations.

Other Extensions