/
Browse all pages

Copy a selector or locator

A unique CSS selector, a Playwright locator or an XPath, each checked against the page.

Press the copy button (Copy as) in the Element tab's head to copy one of:

  • Selector: the label shown in the head, such as div#box.
  • Unique CSS selector: an id, then a test attribute such as data-testid, then the shortest path of tag, class and :nth-of-type steps that matches only this element on the page.
  • Playwright locator: getByTestId, then getByRole with the accessible name when no other element shares that role and name, else locator() with the CSS selector.
  • Testing Library query: screen.getByTestId, getByRole with the name, then getByLabelText, getByPlaceholderText, getByAltText, getByTitle or getByText, else document.querySelector with the CSS selector.
  • Cypress: cy.get with a test attribute (data-cy, data-test, data-testid), else the unique CSS selector.
  • XPath: an absolute path.

For an element no role names, such as a meter, a field with only a placeholder or a span of text, Playwright and Testing Library use its label, placeholder, alt text, title or own text, in the order their docs recommend, when only that element has it.

Each one is checked against the page before it is offered. Inside a component they follow the way in:

  • The CSS selector names each shadow host, then the element inside its root, joined with >>>, as in my-card.second >>> #save. Puppeteer and WebdriverIO read it as it is.
  • The Playwright locator uses the test id, role or selector by itself when it is unique across the page and its components, since Playwright looks inside open roots; otherwise it is chained through each host: page.locator('my-card.second').locator('#save'). In a same-site frame it starts with contentFrame().
  • Cypress enters each host with .shadow() and a frame through its body: cy.get('#app').its('0.contentDocument.body').find('#save'). Testing Library searches a frame's document with within.
  • XPath and Testing Library cannot enter a shadow root, and Playwright and Cypress cannot enter a closed one, so the menu shows those as unavailable rather than copying something that matches nothing.

Inside a frame, the CSS selector and the XPath are for the frame's own page; the menu says so beside them.

Questions

How is the unique selector chosen?

An id, then a test attribute such as data-testid, then the shortest path of tag, class and :nth-of-type steps that matches only this element.

Why is XPath unavailable for some elements?

XPath cannot enter a shadow root, and Playwright cannot enter a closed one, so the menu shows them as unavailable rather than copying something that matches nothing.