What Playwright codegen does
Playwright ships a test generator. You run npx playwright codegen your-site.example, a browser opens beside an inspector, and it writes code for each click and keystroke. Its documentation says it favours role, text and test-id locators, and that it can add assertions for visibility, text and values. It produces test code only: no screenshots and no documentation.
Codegen runs in a browser that Playwright launches. If the flow needs your real session, an extension, or a page behind single sign-on, you have to preserve authentication state or script the login first.
What Showsteps adds
- Records in the Chrome you already use, across tabs, in your signed-in session.
- Gives you the guide and the test from one recording. The steps you review for documentation are the steps that get replayed.
- Uses the best locator per step. It tries
getByTestId,getByRoleandgetByLabelbefore text, and falls back to CSS only when nothing else identifies the element. - Lets you edit before export. Delete a wrong click, merge two typing steps, or skip a step, in the editor.
- Handles sensitive input. Values typed into password fields are never stored, so they never end up in a script you commit.
What the exported test looks like
// Generated by Showsteps (https://showsteps.vercel.app) from the guide "Invite a teammate", 6 steps.
// Run it with: npx playwright test replay.spec.ts
import { expect, test } from "@playwright/test";
test("Invite a teammate", async ({ context }) => {
const page = await context.newPage();
await test.step("1. Go to Settings on Acme", async () => {
await page.goto("https://app.acme.test/settings");
await expect(page).toHaveURL(/^https:\/\/app\.acme\.test\/settings\/?(?:[?#].*)?$/);
});
await test.step("2. Click Team", async () => {
await page.getByRole("link", { name: "Team" }).click();
});
await test.step("3. Click Invite member", async () => {
await page.getByRole("button", { name: "Invite member" }).click();
});
await test.step('4. Type "jane@example.com" in Email', async () => {
await page.getByLabel("Email").fill("jane@example.com");
});
await test.step("5. Select Editor in Role", async () => {
await page.getByLabel("Role").selectOption({ label: "Editor" });
});
await test.step("6. Click Send invite", async () => {
await page.getByRole("button", { name: "Send invite" }).click();
});
});Run it with npx playwright test replay.spec.ts. The export is a starting point, not a finished test: it replays what you did, and it does not know what “success” looks like. Add an expect after the final step, such as await expect(page.getByText("Invite sent")).toBeVisible().
The agent skill format
The same export includes a SKILL.md and a steps.json. The skill file has frontmatter with a name and description and a numbered list of steps in plain language. steps.json is the machine version, with each step’s action, target and locators. A coding agent can read the skill to understand the task, run the script to check it still works, and patch a locator when the UI changes.
Agents can also work with the recording directly through the command line and local MCP server: list steps, edit a step, validate, export.
When to use which
| You want | Use |
|---|---|
| A test for a flow you already understand, written in code | Playwright codegen or write it by hand |
| A test and a guide for the same flow, from your own signed-in Chrome | Showsteps |
| A script a support or ops person can produce without writing code | Showsteps, then hand replay.spec.ts to an engineer |
| Assertions on many pages | Write the tests; recorders only replay what you did |
