Extrair texto de uma lista de elementos, filtrar uma resposta de API e montar conjuntos de dados de teste usam os mesmos quatro métodos do JavaScript. São eles: map, filter, find e forEach. O erro mais comum no Playwright especificamente é chamar forEach com um callback async: ele dispara promises sem aguardar, então as assertions rodam antes dos dados chegarem.

Arrays: revisão de um minuto

Um array é uma lista ordenada de valores:

const usuarios = ['Alice', 'Bob', 'Charlie'];
const precos = [12.99, 5.50, 29.00, 8.75];
const casosDeTeste = [
  { input: 'valido@email.com', devePassar: true },
  { input: 'nao-e-email',      devePassar: false },
  { input: '',                 devePassar: false },
];

Você acessa elementos pelo índice (começando em 0):

console.log(usuarios[0]);   // 'Alice'
console.log(usuarios[2]);   // 'Charlie'
console.log(usuarios.length); // 3

Tudo o mais neste guia parte daqui.

forEach: faça algo com cada item

forEach roda uma função uma vez para cada item do array. Use quando quiser fazer algo com cada item, mas não precisar de um resultado de volta.

const usernames = ['alice', 'bob', 'charlie'];

usernames.forEach((nome) => {
  console.log(`Testando usuário: ${nome}`);
});

// Saída:
// Testando usuário: alice
// Testando usuário: bob
// Testando usuário: charlie

Em testes Playwright

const urlsDeLogin = [
  '/pt/login',
  '/en/login',
  '/es/login',
];

// Verificar que todas as páginas de login por locale carregam
// (não é o padrão ideal, mas mostra o forEach em ação)
urlsDeLogin.forEach(async (url) => {
  await page.goto(url);
  await expect(page.locator('h1')).toBeVisible();
});

Quando usar forEach: quando você quer efeitos colaterais: logging, cliques, preencher formulários. Não use quando precisar transformar ou filtrar dados. O map e o filter são mais adequados para esses casos.

map: transforme cada item

map cria um novo array aplicando uma função a cada item. O array original não muda.

Pense assim: "para cada item, me devolva algo diferente."

const precos = [10, 20, 30];
const comDesconto = precos.map((preco) => preco * 0.9);

console.log(comDesconto); // [9, 18, 27]
console.log(precos);      // [10, 20, 30]  ← inalterado

Exemplo prático: extraindo texto de uma lista de elementos

Com frequência você recebe um array de locators do Playwright e precisa extrair o texto de cada um:

// Pegar todos os textos de células de uma tabela
const celulas = await page.locator('table tbody td').all();
const textos = await Promise.all(
  celulas.map((celula) => celula.textContent())
);
// textos = ['Alice', '28', 'Admin', 'Bob', '34', 'User', ...]

Montando dados de teste com map

const ids = [1, 2, 3, 4, 5];

const usuariosDeTeste = ids.map((id) => ({
  id,
  username: `user_${id}`,
  email: `user${id}@teste.com`,
  role: id === 1 ? 'admin' : 'member',
}));

/*
[
  { id: 1, username: 'user_1', email: 'user1@teste.com', role: 'admin' },
  { id: 2, username: 'user_2', email: 'user2@teste.com', role: 'member' },
  ...
]
*/

Transformando dados de resposta de API

// API retorna dados brutos
const usuariosApi = [
  { first_name: 'Alice', last_name: 'Silva',  is_active: 1 },
  { first_name: 'Bob',   last_name: 'Santos', is_active: 0 },
];

// Transformar para o que a UI exibe
const usuariosExibidos = usuariosApi.map((u) => ({
  nome: `${u.first_name} ${u.last_name}`,
  ativo: u.is_active === 1,
}));

// [{ nome: 'Alice Silva', ativo: true }, { nome: 'Bob Santos', ativo: false }]

Quando usar map: quando quiser transformar cada item de um array em outra coisa. O resultado tem sempre o mesmo tamanho do input.

filter: fique só com o que você precisa

filter cria um novo array contendo apenas os itens que passam em um teste. Os que reprovam são descartados.

const precos = [5, 12, 3, 25, 8, 40, 1];
const caros = precos.filter((preco) => preco > 10);

console.log(caros);   // [12, 25, 40]
console.log(precos);  // [5, 12, 3, 25, 8, 40, 1]  ← inalterado

Filtrando casos de teste

É aqui que filter brilha na automação. Com uma lista grande de casos de teste, você pode dividi-los:

const todosCasos = [
  { input: 'valido@email.com',  devePassar: true },
  { input: 'outro@teste.org',   devePassar: true },
  { input: 'nao-e-email',       devePassar: false },
  { input: '',                  devePassar: false },
  { input: 'faltando@',         devePassar: false },
];

const casosValidos   = todosCasos.filter((tc) => tc.devePassar);
const casosInvalidos = todosCasos.filter((tc) => !tc.devePassar);

// casosValidos tem 2 itens, casosInvalidos tem 3

Filtrando resultados de API

// Todos os pedidos da API
const pedidos = [
  { id: 1, status: 'concluido', valor: 99 },
  { id: 2, status: 'pendente',  valor: 45 },
  { id: 3, status: 'concluido', valor: 12 },
  { id: 4, status: 'cancelado', valor: 75 },
];

// Manter apenas pedidos concluídos para verificação
const pedidosConcluidos = pedidos.filter((p) => p.status === 'concluido');
// [{ id: 1, ... }, { id: 3, ... }]

Filtrando elementos da página por texto

// Todas as linhas de uma tabela
const linhas = await page.locator('table tbody tr').all();

// Apenas linhas que contêm 'Admin'
const linhasAdmin = [];
for (const linha of linhas) {
  const texto = await linha.textContent();
  if (texto?.includes('Admin')) {
    linhasAdmin.push(linha);
  }
}

Quando usar filter: quando quiser um subconjunto de um array. O resultado pode ser mais curto que o input (ou até vazio).

find: pegue o primeiro que corresponde

find retorna o primeiro item que passa em um teste. Se nada corresponder, retorna undefined. Ao contrário de filter, para de buscar assim que encontra uma correspondência.

const usuarios = [
  { id: 1, nome: 'Alice', role: 'admin' },
  { id: 2, nome: 'Bob',   role: 'member' },
  { id: 3, nome: 'Carol', role: 'admin' },
];

const primeiroAdmin = usuarios.find((u) => u.role === 'admin');
// { id: 1, nome: 'Alice', role: 'admin' }

const usuarioAusente = usuarios.find((u) => u.nome === 'Dave');
// undefined

Encontrando dados de teste por ID

const produtos = [
  { id: 'PROD-001', nome: 'Notebook', preco: 999 },
  { id: 'PROD-002', nome: 'Mouse',    preco: 29  },
  { id: 'PROD-003', nome: 'Mesa',     preco: 349 },
];

const produtoAlvo = produtos.find((p) => p.id === 'PROD-002');
// { id: 'PROD-002', nome: 'Mouse', preco: 29 }

Sempre verifique se não é undefined

const produto = produtos.find((p) => p.id === 'PROD-999');

if (!produto) {
  throw new Error('Dado de teste não encontrado: PROD-999');
}

// Agora é seguro usar produto
await page.fill('[data-testid="busca"]', produto.nome);

Quando usar find: quando precisar exatamente de um item de um array e souber o que está procurando. Se precisar de todas as correspondências, use filter.

Combinando os métodos

O poder real vem de encadeá-los:

const pedidosApi = [
  { id: 1, usuario: 'alice', status: 'concluido', valor: 150, itens: 3 },
  { id: 2, usuario: 'bob',   status: 'pendente',  valor: 50,  itens: 1 },
  { id: 3, usuario: 'alice', status: 'concluido', valor: 200, itens: 5 },
  { id: 4, usuario: 'carol', status: 'cancelado', valor: 75,  itens: 2 },
  { id: 5, usuario: 'alice', status: 'pendente',  valor: 30,  itens: 1 },
];

// Total dos pedidos concluídos da Alice
const totalAliceConcluido = pedidosApi
  .filter((p) => p.usuario === 'alice' && p.status === 'concluido')
  .map((p) => p.valor)
  .reduce((soma, valor) => soma + valor, 0);

// 150 + 200 = 350

Ou para verificação:

// Verificar que todos os preços de produto visíveis são maiores que zero
const locatorsPreco = await page.locator('[data-testid="preco-produto"]').all();
const precos = await Promise.all(
  locatorsPreco.map(async (el) => {
    const texto = await el.textContent();
    return parseFloat(texto?.replace('R$', '').replace(',', '.').trim() ?? '0');
  })
);

const temPrecoNegativo = precos.some((p) => p <= 0);
expect(temPrecoNegativo).toBe(false);

Referência rápida

| Método | O que retorna | Use quando |

|--------|--------------|------------|

| forEach | Nada (undefined) | Quer efeitos colaterais (logging, ações) |

| map | Novo array, mesmo tamanho | Quer transformar cada item |

| filter | Novo array, menor ou igual | Quer um subconjunto de itens |

| find | Um item ou undefined | Quer a primeira correspondência |

Erros comuns

Usar map quando quer forEach:

// Errado — map é para retornar valores, não efeitos colaterais
usuarios.map((usuario) => {
  console.log(usuario.nome); // funciona, mas é desperdício
});

// Correto
usuarios.forEach((usuario) => {
  console.log(usuario.nome);
});

Esquecer que find pode retornar undefined:

// Isso vai lançar erro se o usuário não for encontrado
const usuario = usuarios.find((u) => u.id === 99);
usuario.nome; // TypeError: Cannot read properties of undefined

Mutar o array original com map:

Se você fizer usuarios.map((u) => { u.role = 'admin'; return u; }), está mutando os objetos originais, não criando novos. Crie objetos novos:

// Correto — cria novos objetos
usuarios.map((u) => ({ ...u, role: 'admin' }));

Nota sobre async no Playwright

Quando o callback é async (o que acontece constantemente no Playwright), use Promise.all:

// Não funciona — forEach ignora promises
celulas.forEach(async (celula) => {
  const texto = await celula.textContent();  // dispara e esquece
});

// Funciona — aguarda todas as promises
const textos = await Promise.all(
  celulas.map(async (celula) => await celula.textContent())
);

Esse é o erro de "async em arrays" mais comum no Playwright. Na dúvida, use Promise.all com map.

Com isso, você tem os métodos de array mais usados em suites Playwright reais. map, filter, find e forEach cobrem 90% do que você vai precisar ao trabalhar com dados de teste, respostas de API e arrays de elementos de página.

→ Veja também: JavaScript para QA Engineers: O Mínimo para Começar a Automatizar | Async/Await em Português Simples (para Testadores que se Perdem com Promises) | Objetos JavaScript e Desestruturação para Engenheiros QA