Skip to main content

Configuration

Project config lives in taqwright.config.ts. This is what taqwright init generates for an Android project with the demo app, every knob listed, essentials uncommented, the rest commented placeholders you enable by deleting the leading // . The bundled demo app and its managed taqwright_api34 AVD are already wired, so npx taqwright test works out of the box.

taqwright.config.ts

taqwright.config.ts
import { defineConfig, Platform } from 'taqwright';

// Every config knob is listed here. Essentials are uncommented; everything
// else is a commented placeholder you can enable by removing the leading "// ".
export default defineConfig({
testDir: './tests',
timeout: 60_000,
expectTimeout: 30_000,
// 'html' writes playwright-report/, view it with: npx taqwright show-report
reporter: [['list'], ['html', { open: 'never' }]],

// ─── Optional top-level overrides ─────────────────────────────────
// retries: 1,
// outputDir: './test-results',
// fullyParallel: false,
// forbidOnly: !!process.env.CI,
// testMatch: ['**/*.spec.ts'],
// globalSetup: './setup.ts',
// globalTeardown: './teardown.ts',

projects: [
{
name: 'android',
use: {
platform: Platform.ANDROID,
device: {
provider: 'emulator',
name: 'taqwright_api34', // AVD from `taqwright install --with-avd`
// osVersion: '14',
// udid: 'emulator-5554',
// orientation: 'portrait',
//
// ─── Parallel runs (optional) ────────────────────────────
// Declare a pool of devices to fan tests out across, then bump
// `workers` at the top of this config to match. Worker N picks
// pool[N]; `workers > pool.length` fails fast. Each worker gets
// its own Appium + driver ports auto-staggered.
// pool: [
// { udid: 'emulator-5554', name: 'Pixel_7_API_34' },
// { udid: 'emulator-5556', name: 'Pixel_7_API_34_2' },
// ],
},
// Spawn `npx appium` automatically when nothing is listening on
// the configured host:port. Set `autoStart: false` to manage
// Appium yourself (e.g. when Appium runs in Docker).
appium: {
autoStart: true,
// Boot an offline Android emulator automatically. Needs a string
// device.name equal to the AVD id; a RegExp is rejected at config
// load. iOS simulators boot via XCUITest regardless.
autoStartDevice: true, // cold-boots the taqwright_api34 AVD
host: 'localhost',
port: 4723, // Appium 3 default
path: '/', // Appium 3 default (Appium 1.x used '/wd/hub')
// newCommandTimeout: 240,
// logLevel: 'warn',
},

// ─── Reset between tests ────────────────────────────────────
// resetBetweenTests reinstalls + relaunches the app fresh before
// every test. All three are type-required together.
resetBetweenTests: true,
buildPath: './app/DemoApp-v1.0.0.apk',
appBundleId: 'com.taqelah.demo_app',

// ─── Extra capabilities (escape hatch) ──────────────────────
// capabilities: {
// 'appium:autoGrantPermissions': true,
// 'appium:autoAcceptAlerts': true,
// },

// ─── Per-project locator-action timeout (ms) ────────────────
// expectTimeout: 30_000,

// ─── Trace artifact ─────────────────────────────────────────
// 'off' | 'on' | 'on-failure' | 'retain-on-failure'
// trace: 'on-failure',

// ─── Screen recording (video) ───────────────────────────────
// 'off' | 'on' | 'on-failure' | 'retain-on-failure'
// video: 'on-failure',
},

// ─── Per-project test-runner overrides ────────────────────────
// timeout: 90_000,
// retries: 2,
// grep: /smoke/,
// dependencies: ['setup'],
},

// ─── Cloud examples (BrowserStack / LambdaTest) ─────────────────
// {
// name: 'browserstack',
// use: {
// platform: Platform.ANDROID,
// device: {
// provider: 'browserstack',
// name: 'Google Pixel 8',
// osVersion: '14.0',
// },
// resetBetweenTests: true,
// buildPath: 'bs://<app-id>',
// appBundleId: 'com.example.app',
// },
// },
],
});

What this config does:

  • reporter: console list plus an HTML report under playwright-report/; open it with npx taqwright show-report.
  • android project: appium.autoStart spawns Appium and autoStartDevice cold-boots the managed taqwright_api34 AVD, no manual emulator launch.
  • resetBetweenTests + buildPath + appBundleId: bound to the bundled demo app; reinstalled + relaunched fresh before every test.
  • Everything else: parallel pool, trace, video, extra capabilities, and the BrowserStack / LambdaTest cloud projects, is a commented placeholder you enable as needed.

To run your own app instead of the demo, swap buildPath and appBundleId (the Android package id from your AndroidManifest.xml), and point device.name at one of your own AVDs (emulator -list-avds).

Example projects (the Taqelah demo app)

These four projects run the same demo app locally and on the cloud, across both platforms. Add as many as you need to projects[], then run one with --project <name>.

:::note Two things to watch The demo app's Android package is com.taqelah.demo_app, but its iOS bundle id is camelCase com.taqelah.demoApp. iOS simulators use provider: 'emulator' too, and XCUITest auto-boots the named simulator. :::

Android, local emulator

{
name: 'android',
use: {
platform: Platform.ANDROID,
device: { provider: 'emulator', name: 'emulator-5554' },
appium: { autoStart: true, autoStartDevice: false, host: 'localhost', port: 4723, path: '/' },
buildPath: './app/DemoApp-v1.0.0.apk',
appBundleId: 'com.taqelah.demo_app',
resetBetweenTests: true,
},
}
npx taqwright test --project android

iOS, local simulator

{
name: 'ios',
use: {
platform: Platform.IOS,
device: {
provider: 'emulator', // simulators use 'emulator' too
name: 'iPhone 17 Pro',
udid: '5BE03619-BC3C-42E5-8B1E-747C1F9EA698', // optional: pin a specific simulator
},
appium: { autoStart: true, host: 'localhost', port: 4723, path: '/' },
buildPath: './app/DemoApp-v1.0.0.app',
appBundleId: 'com.taqelah.demoApp', // camelCase, differs from Android
resetBetweenTests: true,
},
}
npx taqwright test --project ios

BrowserStack, Android

Cloud runs read credentials from the environment, never from config:

export BROWSERSTACK_USERNAME=...
export BROWSERSTACK_ACCESS_KEY=...
npx taqwright test --project browserstack-android
{
name: 'browserstack-android',
use: {
platform: Platform.ANDROID,
device: { provider: 'browserstack', name: 'Google Pixel 8', osVersion: '14.0' },
// A pre-uploaded BrowserStack app id (bs://...) is used directly, with no per-run
// upload. A local .apk path works too (uploaded once per worker).
buildPath: 'bs://<app-id>',
appBundleId: 'com.taqelah.demo_app',
parallel_sessions: 5, // number of parallel cloud sessions to create
resetBetweenTests: true,
trace: 'on',
video: 'on-failure',
capabilities: {
// BrowserStack runs Appium 2.x for Android; pin a version if you need to.
'bstack:options': { appiumVersion: '2.19.0' },
},
},
}

BrowserStack, iOS

export BROWSERSTACK_USERNAME=...
export BROWSERSTACK_ACCESS_KEY=...
npx taqwright test --project browserstack-ios
{
name: 'browserstack-ios',
use: {
platform: Platform.IOS,
device: { provider: 'browserstack', name: 'iPhone 15', osVersion: '17' },
// A pre-uploaded BrowserStack iOS app id (bs://...), or a local .ipa path.
buildPath: 'bs://<app-id>',
appBundleId: 'com.taqelah.demoApp',
parallel_sessions: 5, // number of parallel cloud sessions to create
resetBetweenTests: true,
},
}

iosParallelCaps(slot, opts?)

iOS-specific helper that returns a capabilities block tuned for parallel runs. Two parallel iOS simulators would otherwise collide on the default WDA port (8100), the MJPEG screenshot port (9100), and the Xcode DerivedData directory. iosParallelCaps(N) generates per-slot offsets so each session is isolated:

SlotwdaLocalPortmjpegServerPortderivedDataPath
081009100/tmp/wda-0
181019101/tmp/wda-1
N8100 + N9100 + N/tmp/wda-N

:::note One slot per separate iOS project, not per device The slot argument exists so two iOS projects in the same config don't fight (project A → iosParallelCaps(0), project B → iosParallelCaps(1)). Parallelism within one iOS project comes from device.pool + workers, and the worker fixture auto-staggers these same ports per worker, so a single iOS project (even with a 3-simulator pool) just uses iosParallelCaps(0). :::

It returns a plain object (Record<string, unknown>), so use the spread to merge it with your own extra capabilities, later keys win:

capabilities: {
...iosParallelCaps(0), // WDA ports + tunings (slot 0)
'appium:forceSimulatorSoftwareKeyboardPresence': true, // your extra cap, merged on top
},

Plus baked-in WDA tunings that work for most setups: useNewWDA: true (fresh build each session), wdaStartupRetries: 4, and generous launch/connection timeouts (120 s / 360 s) that cover Xcode's slow first-build phase. Override any of these via the second argument:

capabilities: iosParallelCaps(0, {
useNewWDA: false, // reuse WDA across sessions
wdaLaunchTimeout: 180_000, // 3 min for slower CI machines
}),

You don't need this helper when using device.pool within a single iOS project (auto-staggered per worker), when running iOS through a cloud provider (the cloud manages WDA), or when you only ever run one iOS simulator at a time.

Common use options

OptionDescription
platformPlatform.ANDROID or Platform.IOS.
deviceWhere the test runs. { provider, name, udid?, osVersion? } where provider is 'emulator' | 'local-device' | 'browserstack' | 'lambdatest'. See Parallel runs for device.pool.
buildPathPath to the APK / IPA / .app to install.
appBundleIdApp bundle id (Android package name / iOS bundle id).
resetBetweenTestsIf true, terminate → uninstall → install → activate the app between every test. Requires buildPath and appBundleId.
expectTimeoutDefault timeout for locator actions, in ms. Default 30000.
appiumAppium server connection: { host, port, path, autoStart?, autoStartDevice? }. autoStart: true spawns npx appium if nothing is listening. autoStartDevice: true cold-boots an offline Android emulator (requires a string device.name = the AVD id).
capabilitiesEscape hatch for extra Appium capabilities, merged on top of the defaults. For iOS, taqwright sets appium:forceSimulatorSoftwareKeyboardPresence: true by default; pass false here to opt out.
trace'off' | 'on' | 'on-failure' | 'retain-on-failure'. Per-action screenshots + page-source as a self-contained trace.html. See Tracing.
video'off' | 'on' | 'on-failure' | 'retain-on-failure'. Records the device screen and attaches a screen.mp4. See Screen recording.