TesterArmyTesterArmy
  • Pricing
Sign inGet started
HomeMigratePuppeteer

Migrate from Puppeteer to TesterArmyYour Puppeteer scripts,
without the selector upkeep

TesterArmy replaces scripted automation with an AI agent that executes natural-language steps using vision. Paste one prompt into Claude Code, Cursor, or Codex and the agent reads your Puppeteer code, converts it, and verifies every test.

GET STARTED FOR FREE

Takes less than 2 minutes. No credit card required.

Resendbolt.newNando'sNovuCodeCraftersRorkGreen-GotShockoeLightsprintCopyfyStandoutAugust
[01] The selector afternoon

Scripts that work
until the DOM changes

Puppeteer scripts are imperative browser automation: page.waitForSelector, page.$eval, manual retries, and assertions bolted on through Jest or plain Node scripts. They work until the DOM changes.

01

Every DOM change costs an afternoon

Your scripts drive the page through CSS and XPath selectors, so any markup change can turn them red. The scripts work until the DOM changes, and then someone spends an afternoon updating selectors.

02

waitForSelector and retries hold the suite together

Every page.click() needs a waitForSelector or waitForNavigation in front of it, and flaky runs get patched with sleeps and manual retry loops. The waiting logic ends up being as much code as the test itself.

03

Assertions are bolted on

Puppeteer is an automation library, not a test framework, so checks arrive through Jest expect() calls on page.$eval and page.content(). Reading what a test actually verifies means untangling DOM plumbing first.

04

Debugging means headless: false and screenshots

When a script fails you relaunch it with puppeteer.launch({ headless: false }) and scatter page.screenshot() calls to see what happened. You reconstruct the failure one still frame at a time instead of watching it.

[02] The same test, twice

What your suite reads like
after the conversion

The intent behind each page.* call becomes an act step and each assertion becomes an assert step, while the selectors and waits are dropped. This is the same checkout flow in both languages.

Puppeteer · checkout.e2e.js
it("checkout with saved card", async () => {
  await page.goto(`${BASE_URL}/products/desk-lamp`);
  await page.waitForSelector('[data-testid="add-to-cart"]');
  await page.click('[data-testid="add-to-cart"]');
  await page.waitForSelector('[data-testid="cart-count"]');
  await page.click('[data-testid="cart-link"]');
  await page.waitForNavigation({ waitUntil: "networkidle0" });
  await page.click("#checkout-button");
  await page.waitForSelector("#payment-form", { timeout: 15000 });
  await page.click('input[name="saved-card"]');
  await page.click('[data-testid="place-order"]');
  await page.waitForSelector('[data-testid="order-confirmation"]');
  const total = await page.$eval('[data-testid="order-total"]',
    (el) => el.textContent);
  expect(total).toBe("$49.00");
});
TesterArmy · the same test
Checkout with a saved cardPassedWeb1m 52s
Navigate to the desk lamp product pageAct
Add the desk lamp to the cartAct
Open the cart and start checkoutAct
Pay with the saved cardAct
The order confirmation appearsAssert
The order total shows $49.00Assert

The CSS selectors, waitForSelector calls, and the page.$eval plumbing are dropped in conversion. The agent finds elements visually and waits on its own, so the next DOM change does not cost anyone an afternoon.

[03] One-prompt migration

The whole migration
is one prompt

Paste this into your coding agent in the repository that contains your Puppeteer tests. It finds every file importing puppeteer, skips the scrapers and PDF generators, converts each test into plain-English steps, and verifies every one locally with real exit codes.

Migration prompt · Puppeteer → TesterArmy
Migrate this repository's Puppeteer tests to TesterArmy using the
TesterArmy CLI (`ta`). Verify auth first with `ta status --json`, and use
`ta --help` plus subcommand help to discover commands. Prefer --json output.

1. Discover: find all files importing puppeteer or puppeteer-core
   (Jest-Puppeteer suites, *.e2e.js scripts, jest-puppeteer.config.js).
   Identify the base URL from config, env vars, or page.goto() calls.
   Only migrate files that TEST user flows - skip scrapers, PDF/screenshot
   generators, and crawling utilities.

2. Create a TesterArmy project (skip if one exists in `ta projects list`):
   echo '{"name":"<repo name>","url":"<base URL>","projectType":"web"}' | ta projects create --json

3. Save durable context as project memories (category site_structure,
   importance high): key routes, the login URL, setup steps from
   beforeAll/globalSetup that describe the app.
   echo '{"category":"site_structure","title":"...","content":"...","importance":"high"}' | ta memories create --project <projectId> --json

4. Convert each test/script into a TesterArmy test:
   - Express the USER INTENT of each action in plain English. Drop all
     selectors, waitForSelector/waitForNavigation calls, sleeps, and retry
     loops - the TesterArmy agent finds elements visually and waits on its
     own.
   - page.goto/click/type/select -> steps with type "act"
   - expect() assertions on page content -> steps with type "assert"
   - manual login sequences or cookie injection -> one step with type "login"
   - page.screenshot() evidence points -> steps with type "screenshot"
   - Keep tests focused: 3-10 steps. Split long scripts that cover
     multiple flows into separate tests.
   Create each test:
   echo '{"title":"<test name>","description":"Migrated from <file>","steps":[{"title":"Navigate to /login","type":"act"},{"title":"Dashboard loads","type":"assert"}]}' | ta tests create --project <projectId> --json
   Step types: act, assert, login, screenshot.

5. Never hardcode passwords in test steps. If scripts read credentials from
   env vars or inject cookies, tell me which credentials to add and I will run:
   echo '{"kind":"login","label":"...","username":"...","password":"..."}' | ta projects credentials-create <projectId> --json

6. Verify: run each migrated test locally with
   `ta tests run <testId> --local --url <base URL> --json` and report results.
   Exit code 0 = pass, 1 = fail.

7. Report a summary table: source file -> TesterArmy test ID -> run result,
   plus a list of anything you intentionally skipped and why.
Read the full guide →
Works with:
[04] Concept map

Everything you built
has a place to land

Every Puppeteer concept maps to a TesterArmy equivalent - and the two things that break most often, selectors and waits, map to nothing at all.

Puppeteer→TesterArmy
Puppeteer
TesterArmy
A script or it() block driving page
→A test with natural-language steps
page.goto(), page.click(), page.type()
→act steps ("Go to /checkout", "Type the coupon code")
Jest expect() on page.$eval / page.content()
→assert steps ("The total shows the discount")
Manual login sequences / cookie injection
→login step + encrypted project credentials
page.waitForSelector(), waitForNavigation()
→Not needed - the agent waits like a human
CSS/XPath selectors
→Not needed - the agent finds elements visually
page.screenshot() for evidence
→screenshot step (every run also records video)
puppeteer.launch({ headless: false }) debugging
→ta tests run <testId> --local --headed
[05] Side by side

Puppeteer and TesterArmy,
row by row

Puppeteer is free, built by the Chrome team, and for scraping, PDF generation, and precise Chrome automation it stays the right tool. This table is about what owning a test suite on top of it costs, and where each side wins.

DimensionTesterArmyPuppeteer
  • Who maintains the testsTesterArmyThe agent finds elements visually and waits on its own, so nobody owns a selector layer.AdvantagePuppeteerYour team owns the scripts, CSS selectors, waitForSelector calls, and retry loops - maintenance scales with DOM change.
  • What breaks on a UI changeTesterArmyUsually nothing - a renamed data-testid or a restructured page is invisible to a vision agent.AdvantagePuppeteerEvery script whose selector touched the changed markup, and updating them is the selector afternoon.
  • Writing a new testTesterArmy3-10 plain-English steps that anyone on the team can write and review.PuppeteerAn imperative page.* script with selectors and waits, plus Jest or similar bolted on for the assertions.
  • Flaky failuresTesterArmyThe agent waits like a human, and every failure comes with a recording and a step trace.PuppeteerHandled with waitForSelector, waitForNavigation, sleeps, and retry loops that accumulate inside the scripts.
  • Run verdictsTesterArmyThree verdicts - passed, failed, or blocked. Environment and setup stops land in blocked with the reason attached, so the failure count only holds real product failures.AdvantagePuppeteerTwo verdicts. A crashed Chrome instance and a product bug both arrive as the same Jest failure until you read the trace.
  • License and infrastructureTesterArmyA paid service - the agent, browsers, and infrastructure are included.PuppeteerFree and open source from the Chrome team; you run the browsers, CI workers, and waiting logic yourself.Advantage
  • Scraping and Chrome automationTesterArmyOut of scope - TesterArmy tests user flows rather than automating browsers, so scrapers and generators stay in Puppeteer.PuppeteerPuppeteer's home turf: scraping, PDF generation, crawling, and precise CDP control are what it is built for.Advantage
  • Pull request workflowTesterArmyPR testing is built in - runs trigger from GitHub and report back on the pull request.PuppeteerYou wire your Puppeteer job into CI yourself and maintain the workflow and its retries.
  • Native mobile appsTesterArmyThe same plain-English tests run on iOS and Android via managed cloud simulators.AdvantagePuppeteerChrome and web focused - native apps need a separate stack like Appium, Maestro, or Detox.
  • Entry priceTesterArmyFree trial without a credit card; Hobby is $99 per month with 250 test runs included.Puppeteer$0 forever - Puppeteer has no paid tier, and the cost is the engineering time in the rows above.

Facts checked August 2026. Spotted something out of date? Tell us and we will fix it.

GET STARTED FOR FREE

Takes less than 2 minutes. No credit card required.

[06] The migration path

From imperative scripts to green runs in four steps

Install the CLI, hand the prompt to your coding agent, and review what comes back. Your Puppeteer scripts keep running until every migrated test is green.

1

Point the agent at your repo

Install the TesterArmy CLI and authenticate, then paste the migration prompt into Claude Code, Cursor, or Codex. The agent finds every file importing puppeteer or puppeteer-core, identifies the base URL, and creates a matching web project.

2

The agent converts every test

Each script becomes a test of 3-10 plain-English steps: page.* calls turn into act steps, expect() assertions into assert steps, cookie injection into a single login step, and page.screenshot() evidence points into screenshot steps.

3

Every migrated test runs locally

The agent verifies each test against your app with ta tests run --local and reports pass or fail through real exit codes, plus a summary of the scrapers and generators it intentionally skipped and why.

4

Wire the suite into CI

Replace your Puppeteer CI job with ta tests run --group or a group webhook. Keep Puppeteer for scraping or PDF work, and delete the test scripts once the TesterArmy runs are green.

[07] The honest inventory

What comes with you,
what stays behind

End-to-end user flows translate cleanly, and the guide is explicit about what to leave behind. Puppeteer stays in your repo for the jobs it is the right tool for.

Comes with you
Stays behind
Comes with you+Puppeteer itself, for scraping and PDF generation scripts
Stays behind−CSS and XPath selectors - the agent finds elements visually
Comes with you+Your CI pipeline - only the run step changes, to ta tests run --group or a group webhook
Stays behind−waitForSelector, waitForNavigation, sleeps, and retry loops - the agent waits like a human
Comes with you+The user intent behind every page.* call, expressed as plain-English steps
Stays behind−Request interception with page.setRequestInterception - tests run against a real environment instead
Comes with you+Your staging and preview environments as the test targets
Stays behind−Manual login sequences and cookie injection - credentials move to the encrypted project store
Comes with you+The old test scripts, until every TesterArmy run is green
Stays behind−Low-level browser tweaks like custom user agents and CDP sessions - needs like viewport size are configured per project

When Puppeteer is still the right call

  • →Most of your Puppeteer code is scrapers, PDF generators, or crawling utilities rather than user-flow tests - that is Puppeteer's home turf, and the migration prompt itself says to skip those files.
  • →Your tests depend on request interception with page.setRequestInterception or on low-level CDP control - TesterArmy runs against a real environment instead of an instrumented browser.
  • →Your flows must run air-gapped or fully offline - TesterArmy tests run against a real, reachable environment.
  • →You have engineers who genuinely enjoy owning the scripts and your DOM rarely churns.

Nothing forces the choice on day one. Migrated tests run alongside your Puppeteer scripts, Puppeteer keeps the scraping and PDF work permanently, and the guide's own advice is to delete the test scripts only once the TesterArmy runs are green.

[08] FAQ

Frequently Asked Questions

The two work at different layers. Puppeteer is an automation library - you write and maintain the browser scripts in code. TesterArmy is a service: you describe flows in plain English and an AI agent with vision executes them against your app, finds elements visually, and waits like a human.
For the end-to-end layer, yes: TesterArmy replaces the tests that cover user flows, while Puppeteer stays in your repo for scraping and PDF generation scripts. Migrated tests run alongside the old ones, and the guide's advice is to delete the Puppeteer test scripts only once the TesterArmy runs are green.
No. Keep Puppeteer for scraping and PDF work - it is the right tool for those, while TesterArmy is for testing user flows. The guide's own advice is to delete the test scripts only once the TesterArmy runs are green.
The conversion drops them instead of translating them. The agent finds elements visually, so CSS and XPath selectors are not needed, and it waits like a human, so waitForSelector, waitForNavigation, sleeps, and retry loops are not needed either.
You paste one prompt into your coding agent - Claude Code, Cursor, or Codex - inside the repo that holds your Puppeteer tests. The agent drives the TesterArmy CLI: it finds every file importing puppeteer, creates a project, converts each test, verifies every one locally with real exit codes, and reports what it skipped.
Scrapers, PDF and screenshot generators, and crawling utilities stay in Puppeteer, where they belong. Request interception with page.setRequestInterception does not carry over either - TesterArmy runs against a real environment such as staging or a preview deployment - and low-level browser tweaks like custom user agents and CDP sessions become project-level configuration instead.
The same place your Puppeteer CI job runs today. Replace that job with ta tests run --group or a group webhook, and the suite runs against your staging or preview environment.
Into TesterArmy's encrypted credential store, added with ta projects credentials-create. The migration prompt explicitly forbids hardcoding passwords in test steps - if your scripts read credentials from env vars or inject cookies, the agent flags which credentials you need to add instead.
Migrating from something else?
PlaywrightMigrate →CypressMigrate →SeleniumMigrate →AppiumMigrate →MaestroMigrate →MablMigrate →Bug0Migrate →All playbooksView →

The next DOM change
should not cost an afternoon

Your Puppeteer scripts encode real knowledge about how your product is supposed to work. The migration keeps that knowledge and retires the machinery around it - the selectors, the waitForSelector calls, the retry loops - so the tests describe intent instead of DOM structure.

[09] Start the migration

Run your first
migrated test today

Contact usGet started for free
XLinkedInDiscord
TesterArmyTesterArmy

AI-powered QA testing for modern teams. Ship faster with confidence.

SOC 2 Type 2 badge
GDPR badge

© 2026 TesterArmy, Inc.

Solutions
  • AI app testingAI app testing
  • EcommerceEcommerce
  • Expo app testingExpo app testing
  • MobileMobile
  • Production monitoringProduction monitoring
  • React Native testingReact Native testing
  • WebWeb
  • WordPress testingWordPress testing
Quick links
  • HomeHome
  • DemoDemo
  • FeaturesFeatures
  • How it worksHow it works
  • FAQFAQ
  • PricingPricing
  • Get a demoGet a demo
  • About usAbout us
  • Contact usContact us
Resources
  • DocumentationDocumentation
  • Migrate to TesterArmyMigrate to TesterArmy
  • BlogBlog
  • API referenceAPI reference
  • Getting startedGetting started
Legal
  • Privacy policyPrivacy policy
  • Terms of serviceTerms of service
TesterArmyTesterArmy
  • Pricing
Sign inGet started
Quick links
  • HomeHome
  • DemoDemo
  • FeaturesFeatures
  • How it worksHow it works
  • FAQFAQ
  • PricingPricing
  • Get a demoGet a demo
  • About usAbout us
  • Contact usContact us