playwright/docs-src/api-footer.md
Dmitry Gozman c8e9b0542b
feat(selectors): disable proximity selectors (#4659)
These are not ready for prime time yet.
2020-12-10 10:04:10 -08:00

11 KiB

EvaluationArgument

Playwright evaluation methods like page.evaluate(pageFunction[, arg]) take a single optional argument. This argument can be a mix of Serializable values and JSHandle or ElementHandle instances. Handles are automatically converted to the value they represent.

See examples for various scenarios:

// A primitive value.
await page.evaluate(num => num, 42);

// An array.
await page.evaluate(array => array.length, [1, 2, 3]);

// An object.
await page.evaluate(object => object.foo, { foo: 'bar' });

// A single handle.
const button = await page.$('button');
await page.evaluate(button => button.textContent, button);

// Alternative notation using elementHandle.evaluate.
await button.evaluate((button, from) => button.textContent.substring(from), 5);

// Object with multiple handles.
const button1 = await page.$('.button1');
const button2 = await page.$('.button2');
await page.evaluate(
    o => o.button1.textContent + o.button2.textContent,
    { button1, button2 });

// Obejct destructuring works. Note that property names must match
// between the destructured object and the argument.
// Also note the required parenthesis.
await page.evaluate(
    ({ button1, button2 }) => button1.textContent + button2.textContent,
    { button1, button2 });

// Array works as well. Arbitrary names can be used for destructuring.
// Note the required parenthesis.
await page.evaluate(
    ([b1, b2]) => b1.textContent + b2.textContent,
    [button1, button2]);

// Any non-cyclic mix of serializables and handles works.
await page.evaluate(
    x => x.button1.textContent + x.list[0].textContent + String(x.foo),
    { button1, list: [button2], foo: null });

Environment Variables

Note

playwright-core does not respect environment variables.

Playwright looks for certain environment variables to aid its operations. If Playwright doesn't find them in the environment, a lowercased variant of these variables will be used from the npm config.

  • PLAYWRIGHT_DOWNLOAD_HOST - overwrite URL prefix that is used to download browsers. Note: this includes protocol and might even include path prefix. By default, Playwright uses https://storage.googleapis.com to download Chromium and https://playwright.azureedge.net to download Webkit & Firefox. You can also use browser-specific download hosts that superceed the PLAYWRIGHT_DOWNLOAD_HOST variable:
    • PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST - host to specify Chromium downloads
    • PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST - host to specify Firefox downloads
    • PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST - host to specify Webkit downloads
  • PLAYWRIGHT_BROWSERS_PATH - specify a shared directory that playwright will use to download browsers and to look for browsers when launching browser instances.
  • PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD - set to non-empty value to skip browser downloads altogether.
# Linux/macOS
# Install browsers to the shared location.
$ PLAYWRIGHT_BROWSERS_PATH=$HOME/playwright-browsers npm install --save-dev playwright
# Use shared location to find browsers.
$ PLAYWRIGHT_BROWSERS_PATH=$HOME/playwright-browsers node playwright-script.js

# Windows
# Install browsers to the shared location.
$ set PLAYWRIGHT_BROWSERS_PATH=%USERPROFILE%\playwright-browsers
$ npm install --save-dev playwright
# Use shared location to find browsers.
$ set PLAYWRIGHT_BROWSERS_PATH=%USERPROFILE%\playwright-browsers
$ node playwright-script.js

Working with selectors

Selector describes an element in the page. It can be used to obtain ElementHandle (see page.$() for example) or shortcut element operations to avoid intermediate handle (see page.click() for example).

Selector has the following format: engine=body [>> engine=body]*. Here engine is one of the supported selector engines (e.g. css or xpath), and body is a selector body in the format of the particular engine. When multiple engine=body clauses are present (separated by >>), next one is queried relative to the previous one's result.

Playwright also supports the following CSS extensions:

  • :text("string") - Matches elements that contain specific text node. Learn more about text selector.
  • :visible - Matches only visible elements. Learn more about visible selector.
  • :light(selector) - Matches in the light DOM only as opposite to piercing open shadow roots. Learn more about shadow piercing.

For convenience, selectors in the wrong format are heuristically converted to the right format:

  • selector starting with // or .. is assumed to be xpath=selector;
  • selector starting and ending with a quote (either " or ') is assumed to be text=selector;
  • otherwise selector is assumed to be css=selector.
// queries 'div' css selector
const handle = await page.$('css=div');

// queries '//html/body/div' xpath selector
const handle = await page.$('xpath=//html/body/div');

// queries '"foo"' text selector
const handle = await page.$('text="foo"');

// queries 'span' css selector inside the result of '//html/body/div' xpath selector
const handle = await page.$('xpath=//html/body/div >> css=span');

// converted to 'css=div'
const handle = await page.$('div');

// converted to 'xpath=//html/body/div'
const handle = await page.$('//html/body/div');

// converted to 'text="foo"'
const handle = await page.$('"foo"');

// queries '../span' xpath selector starting with the result of 'div' css selector
const handle = await page.$('div >> ../span');

// queries 'span' css selector inside the div handle
const handle = await divHandle.$('css=span');

Working with Chrome Extensions

Playwright can be used for testing Chrome Extensions.

Note

Extensions in Chrome / Chromium currently only work in non-headless mode.

The following is code for getting a handle to the background page of an extension whose source is located in ./my-extension:

const { chromium } = require('playwright');

(async () => {
  const pathToExtension = require('path').join(__dirname, 'my-extension');
  const userDataDir = '/tmp/test-user-data-dir';
  const browserContext = await chromium.launchPersistentContext(userDataDir,{
    headless: false,
    args: [
      `--disable-extensions-except=${pathToExtension}`,
      `--load-extension=${pathToExtension}`
    ]
  });
  const backgroundPage = browserContext.backgroundPages()[0];
  // Test the background page as you would any other page.
  await browserContext.close();
})();

Note

It is not yet possible to test extension popups or content scripts.