TestWatchStart free

From a sentence to a scheduled Playwright test

One real test, recorded on the open-source demo shop: the whole loop in 30 seconds.

The whole loop in 30 seconds

Recorded 3 October 2026 against the open-source Fieldmark demo shop: the request, the agent exploring the shop, the generated Playwright test and its replay, a passing run with no AI calls, and a fix approved after the page changed. Has music, no narration.

Step through it yourself

Press a tab, or pick another real generation.

Checkout with 2FA sign-in, on the Fieldmark demo shop

You describe the flow

  1. Sign in as the 2FA shopper: username and password, then the 6-digit authenticator code.
  2. Open the Waterproof Notebook and add one to the cart.
  3. Check out: fill in a shipping address and pay with the test card 4242 4242 4242 4242, any future expiry date and CVC 123.
  4. Check the order confirmation says the order was placed and the total is $21.00 (the $16.00 notebook plus $5.00 shipping).
Real generations:

TestWatch writes a Playwright test

checkout-with-2fa-sign-in.spec.ts

import { test, expect, otp } from '../fixtures';

test('Checkout with 2FA sign-in', async ({ page }) => {
  await test.step('Sign in as the 2FA shopper', async () => {
    await page.getByRole('link', { name: 'Sign in' }).click();
    await page.getByRole('textbox', { name: 'Username' }).fill(process.env.TARGET_EMAIL!);
    await page.getByRole('textbox', { name: 'Password' }).fill(process.env.TARGET_PASSWORD!);
    await page.getByRole('button', { name: 'Sign in' }).click();

    await page.getByRole('textbox', { name: 'Authentication code' }).fill(otp());
    await page.getByRole('button', { name: 'Verify' }).click();

    await expect(page.getByRole('button', { name: 'Sign out' })).toBeVisible();
  });

  await test.step('Open the Waterproof Notebook and add one to the cart', async () => {
    await page.getByRole('link', { name: 'Waterproof Notebook' }).click();
    await page.getByTestId('add-to-cart').click();
    await expect(page.getByRole('link', { name: 'Check out' })).toBeVisible();
  });

  await test.step('Check out and pay with test card', async () => {
    await page.getByRole('link', { name: 'Check out' }).click();

    await page.getByRole('textbox', { name: 'Street address' }).fill('123 Main St');
    await page.getByRole('textbox', { name: 'City' }).fill('Anytown');
    await page.getByRole('textbox', { name: 'Postcode' }).fill('12345');

    const paymentFrame = page.locator('iframe[title="Secure card payment input frame"]').contentFrame();
    await paymentFrame.getByRole('textbox', { name: 'Card number' }).fill('4242 4242 4242 4242');
    await paymentFrame.getByRole('textbox', { name: 'Expiration (MM / YY)' }).fill('12/28');
    await paymentFrame.getByRole('textbox', { name: 'CVC' }).fill('123');

    await page.getByTestId('place-order').click();
  });

  await test.step('Verify order confirmation and total', async () => {
    await expect(page.getByText('Thanks! Your order has been placed.')).toBeVisible();
    await expect(page.getByTestId('order-total')).toHaveText('$21.00');
  });
});

It runs on a schedule

  1. PassedSign in as the 2FA shopper310 ms
  2. PassedOpen the Waterproof Notebook and add one to the cart130 ms
  3. PassedCheck out and pay with test card185 ms
  4. PassedVerify order confirmation and total65 ms

0AI calls on this passing run

The page changed. You approve the fix

Proposed fixThe page changed, not the app’s behaviour.

    await page.getByRole('link', { name: 'Waterproof Notebook' }).click();
Removed:     await page.getByTestId('add-to-cart').click();
Added:     await page.getByTestId('add-to-bag').click();

A real run from 3 October 2026, exported from TestWatch unedited.

Step by step

  1. You describe the flow

    Write what a user does and what should be true at the end, in plain English. If something is unclear (which account, which product), TestWatch asks before it starts.

    Example: a login with 2FA

  2. It explores your app and writes the test

    An AI agent opens your live app in a real browser, follows the flow, checks each step works, and writes a Playwright test with named steps. Then it runs the test against your app before calling it ready.

    How the test generator works

    TestWatch dashboard while it generates the test “Sign in with 2FA, purchase a product, and verify total with $5 shipping”. The step log shows the agent filling the shipping address and the 4242 test card on the demo shop, then self-verify passed; the drafted test is being checked twice against the live app.
    Recorded 19 October 2026 on the Fieldmark demo shop. Unedited dashboard screenshot.
  3. It runs on a schedule or from CI, without AI

    Runs are plain Playwright on our browsers, on up to 4 browser profiles. They start on a preset or cron schedule, by hand, or (Starter and up) from CI through the GitHub Action, the CLI, the API or a deploy hook. A passing run makes no AI calls, which is why every plan includes the runs.

    Run it from CI: the docs

    TestWatch result page for the checkout test on the demo shop's production environment: all 12 steps passed in 2.9 seconds, each step listed with its timing and a screenshot thumbnail.
    Recorded 19 October 2026 on the Fieldmark demo shop. Unedited dashboard screenshot.
  4. A failure gets a reason

    When a run fails, TestWatch looks at the evidence and says what happened: the page changed, a real bug, the app is down, a CAPTCHA blocked it, or the login no longer works. When it isn’t a page change, it asks you instead of changing the test.

    TestWatch result page marked App bug found: the checkout test failed at step 12 of 12 on a staging copy of the demo shop. Expected the order total $17.00 (product price plus $5 shipping), but the page showed $12.00, with the step list above the failure.
    Recorded 19 October 2026 on the Fieldmark demo shop. Unedited dashboard screenshot.
  5. You approve the fix

    For a page change it proposes a new locator or wait as a diff. Assertions in your main tests are never touched, and nothing changes until you approve it. A fix you accept on a pull-request preview may also update a check’s expected text; it is applied to the main test once it passes there twice, with a notice and Undo.

    How proposed fixes work

    TestWatch result page for a checkout test that failed on a staging copy of the demo shop where the add-to-cart button was renamed. The Suggested fix tab marks it Test outdated at 98% confidence and shows a one-line diff from getByTestId('add-to-cart') to getByTestId('add-to-bag'), waiting for Apply fix or Decline.
    Recorded 19 October 2026 on the Fieldmark demo shop. Unedited dashboard screenshot.

What it won’t do

  • No

    Log in with SMS codes, or through Google, GitHub or SSO in your app. It tells you instead.

  • No

    Get past a CAPTCHA or bot wall. It tells you the flow is blocked instead.

  • No

    Change what a test checks. Fixes touch locators and waits only.

  • No

    Test native mobile apps. Mobile means mobile browsers, emulated.

Try it on your own app.

Free: 5 tests, 500 runs a month, 2 apps and one daily schedule. Unlimited teammates, no card.

Start freeAll features

The story above is Fieldmark demo shop data, exported from TestWatch unedited.