How the recording becomes a Playwright test
This page answers one question in detail: how to generate Playwright tests from user actions without ending up with a file the team has to rewrite. Retracio is a desktop app. You run the scenario by hand once, the app reads the conventions of your repository, and the result is a TypeScript or JavaScript spec file that reuses the page objects and fixtures you already have. Below is what happens at each step, what the app reads, what it sends to the model, and what stays on your machine.
Step 1: Run the test by hand
You open the app, start a session and walk through the scenario in the browser the way you would test it manually: navigate, click, type. On each screen you mark what should be true: a heading is visible, a row appeared in the table, the total equals the sum of the rows. Those marks become the assertions of the generated file, so a green run means the scenario worked rather than that buttons were clicked.
While you work, the app records every action together with the element it resolved, the page state before and after, and each check you marked. For every element it prefers a role, label or test-id locator and falls back to CSS or XPath only when nothing better exists. It also notes where the page waited on network or animation, so the generated test can wait for the same condition instead of a fixed timeout.
The output is a recorded run stored on your machine: an ordered list of steps with stable locators and explicit expectations. No code has been written yet.
- Open /products
- Click “Add to cart”
- Heading “Your cart” is visible
- Fill “Email”
- Click “Checkout”
- Row “Order summary” appeared
- Total equals the sum
Step 2: Point the app at the repository
You select the local checkout of the project and the folder where E2E tests live. The app scans the repository and builds a conventions profile from the framework and language, existing page objects and fixtures, file and test naming, assertion style, lint and formatter config, and custom helpers. If the repository has its own locator convention, such as a data-testid prefix, that becomes part of the profile too.
Generation runs through your own API key to Anthropic Claude. The request contains the recorded steps, trimmed DOM snapshots of the pages you visited, and excerpts of the conventions profile: page objects, fixtures, naming. Source code never leaves the machine, and neither do cookies, credentials or screenshots.
The draft that comes back is placed next to similar tests in the folder you chose. When the repository already has a page object or a helper for a screen you walked through, the draft imports it rather than duplicating selectors inline. A new page object appears only for a screen the repository has never covered, in the same shape as the existing ones.
- src/
- tests/e2e/
- login.spec.ts
- search.spec.ts
- pages/
- fixtures/
- framework
- Playwright · TypeScript
- page objects
- pages/CartPage.ts, pages/CheckoutPage.ts
- fixtures
- fixtures/auth.ts
- naming
- kebab-case · *.spec.ts
- lint
- eslint · prettier
Step 3: Review the generated test
The draft opens as a diff inside the app. You can edit it before committing: rename a step, tighten an assertion, or drop a check. Then you run the test locally with one click. The app executes it with Playwright against the same application and shows pass or fail per step.
When a step fails, you ask the app to regenerate that step alone. The rest of the file, including edits you already made, stays untouched, and the diff on the review screen shows exactly what changed. The review screen also lists the locator breakdown for the session (role, label, test-id, CSS) and one expect per check marked during the run.
A finished draft for a checkout scenario, in a repository that already has a signed-in fixture and a cart page object:
import { test, expect } from "../fixtures/test";
import { CatalogPage } from "../pages/CatalogPage";
import { CartPage } from "../pages/CartPage";
test.describe("checkout", () => {
test("adds two items and shows the correct cart total", async ({ page, signedIn }) => {
const catalog = new CatalogPage(page);
const cart = new CartPage(page);
await catalog.goto();
await catalog.addToCart("Standing desk");
await catalog.addToCart("Monitor arm");
await page.getByRole("link", { name: "Cart" }).click();
await expect(page.getByRole("heading", { name: "Your cart" })).toBeVisible();
await expect(cart.row("Standing desk")).toBeVisible();
await expect(cart.row("Monitor arm")).toBeVisible();
await cart.setQuantity("Standing desk", 2);
await expect(page.getByTestId("cart-total")).toHaveText(await cart.sumOfRows());
await page.getByRole("button", { name: "Proceed to checkout" }).click();
await expect(page).toHaveURL(/\/checkout$/);
await expect(page.getByLabel("Shipping address")).toBeVisible();
});
});
The file imports the fixture and the page objects from the repository's own folders. The locators are roles, labels and a test id. Each expect maps to a check marked during the manual run. Nothing in the file refers to Retracio.
Step 4: Commit and run in CI
You commit the file to a branch and open a pull request like any other test. The test is plain Playwright with no runtime, plugin or dependency from the app, so the pipeline treats it the same way it treats the tests written by hand. If the repository has no E2E job yet, the app offers a ready job snippet for GitHub Actions or GitLab CI that references only the Playwright runner.
From here on, the manual scenario runs on every push and reports on the pull request. If the test fails in CI after a change to the application, you handle it like any failing test: read the report, open the file, and fix or regenerate the failing step locally. No self-healing layer rewrites your tests behind your back, and uninstalling the app tomorrow leaves every generated test working.
- branch
- test/checkout-flow
- file
- tests/e2e/checkout.spec.ts
- message
- Add checkout flow test
# .github/workflows/e2e.yml
runs-on: ubuntu-latest
steps:
- run: npx playwright install --with-deps
- run: npx playwright test
What the app does not do
- It does not clone or upload your repository. It reads the local checkout only and writes generated tests as files into the folder you choose. Committing stays with you.
- It does not send source code, generated tests, browser sessions, cookies, screenshots or credentials anywhere. What leaves the machine is the recorded steps, trimmed DOM snapshots and excerpts of the conventions profile, sent to the LLM provider through your key.
- It does not run your tests in a cloud. The browser, the recording, the repository scan and the test execution happen locally inside the desktop app, and CI runs the test on your own pipeline.
- It does not add a dependency to your project. The output is a spec file with no Retracio import, plugin or runtime.
- It does not charge per test. Model cost is visible per generated test on the review screen and is billed by the provider whose key you use.
Currently supported: Playwright with TypeScript or JavaScript, on macOS and Windows, with GitHub Actions and GitLab CI. Cypress and WebdriverIO, Python and Java, and Jenkins, Azure Pipelines and CircleCI are planned.
Join the waitlist