---
name: pw_wait_predicate
kind: function
lang: ts
domain: browser
version: "1.0.0"
purity: impure
signature: "async <T = unknown>(page: Page, predicate: string | ((arg?: unknown) => unknown), opts?: PwWaitOptions) => Promise<T>"
description: "Polls an arbitrary predicate inside the page context until it returns truthy or times out. Thin wrapper around page.waitForFunction with friendlier defaults and custom error messages. Use to wait for CSS class changes, DOM counts, or any computed condition."
tags: [playwright, e2e, browser, wait]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
  - name: page
    desc: "Playwright Page."
  - name: predicate
    desc: "JS expression as string OR function evaluated in page context. Returns truthy to stop polling."
  - name: opts
    desc: "{timeoutMs?, pollMs?, arg?, message?}."
output: "Resolved value of the predicate (page.waitForFunction jsonValue)."
tested: true
tests: ["defaults applied", "arg passed through", "jsonValue returned", "message wraps timeout"]
test_file_path: "frontend/functions/browser/pw_wait_predicate.test.ts"
file_path: "frontend/functions/browser/pw_wait_predicate.ts"
---

## Ejemplo

```typescript
import { pw_wait_predicate } from "./pw_wait_predicate";

// Wait for at least one red-bordered card to appear
await pw_wait_predicate(
  page,
  () => document.querySelectorAll('[data-card-id].border-red').length > 0,
  { timeoutMs: 2000, message: "no red-bordered card appeared" },
);

// Wait for exactly 1 highlighted card using an arg
await pw_wait_predicate(
  page,
  (sel) => document.querySelectorAll(sel as string).length === 1,
  { arg: ".highlighted", timeoutMs: 3000, pollMs: 50 },
);
```

## Cuando usarla

Cuando `waitForSelector` no basta porque la condicion depende de una clase CSS compuesta, un conteo exacto de elementos, o cualquier expresion calculada en el contexto de la pagina. Usar antes de assertions que requieren un estado DOM especifico que tarda en estabilizarse.

## Gotchas

- `predicate` se ejecuta en el contexto de la pagina (sandbox del browser), no en Node. No puede cerrar sobre variables de Node; usa `opts.arg` para pasar datos.
- Si `predicate` es una funcion, Playwright la serializa a string para enviarla al browser. No uses referencias externas ni closures de Node dentro de ella.
- `opts.message` solo se usa cuando `waitForFunction` lanza; no modifica el valor de retorno en caso de exito.
- `playwright` debe estar instalada en el proyecto consumidor como peer dependency. El registry no la instala.
- Con `polling: number`, Playwright hace polling activo (busy loop con sleeps cortos). Un `pollMs` muy bajo (< 50) puede saturar la CPU del browser en tests largos.
