Localizadores (Locators) de Playwright

Locator (localizador) es uno de los conceptos más centrales de Playwright; representa una forma de encontrar elementos en la página.

Este capítulo presenta los métodos de localización recomendados por Playwright: localizar elementos mediante rol, texto, etiqueta y marcador de posición.


¿Qué es un Locator?

Locator es un objeto abstracto que Playwright utiliza para encontrar elementos en la página.

A diferencia de losdocument.querySelector()métodos tradicionales, el Locator de Playwright tieneespera automática y reintento automáticocapacidad.

Cuando el contenido de la página cambia dinámicamente, Locator vuelve a buscar elementos constantemente hasta que encuentra un elemento que coincida o se agota el tiempo de espera.

Ejemplo

// Crear un Locator (no buscará elementos inmediatamente)
const button = page.getByRole('button', { name: 'Enviar' });

// Al realizar la operación, Playwright esperará automáticamente a que el botón aparezca y esté en estado operable.
await button.click();

Cómo funciona Locator

Al crear un Locator, Playwright solo registra una regla de búsqueda.

Cuando llamas a.click()、.fill()tales operaciones oexpect(locator)aserciones, el Locator realmente comienza a buscar elementos.

Si no encuentra el elemento, Locator sigue reintentando hasta que la operación agota el tiempo de espera.


Localizar por rol: getByRole()

getByRole()Es el método de localización más recomendado por Playwright.

Se basa en elrol de accesibilidad (ARIA Role)para encontrar elementos; es la forma más cercana a la percepción del usuario.

Uso básico

Ejemplo

// Localizar un botón — mediante el rol "button"
const submitBtn = page.getByRole('button', { name: 'Enviar' });
await submitBtn.click();

// Localizar un enlace — mediante el rol "link"
const homeLink = page.getByRole('link', { name: 'Inicio' });
await homeLink.click();

// Localizar un encabezado — mediante el rol "heading"
const mainTitle = page.getByRole('heading', { name: 'Bienvenido a EJEMPLO' });

// Localizar un cuadro de texto — mediante el rol "textbox"
const searchBox = page.getByRole('textbox', { name: 'Buscar' });
await searchBox.fill('Playwright');

Roles ARIA comunes

RoleElemento HTML correspondienteEjemplo de uso
'button'<button>、role="button"getByRole('button', { name: '登录' })
'link'<a>getByRole('link', { name: '了解更多' })
'heading'<h1>~<h6>getByRole('heading', { name: 'EJEMPLO 教程' })
'textbox'<input type="text">、<textarea>getByRole('textbox', { name: '用户名' })
'checkbox'<input type="checkbox">getByRole('checkbox', { name: '记住我' })
'radio'<input type="radio">getByRole('radio', { name: '男' })
'combobox'<select>getByRole('combobox', { name: '城市' })
'img'<img>getByRole('img', { name: 'Logo' })
'list'<ul>、<ol>getByRole('list')
'listitem'<li>getByRole('listitem')
'navigation'<nav>getByRole('navigation')
'table'<table>getByRole('table')

Opción name

nameLa opción se especifica mediante elnombre accesiblepara reducir el alcance.

Las fuentes del nombre accesible incluyen: el contenido de texto del elemento,aria-labelatributos asociados<label>etc.

Ejemplo

// Coincidir mediante el texto del botón
page.getByRole('button', { name: 'Iniciar sesión' });

// Coincidir mediante aria-label
page.getByRole('button', { name: 'Cerrar diálogo' });

// Coincidencia con expresión regular
page.getByRole('link', { name: /EJEMPLO|novato/ });

Opciones de estado

Además dename,getByRoletambién admite varias opciones de estado:

Ejemplo

// Localizar una casilla de verificación seleccionada
page.getByRole('checkbox', { checked: true });

// Localizar un botón deshabilitado
page.getByRole('button', { disabled: true });

// Localizar un menú desplegable expandido
page.getByRole('button', { expanded: true });

// Localizar una opción seleccionada
page.getByRole('option', { selected: true });

// Combinar múltiples estados
page.getByRole('checkbox', { name: 'Aceptar el acuerdo', checked: false });

Localizar por texto: getByText()

getByText()Mediante elcontenido de texto del elementopara localizar.

Ejemplo

// Coincidencia exacta de texto
page.getByText('Bienvenido a EJEMPLO');

// Coincidencia parcial (por defecto)
page.getByText('EJEMPLO');

// Forzar coincidencia exacta
page.getByText('EJEMPLO', { exact: true });

// Coincidencia con expresión regular
page.getByText(/EJEMPLO|tutorial para novatos/);

getByTextCoincide con el contenido de texto completo del elemento, por lo tantogetByText('EJEMPLO', { exact: true })solo coincidirá con elementos cuyo contenido de texto sea exactamente "EJEMPLO".

Cuando no se usa coincidencia exacta por defecto, basta con la coincidencia de subcadena (por ejemplo,getByText('EJEMPLO')coincidirá con "Bienvenido a EJEMPLO").


Localizar por etiqueta: getByLabel()

getByLabel()Se utiliza para localizar<label>los controles de formulario asociados.

Ejemplo

// Estructura HTML:
// <label for="username">nombre de usuario</label>
// <input id="username" type="text" />

// Localizar el input mediante el texto de la label
await page.getByLabel('nombre de usuario').fill('ejemplo_user');

// Estructura HTML:
// <label>contraseña <input type="password" /></label>

// La label anidada también es válida
await page.getByLabel('contraseña').fill('password123');

También admite{ exact: true }la opción de coincidencia exacta.


Localizar por marcador de posición: getByPlaceholder()

getByPlaceholder()Mediante elplaceholderatributo se localiza el cuadro de entrada.

Ejemplo

// Estructura HTML: <input placeholder="Ingrese la palabra clave de búsqueda" />
await page.getByPlaceholder('Ingrese la palabra clave de búsqueda').fill('Playwright');

// Estructura HTML: <textarea placeholder="Cuéntanos lo que piensas..."></textarea>
await page.getByPlaceholder('Cuéntanos lo que piensas...').fill('¡Los tutoriales de EJEMPLO son increíbles!');

Elección entre getByLabel y getByPlaceholder

MétodoEscenario aplicablePrioridad
getByLabel()Cuando hay un elemento <label>Usar preferentemente
getByPlaceholder()Cuando no hay label, pero hay placeholderSegunda opción

getByRoleEs el método de localización más recomendado por Playwright, porque simula la forma en que los usuarios identifican los elementos por su rol. El siguiente esgetByLabelygetByPlaceholder. Solo considere usar XPathgetByTestIdo selectores CSS.


getByAltText() Localización de imágenes

getByAltText()Mediante elaltatributo se localiza el<img>elemento.

Ejemplo

// HTML:<img src="logo.png" alt="EJEMPLO Logo" />
await expect(page.getByAltText('EJEMPLO Logo')).toBeVisible();

// Coincidencia con expresión regular
await expect(page.getByAltText(/logo/i)).toBeVisible();

getByTitle() Localización por atributo title

getByTitle()Mediante eltitleatributo se localiza.

Ejemplo

// HTML: <button title="Cerrar la página actual">X</button>
await page.getByTitle('Cerrar la página actual').click();

getByAltTextygetByTitleSe usa con poca frecuencia, solo cuando el elemento tiene atributos alt o title claros y no se puede localizar de otra manera.


getByTestId() Localización por ID de prueba

getByTestId()SíPlan de respaldo, mediantedata-testidel atributo para localizar el elemento.

Ejemplo

// HTML: <button data-testid="submit-btn">Enviar</button>
await page.getByTestId('submit-btn').click();

// Puede contener múltiples coincidencias (como elementos de lista)
const items = page.getByTestId('todo-item');
await expect(items).toHaveCount(3);

Atributo testId personalizado

Si tu proyecto no usadata-testid, puedesplaywright.config.tspersonalizar el nombre del atributo en:

Ejemplo

// Ruta del archivo: playwright.config.ts
export default defineConfig({
  use: {
    // Usar data-cy en lugar de data-testid (para migración desde Cypress)
    testIdAttribute: 'data-cy',
    // O usar id como testId
    // testIdAttribute: 'id',
  },
});

page.locator() Localización con CSS y XPath

page.locator()Admite selectores CSS y XPath, es una alternativa más flexible.

Selectores CSS

Ejemplo

// Mediante la clase CSS
await page.locator('.submit-btn').click();

// Mediante el ID
await page.locator('#username').fill('ejemplo_user');

// Mediante el atributo
await page.locator('[data-type="primary"]').click();

// Mediante la combinación de etiqueta + clase
await page.locator('button.primary').click();

// Mediante la relación padre-hijo
await page.locator('nav a').first().click();

// Selector CSS que contiene un texto específico
await page.locator('button:has-text("Enviar")').click();

Localización con XPath

Ejemplo

// Usar XPath para localizar
await page.locator('xpath=//button[@type="submit"]').click();

// Localizar por texto
await page.locator('xpath=//h1[contains(text(), "EJEMPLO")]').click();

Los selectores CSS y XPath son la última opción, prioriza usargetByRole、getByTextmétodos de localización semánticos, etc. Los selectores CSS pueden fallar fácilmente por la refactorización de estilos, XPath es menos legible y más lento.


Operaciones en cadena de Locator

El Locator de Playwright admite llamadas en cadena, lo que permite filtrar aún más sobre los resultados coincidentes actuales.

.first()、.last()、.nth()

Ejemplo

// Obtener el primer elemento de lista coincidente
const firstItem = page.getByRole('listitem').first();

// Obtener el último
const lastItem = page.getByRole('listitem').last();

// Obtener el segundo (el índice comienza en 0)
const secondItem = page.getByRole('listitem').nth(1);

.filter() Filtrar

Ejemplo

// Filtrar de todos los botones los que contienen un texto específico
page.getByRole('button').filter({ hasText: 'Guardar' });

// Filtrar los que no contienen un texto específico
page.getByRole('listitem').filter({ hasNotText: 'Eliminado' });

// Filtrar los que contienen un elemento hijo específico
page.getByRole('listitem').filter({ has: page.getByRole('button') });

// Filtrar los que no contienen un elemento hijo específico
page.getByRole('listitem').filter({ hasNot: page.getByTestId('badge') });

.locator() Localizar elementos hijos

Ejemplo

// Primero localizar el contenedor de la lista, luego buscar botones dentro
const list = page.getByTestId('todo-list');
const deleteBtn = list.locator('button.delete');
await deleteBtn.click();

// Anidamiento de varios niveles
page
  .getByRole('dialog')
  .locator('div.content')
  .locator('button')
  .filter({ hasText: 'Confirmar' })
  .click();

.and() y .or() Combinación lógica (1.63+)

Ejemplo

// Cumplir ambas condiciones a la vez
const btn = page.getByRole('button')
  .and(page.getByText('Enviar'));

// Cumplir cualquiera de las condiciones
const target = page.getByText('EJEMPLO')
  .or(page.getByTitle('EJEMPLO'));

Resumen de prioridades de localización en Locator

Ordenados de mayor a menor recomendación:

PrioridadMétodoCondición de uso
1 (más recomendado)getByRole()El elemento tiene un rol ARIA explícito
2getByLabel()El elemento de formulario tiene una etiqueta (label) asociada
3getByPlaceholder()El campo de entrada tiene placeholder
4getByText()El elemento tiene contenido de texto explícito
5getByAltText()La imagen tiene el atributo alt
6getByTitle()El elemento tiene el atributo title
7 (respaldo)getByTestId()Cuando no se puede localizar con los métodos anteriores.
8 (última opción)locator()Selectores CSS / XPath
Otras extensiones