Playwright export
Upliftr is AI debugging agents that debug your app, read-only by design. When an agent confirms a flow, it saves the check as a plain-English suite. You can compile that suite into a standalone Playwright .spec.ts and drop it into any repo with @playwright/test, no Upliftr runtime, no LLM at runtime.
This neutralizes the most common objection to AI debugging agents, "non-deterministic, not reproducible, locked-in." The answer: let the agents reproduce and root-cause the failure, then run deterministic Playwright at run time when you want it.
Export via the API
curl http://127.0.0.1:8400/api/v1/suites/signup-login.upliftr.yaml/exportThe endpoint returns the spec as text/plain. Save it into your Playwright project:
curl http://127.0.0.1:8400/api/v1/suites/signup-login.upliftr.yaml/export \
-o tests/signup-login.spec.tsWhat you get
Each case becomes a test(...); the suite becomes a test.describe(...). Steps become a comment plus a best-effort action; expectations become real Playwright assertions:
// Generated from a Upliftr suite. Portable Playwright spec, no Upliftr
// runtime required. Locators and assertions are best-effort; review before use.
import { test, expect } from '@playwright/test';
test.describe('Signup & Login', () => {
test('A new user can sign up', async ({ page }) => {
await page.goto('http://localhost:8500');
// step: Open the sign-up page
// step: Enter email and password
// await page.getByLabel('field').fill('value');
// step: Click 'Create account'
await page.getByRole('button', { name: 'Create account' })
.or(page.getByText('Create account')).first().click();
// assert: a confirmation 'Account created' is shown
await expect(page.locator('body')).toContainText('Account created');
});
});How checks compile
Deterministic checks map straight to Playwright assertions:
| Check | Compiles to |
|---|---|
url (path_is / contains) | await expect(page).toHaveURL(...) |
visible_text (contains) | await expect(locator).toContainText(...) |
visible_text (equals + selector_hint) | await expect(locator).toHaveText(...) |
element_visible (selector_hint) | await expect(locator).toBeVisible() |
absent_text (any_of) | await expect(body).not.toContainText(...) per string |
Assertions with no deterministic check export as a clearly-marked // TODO assert: comment carrying the plain-English text, so a human can finish them. Likewise, steps export their action when the target is obvious (a quoted phrase or a Capitalized run) and a // (no obvious target, fill in the locator) hint otherwise.
When to use it
- You want determinism in CI. Let the agents confirm the check in Upliftr; run the exported spec in your existing Playwright pipeline.
- You're migrating in. Keep your Playwright project; let the Upliftr agents generate first drafts.
- You want zero lock-in. The export is plain
@playwright/test, yours to keep, edit, and run with no Upliftr dependency.
Best-effort, review before relying on it
The compiler derives locators and actions from prose, so the output is a strong starting point, not a guaranteed-green spec. Review the generated locators and finish any // TODO assertions before wiring it into a gate.
Related: URL → test generation · Checks reference · CI