@kifas/playwright
v2.1.0
Published
Kifas helpers for Playwright tests: AI/visual/compare checks, collect, state handles, and auth utilities
Maintainers
Readme
@kifas/playwright
Helpers for running Kifas-compiled Playwright tests in your own repo.
When you export a workflow from Kifas as Playwright code, the generated spec
imports this package. Install it alongside @playwright/test and the test runs
anywhere you run Playwright.
Install
npm install --save-dev @kifas/playwrightRequires @playwright/test >= 1.40 as a peer dependency.
Usage
import { test } from '@playwright/test'
import { kifas } from '@kifas/playwright'
test('checkout', async ({ page }) => {
await kifas.state.load(page, 'logged-in-user')
await page.goto('https://example.com/cart')
})Configuration
| Variable | Required | Default |
| --- | --- | --- |
| KIFAS_API_KEY | yes | — |
| KIFAS_API_BASE | no | https://api.kifas.io |
| KIFAS_PROJECT_ID | only for kifas.visualCheck, unless your key is project-scoped | — |
| KIFAS_BUILD_ID | no | — |
Your key needs the state:read and state:write scopes to use kifas.state,
workflow:run to use kifas.auth, ai_check:run to use kifas.aiCheck, and
visual_snapshot:write to use kifas.visualCheck. Issue one at
app.kifas.io/settings/api-keys.
API
kifas.state
load(page, handleName)— restore saved cookies into the page's context.save(page, handleName)— capture the page's storage state under a handle.
State saved here is the same state Kifas-hosted runs use, so a login captured in the dashboard is reusable from your own CI.
kifas.auth
checkFreshness(page, stateHandleRef, probeUrl, successSignal)fillTotp(page, secretRef, targetSelector, digits?)waitForInbox(page, inboxId, matchRegex, timeoutSeconds?)mintOauthToken(page, credentialsRef, mintMode, scopes, outputVariable, claims)setBearerHeader(page, tokenSource, headerName?, headerPrefix?)
kifas.collect(page, selector, { read, attribute?, columns?, timeoutMs? })
Reads a whole list, table, text value, attribute or count the same way Kifas
replays a Collect step — over a CDP session on page, so it only works on
Chromium. read is one of 'text' | 'items' | 'rows' | 'attribute' | 'count';
attribute is required when read: 'attribute', and columns restricts which
named columns read: 'rows' returns. timeoutMs defaults to 10 seconds.
const items = await kifas.collect(page, 'ul.results', { read: 'items' })kifas.compare(left, op, right, { normalize? })
Runs the exact comparison a Kifas Compare step runs — op is one of
'equals' | 'not_equals' | 'contains' | 'contains_all' | 'subset_of' | 'same_set' | 'gt' | 'gte' | 'lt' | 'lte' | 'matches'.
Returns { pass: true, detail } on success and throws KifasCheckError (with a
.detail object carrying missing/extra) when the comparison fails.
kifas.compare(items, 'contains_all', ['apple', 'pear'])kifas.aiCheck({ page, condition, vars?, screenshots?, tier?, timeoutMs? })
Asks Kifas to judge a plain-language condition against vars and optional
screenshots ('viewport' or { target: selector }). Billed to your AI
credits and cached for identical evidence. Throws KifasCheckError on a
failed verdict and KifasCheckUnavailableError when the check could not run
(for example, out of credits). timeoutMs bounds the request itself
(default 60s) — a slow judge aborts loudly instead of hanging your CI.
await kifas.aiCheck({
page,
condition: 'Every item in the cart is a fruit',
vars: { items },
screenshots: ['viewport'],
})kifas.visualCheck(page, name, { threshold?, mask?, target?, timeoutMs? })
Compares a screenshot of page (or of target if given) against its approved
baseline in Kifas. mask selectors are covered with a solid color before the
screenshot is taken and their boxes sent alongside it, so highlighted regions
never fail the diff. The first run under a name stores a baseline for
review; a later run that differs throws KifasCheckError, and a check the
platform could not evaluate (for example, no baseline capacity) throws
KifasCheckUnavailableError — the same taxonomy kifas.aiCheck uses. Requires
KIFAS_PROJECT_ID unless your API key is already scoped to one project. The
helper does not send a browser field, so it compares against the platform's
default (chromium) baseline regardless of which browser Playwright is
driving — non-Chromium baselines are not separated yet. mask boxes are sent
in CSS pixels; see the note on device pixel ratio below.
await kifas.visualCheck(page, 'checkout-page', { mask: ['.timestamp'] })License
MIT
