taqwright

Installation

Taqwright puts Playwright's test runner on top of Appium 3 so you write mobile E2E tests the same way you'd write a Playwright web test — but you drive a real phone instead of a browser. This page takes you from nothing installed to a configured project ready to run its first test.

Introduction

Taqwright sits on top of Playwright's test runner and Appium 3. From Playwright you get parallelism, retries, projects, sharding, fixtures, the HTML reporter, and the test / expect primitives. From Appium you get UiAutomator2 (Android) and XCUITest (iOS) underneath, with a flat mobile API and a chainable Locator on top.

You write tests the same way you'd write a Playwright web test — same file shape, same hooks, same runner flags — but you drive a phone instead of a browser. Once setup below is done, head to Writing tests for your first test.

Installing taqwright

Get started by installing taqwright. The command below initializes a new project (or use npm i -D taqwright to add taqwright to an existing one):

npm init taqwright@latest

When prompted, choose / confirm:

You can re-run the command later — it asks before writing into a non-empty directory, so it won't overwrite existing work. npm init taqwright@latest is equivalent to npm create taqwright@latest (and, once taqwright is installed, npx taqwright init).

What's installed

taqwright scaffolds the project below. If you accept the toolchain prompt (or run npx taqwright install), it also vendors the Android toolchain — a JDK, the Android SDK + adb, Appium 3, and the uiautomator2 driver — into a taqwright-managed cache dir (the mobile analogue of Playwright's browser binaries), not into node_modules.

taqwright.config.ts          # test + device/Appium configuration
package.json
package-lock.json            # after npm install
tsconfig.json
.gitignore
tests/
  example.spec.ts            # runnable demo tests (login flows)
app/
  DemoApp-v1.0.0.apk         # bundled demo app (Android, when accepted)

taqwright.config.ts centralizes configuration: platform, device + Appium, resetBetweenTests, reporters (console list + HTML), timeouts, and projects — see Configuration. Adding taqwright to an existing project instead (npm i -D taqwright) only adds the dependency to your current package.json — no scaffold.

tests/ contains runnable example tests against the demo app (a minimal no-op stub if you declined the demo app). The managed toolchain lives under ~/Library/Caches/taqwright (overridable via TAQWRIGHT_HOME), is shared across projects, and is used automatically by test / devices / doctor — delete that dir to fully revert.

Running the example test

taqwright is serial by default (workers: 1) — one Appium session against your configured emulator / simulator / device, not parallel browsers. With the generated config, appium.autoStart spawns Appium and autoStartDevice cold-boots the managed taqwright_api34 AVD, so you just run:

npx taqwright test

Output and aggregated results stream to the terminal (the list reporter) while the device window shows the run live:

Running 3 tests using 1 worker

  ✓  tests/example.spec.ts:9:1 › user can log in to the demo app (4.1s)
  ✓  tests/example.spec.ts:16:1 › login fails with invalid username & password (3.4s)
  ✓  tests/example.spec.ts:23:1 › login is blocked without username & password (2.9s)

  3 passed (12.3s)

To open the HTML report: npx taqwright show-report

Tips:

See Running & debugging tests for tracing, screen recording and reports, and Parallel runs for workers / device pools / sharding.

HTML test reports

After a run, the HTML report is a dashboard filterable by project (android / ios) and status (passed, failed, flaky, skipped). Click a test to inspect its error, steps and attachments — including taqwright's taqwright-trace (a self-contained per-action screenshot + page-source timeline) and taqwright-video (the device screen recording) when trace / video are enabled.

The generated config uses ['html', { open: 'never' }], so it never auto-opens — view it manually:

npx taqwright show-report

This serves playwright-report/ at http://localhost:9323 (override with --host / --port). Want it to pop open automatically when a test fails instead? Set the reporter to ['html', { open: 'on-failure' }] in taqwright.config.ts.

taqwright HTML test report — a dashboard listing the demo tests with pass/fail status, durations, and per-test steps and attachments
The taqwright HTML report (npx taqwright show-report).

Updating taqwright

Update the package, then re-provision the managed Android toolchain — a newer taqwright may pin newer JDK / SDK / Appium / driver versions (the analogue of Playwright re-downloading browser binaries):

npm install -D taqwright@latest
npx taqwright install            # idempotent; add --force to fully re-vendor

taqwright install skips anything already present and pulls only what changed; pass --force to rebuild the whole managed toolchain from scratch. Check your installed version:

npx taqwright --version

System requirements

Quick start

A few commands to get oriented:

npm init taqwright               # scaffold a project (interactive)
npx taqwright install            # auto-install the Android toolchain (or say yes during init)
npx taqwright doctor             # verify your env (adb, xcrun, java, appium)
npx taqwright devices            # list local emulators / simulators + state
npx taqwright codegen            # web inspector + record on connect
npx taqwright test               # run your tests

Fast path — auto-install the Android toolchain

Don't want to install the Android SDK, a JDK, and Appium by hand? One command vendors the entire Android stack — a Temurin JDK, the Android SDK + adb, Appium 3, and the uiautomator2 driver — into a taqwright-managed directory:

npx taqwright install

Run it any time, standalone — or let scaffolding do it: npm init taqwright (and taqwright init) offers this exact step for Android projects right after creating the files (default no; or pass --install-toolchain to skip the prompt). Same command underneath either way.

No sudo, no shell edits. Everything downloads under a managed cache dir (override with TAQWRIGHT_HOME) — nothing is installed system-wide and your shell rc is never touched. taqwright automatically uses this toolchain when you run test, devices, codegen, or doctor — no export ANDROID_HOME=… required.

It runs four idempotent steps (re-running skips anything already present), then self-verifies with doctor:

1/4  JDK (Temurin 21)                                  ✓
2/4  Android SDK (cmdline-tools + platform-tools/adb)  ✓
3/4  Appium 3 + uiautomator2 driver                    ✓
4/4  AVD — skipped (pass --with-avd to also create an emulator)

Verifying with doctor:
  [ok] adb (Android SDK)                — on PATH
  [ok] ANDROID_HOME (Appium adb lookup) — ANDROID_HOME=~/Library/Caches/taqwright/android-sdk
  [ok] java (JDK for UiAutomator2)      — on PATH
  [ok] JAVA_HOME (UiAutomator2 JDK)     — JAVA_HOME=~/Library/Caches/taqwright/jdk/…/Contents/Home
  [ok] Appium (test server)             — on PATH (v3.x.x)
  [ok] Appium drivers                   — uiautomator2
FlagEffect
--forceReinstall even if already provisioned (otherwise every step is skipped when present).
--with-avdAlso download a system image and create an emulator (taqwright_api34, ~1 GB).
--print-envAlso print export lines, if you want the managed toolchain on your own shell too.
Android only. install can't auto-install two things: Node.js 24+ (it's the runtime taqwright itself runs on — install it first, step 1 below) and the iOS / Xcode stack (Apple-gated: App Store, license, ~10 GB). For iOS — or if you'd rather install the Android pieces by hand — use the step-by-step below.

Installing taqwright (manual)

Prefer manual control, or testing iOS? Install the stack yourself. The fast path above already does steps 2–7 automatically for Android, so reach for this when you want manual control, an existing system toolchain, or iOS.

The setup is a stack: Node → Appium → driver → device. Each step has a verification command — run it and confirm the output before moving on. At the end, npx taqwright doctor runs every check at once.

At a minimum you need: Node.js 24+, Appium 3.x, and the driver + toolchain for the platform you're testing (Android, iOS, or both).

1. Node.js 24+

Taqwright and Appium 3 both require Node.js 24 or newer. Use nvm (macOS / Linux) or fnm (cross-platform) — they let you switch Node versions per project, and a .nvmrc in the project root picks up automatically.

macOS / Linux — nvm
# Install nvm itself (one-time)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
# Re-open your shell, then:
nvm install 24
nvm use 24
macOS — Homebrew
brew install node@24
brew link --overwrite node@24
Windows / cross-platform — fnm
winget install Schniz.fnm        # or: choco install fnm
fnm install 24
fnm use 24

Verify:

node -v
# v24.x.x  ← anything 24.0.0 or newer

2. Appium 3.x (recommended)

Appium is the WebDriver server that talks to the device. The supported path is Appium 3.x:

npm install -g appium@^3
Already on Appium 2.x? Taqwright will run on it — every mobile: command shape is identical between 2.x and 3.x — but taqwright doctor will print a best-effort warning and the 2.x path isn't in CI. Upgrade with npm i -g appium@^3 when you're ready for the officially supported path.

Verify:

appium --version
# 3.x.x  ← must start with 3

You can leave Appium not-yet-running. Taqwright will spawn it for you when use.appium.autoStart: true (see Configuration). Or run it yourself in a separate terminal:

appium
# Welcome to Appium v3.x.x
# Appium REST http interface listener started on http://0.0.0.0:4723

3. Appium drivers

Appium's driver model is one driver per platform. Install the one(s) you need:

Android — UiAutomator2
appium driver install uiautomator2
iOS — XCUITest
appium driver install xcuitest

Verify:

appium driver list --installed
# - uiautomator2@3.x.x [installed (npm)]
# - xcuitest@8.x.x     [installed (npm)]

4. Android toolchain (Android testing only)

UiAutomator2 needs the Android SDK Platform Tools (for adb) and a JDK.

Android SDK Platform Tools (adb)

Easiest: install Android Studio — its first-run setup installs the SDK + Platform Tools and creates an emulator. If you don't want the full IDE, install just the Command Line Tools and use sdkmanager.

macOS — Homebrew
brew install --cask android-platform-tools     # adb + fastboot only
# or, full SDK with emulator:
brew install --cask android-commandlinetools

Set ANDROID_HOME and add tools to PATH in your shell rc (~/.zshrc / ~/.bashrc):

export ANDROID_HOME="$HOME/Library/Android/sdk"   # macOS Android Studio default
export PATH="$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator:$ANDROID_HOME/cmdline-tools/latest/bin:$PATH"

Verify:

adb --version
# Android Debug Bridge version 1.0.x

emulator -list-avds
# Pixel_7_API_34   ← your created emulators

JDK (for UiAutomator2)

Any LTS Java (11, 17, or 21) works. On macOS:

brew install --cask temurin@21
# Tell shells where to find it:
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
export PATH="$JAVA_HOME/bin:$PATH"

On Linux: sudo apt install openjdk-21-jdk (Debian/Ubuntu) or sudo dnf install java-21-openjdk (Fedora).

Verify:

java -version
# openjdk version "21.x.x"

echo $JAVA_HOME
# /Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home

5. iOS toolchain (iOS testing only — macOS required)

XCUITest needs Xcode and its Command Line Tools.

# 1. Install Xcode from the App Store (~10 GB download).
# 2. Then accept the license + install CLT:
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -license accept
xcode-select --install

For real-device testing (not just the simulator), also install libimobiledevice for some Appium device probes:

brew install libimobiledevice ios-deploy

If you'll use screen recording (video in a project's use block) on the iOS simulator, also install ffmpeg — XCUITest pipes simulator frames through it, and without it every iOS test fails at fixture setup ('ffmpeg' binary is not found in PATH):

brew install ffmpeg
ffmpeg -version   # verify it's on PATH

Verify:

xcrun --version
# xcrun version 70.x.x

xcodebuild -version
# Xcode 16.x

xcrun simctl list devices available | head -20
# == Devices ==
# -- iOS 18.0 --
#     iPhone 16 (xxxx) (Shutdown)
#     iPhone 16 Pro (xxxx) (Shutdown)
#     ...

6. A device

You need at least one of: an emulator (Android), a simulator (iOS), or a real device on USB.

Android emulator

Easiest path: create one in Android Studio's Device Manager → Create device. Or via CLI:

sdkmanager "system-images;android-34;google_apis;arm64-v8a"
avdmanager create avd -n Pixel_7_API_34 -k "system-images;android-34;google_apis;arm64-v8a" -d pixel_7
emulator -avd Pixel_7_API_34 -no-snapshot &

Verify:

adb devices
# List of devices attached
# emulator-5554   device   ← booted and ready

iOS simulator

List, then boot:

xcrun simctl list devices available
xcrun simctl boot "iPhone 16"            # or whatever name appears in the list above
open -a Simulator

Verify:

xcrun simctl list devices booted
# iPhone 16 (xxxx) (Booted)
WebDriverAgent won't start — connect ECONNREFUSED 127.0.0.1:8100? iOS sessions go through WebDriverAgent (WDA), which Appium builds with xcodebuild and reaches on port 8100. If it can't, you'll see Unable to start WebDriverAgent session … connect ECONNREFUSED 127.0.0.1:8100. Two causes, in order of likelihood:
  • The iOS simulator platform for your Xcode isn't installed. e.g. Xcode 26.5 but only an iOS 26.4 runtime present — xcodebuild then can't resolve a build destination ("iOS 26.5 is not installed. … Xcode > Settings > Components"), so WDA never builds and nothing listens on :8100. This is an Xcode environment gap, not a taqwright/config issue. Install the matching platform, then make a sim on it:
    xcodebuild -downloadPlatform iOS          # or: Xcode → Settings → Components
    xcrun simctl create 'iPhone 17 Pro' 'iPhone 17 Pro' \
      com.apple.CoreSimulator.SimRuntime.iOS-26-5
    xcrun simctl list devices available       # copy the new UDID into device.udid / pool
  • The first WDA build is just slow and times out (Appium's default is ~60 s; a cold WDA build is longer). Set iosParallelCaps() on the project (it bumps WDA launch/connection timeouts, enables useNewWDA, and retries), or pre-build WDA once so it's cached:
    WDA=~/.appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent
    xcodebuild build-for-testing -project "$WDA/WebDriverAgent.xcodeproj" \
      -scheme WebDriverAgentRunner -destination 'id=<sim-udid>'
Note: iosParallelCaps()'s WDA tuning applies to taqwright test (the runner). The taqwright codegen connect builds capabilities from its own form, so it uses Appium's default WDA timeout — once the platform is installed and WDA is prebuilt/cached, the inspector connects fine. Add appium:showXcodeLog: true to surface the real xcodebuild error if it still fails.

Real device (Android)

  1. On the phone: Settings → About phone, tap "Build number" seven times to unlock Developer Options.
  2. Settings → Developer options → USB debugging → On.
  3. Plug into USB. On first connect, accept the "Allow USB debugging" prompt.
  4. Run adb devices — your device shows with state device (not unauthorized).

Real device (iOS)

  1. Plug into the Mac. Xcode shows the device in Window → Devices and Simulators.
  2. On the phone: trust the computer when prompted.
  3. Provisioning: you'll need an Apple Developer account + a signed build of your app on the device.
  4. Verify: xcrun xctrace list devices shows the device by name + UDID.

7. Install taqwright

Two options:

Scaffold a new project (recommended)
npm init taqwright my-mobile-tests
cd my-mobile-tests
npm install

npm init taqwright (equivalently npm create taqwright@latest) is the standard bootstrap — it runs the create-taqwright initializer, which delegates to taqwright init. If taqwright is already installed/linked, the equivalent is npx taqwright init my-mobile-tests. Either way it walks you through picking a platform, points at your APK / IPA, and writes a ready-to-run package.json, tsconfig.json, taqwright.config.ts, and a sample spec. For an Android project it then offers to download the demo app (a small reference APK, default yes) — wiring buildPath/appBundleId + a real login spec so npx taqwright test works out of the box — and to auto-install the toolchain (the fast path above, default no). Both are skippable via --demo-app/--no-demo-app and --install-toolchain/--no-install-toolchain. All flags forward, e.g. npm init taqwright my-app -- --platform ios -y.

Example run — npm init taqwright taq-demo, choosing android and accepting the prompts:

taqwright init — scaffold a new project

? Test folder name (tests):
? Platform [android/ios/both]: android
? Run npm install now? (Y/n): Y
? Auto-install the Android toolchain now? (~700 MB: JDK + Android SDK + Appium) (y/N): y
? Download the demo app so the example test runs out of the box? (~few MB) (Y/n): Y

Downloading the demo app (DemoApp-v1.0.0.apk)… done.

Created:
  taq-demo/package.json
  taq-demo/tsconfig.json
  taq-demo/taqwright.config.ts
  taq-demo/tests/example.spec.ts
  taq-demo/.gitignore
  taq-demo/app/DemoApp-v1.0.0.apk

Running npm install …
added 179 packages, audited 179 packages — found 0 vulnerabilities

Installing the Android toolchain — this can take a few minutes…

taqwright install — vendoring the Android toolchain into:
  ~/Library/Caches/taqwright
…  (the 4 install steps + doctor verification — identical to the Fast path output above)  …

Next steps:
  cd taq-demo
  npx taqwright doctor          # check your environment
  npx taqwright devices         # list connected devices
  npx taqwright test            # runs the demo login test (Appium auto-starts)

With the demo app accepted, the generated taqwright.config.ts has resetBetweenTests: true + buildPath: './app/DemoApp-v1.0.0.apk' + appBundleId: 'com.taqelah.demo_app' active, and tests/example.spec.ts is a real login test — so npx taqwright test passes once an emulator is up. Decline it and those config lines stay commented and the example is a no-op stub instead.

That toolchain block is the prompt in action. This Android-capable project answered yes to "Auto-install the Android toolchain", so init chained taqwright install automatically — the project is runnable immediately, no separate step. Answer no (the default) and that same command instead appears under Next steps as npx taqwright install.
Add to an existing project
npm install --save-dev taqwright

8. Final verification

Run the built-in doctor — it re-checks everything above in one go:

npx taqwright doctor

Expected output:

taqwright doctor (v0.0.1)
  [ok] Node.js >= 24  — v24.15.0
  [ok] adb (Android SDK)  — on PATH
  [ok] ANDROID_HOME (Appium adb lookup)  — ANDROID_HOME=~/Library/Android/sdk
  [ok] xcrun (Xcode CLT)  — on PATH
  [ok] Xcode (full, for XCUITest)  — Xcode 16.2 (/Applications/Xcode.app/Contents/Developer)
  [ok] ffmpeg (iOS-sim video)  — on PATH
  [ok] iOS simulator (WDA target)  — 8 available (latest iOS 18.2)
  [ok] java (JDK for UiAutomator2)  — on PATH
  [ok] JAVA_HOME (UiAutomator2 JDK)  — JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home
  [ok] Appium (test server)  — on PATH (v3.x.x)
  [ok] Appium drivers  — uiautomator2, xcuitest
What you'll actually see varies by platform — that's expected. The xcrun / Xcode / ffmpeg / iOS simulator lines are macOS-only (skipped entirely on Linux/Windows). A [warn] is a soft heads-up, never a hard failure — e.g. ffmpeg and iOS simulator only matter if you record iOS-simulator video, and a single missing Appium driver is fine if you don't test that platform. Only [error] (e.g. Node < 24) blocks you.

List what taqwright can see:

npx taqwright devices

Example output:

Android (adb + emulator):
  Pixel 7 API 34  emulator-5554  (booted, Android 14)
  Pixel 6 API 33  avd:Pixel_6_API_33  (shutdown)

iOS Simulators (xcrun simctl):
  iPhone 16  1A2B3C4D-5E6F-7A8B-9C0D-1E2F3A4B5C6D  (booted, iOS 18.2)
  iPhone 16 Pro  9F8E7D6C-5B4A-3210-FEDC-BA9876543210  (shutdown, iOS 18.2)

Every created emulator / simulator is listed with its state(booted, …) if it's running, (shutdown) if it exists but isn't started. A shutdown Android AVD shows an avd:<name> id (use it to boot the emulator); a running one shows its live emulator-5554 serial. Connected physical devices appear here too. If doctor all passes and devices lists something, you're ready to write your first test — boot a shutdown device first (e.g. emulator -avd Pixel_7_API_34 or xcrun simctl boot "iPhone 16").

Stuck? Most setup failures fall into three buckets:
  1. ANDROID_HOME not set — the shell can find adb but appium can't find the rest of the SDK. Add the exports from step 4 to your shell rc.
  2. Wrong Node versionnode -v shows v22 or older. Re-run nvm use 24 (or check your fnm setup) — restart the shell if needed.
  3. Appium 2 leftoverappium --version prints 2.x. Uninstall the old one (npm uninstall -g appium) then re-run step 2.

What's next