For AI agents and LLMs: a machine-readable index is available at llms.txt. A plain-Markdown version of any documentation page is available by appending .md to its URL.
Skip to main content

Getting Started With Playwright Testing on iOS Real Devices


Playwright test automation on real iOS devices is now supported on TestMu AI across Node.js, Java, C#, and Python. Test on latest iPhone and iPad Safari combinations to catch device-specific issues that mobile emulation may miss. Integrate with your existing CI pipeline, and access logs and debugging artifacts for each test run.

This guide will cover the basics of getting started with Playwright testing on iOS devices on the TestMu AI platform.

Currently in BETA

Playwright testing on real iOS devices is currently in Beta. To enable this feature for your organization, please contact your account team to have the feature flag turned on.

Supported Versions
  • Playwright versions v1.53.0 to v1.60.0 are supported for iOS Real Device testing (excluding v1.54.0).
  • All languages use the stock Playwright packages, with no custom forks or client-side changes required.
  • Playwright v1.53.0 is currently supported for Playwright C# (for Android & iOS).

Prerequisites


Set your TestMu AI username and access key in the environment variables. You can get your TestMu AI username and access key from your TestMu AI Profile > Account Settings > Password & Security.

Access Key on TestMu AI Automation Dashboard

Windows

set LT_USERNAME="YOUR_LAMBDATEST_USERNAME"
set LT_ACCESS_KEY="YOUR_LAMBDATEST_ACCESS_KEY"

macOS/Linux

export LT_USERNAME="YOUR_LAMBDATEST_USERNAME"
export LT_ACCESS_KEY="YOUR_LAMBDATEST_ACCESS_KEY"

Install the Playwright package:

npm install playwright

Run Your First Test


playwright-ios-test.js
const { webkit } = require("playwright");

(async () => {
const capabilities = {
"LT:Options": {
"platformName": "ios",
"deviceName": "iPhone 16",
"platformVersion": "18",
"isRealMobile": true,
"build": "Playwright iOS Build",
"name": "Playwright iOS Test",
"user": process.env.LT_USERNAME,
"accessKey": process.env.LT_ACCESS_KEY,
"network": true,
"video": true,
"console": true,
},
};

const browser = await webkit.connect(
`wss://cdp.lambdatest.com/playwright?capabilities=${encodeURIComponent(
JSON.stringify(capabilities)
)}`
);

const context = await browser.newContext();
const page = await context.newPage();

await page.goto("https://duckduckgo.com", { timeout: 30000 });
await page.locator('[name="q"]').fill("LambdaTest");
await page.locator('[name="q"]').press("Enter");
await page.waitForTimeout(3000);

const title = await page.title();
console.log("Page title:", title);

try {
if (title.includes("LambdaTest")) {
await page.evaluate(
(_) => {},
`lambdatest_action: ${JSON.stringify({
action: "setTestStatus",
arguments: { status: "passed", remark: "Title verified" },
})}`
);
}
} catch (e) {
await page.evaluate(
(_) => {},
`lambdatest_action: ${JSON.stringify({
action: "setTestStatus",
arguments: { status: "failed", remark: e.message },
})}`
);
}

await page.close();
await context.close();
await browser.close();
})();

Run the test:

node playwright-ios-test.js

Apple Pay Automation


Automate the Apple Pay checkout flow on a real iOS device using Playwright over the TestMu AI CDP endpoint (wss://cdp.lambdatest.com/playwright). When enabled, the platform provisions Wallet, a sandbox card, and the device passcode on the real iPhone — so you never interact with Face ID / Touch ID or set up Wallet manually.

info
  • Apple Pay runs on WebKit/Safari and is supported across all languages available for Playwright iOS testing. The hook calls use the same lambdatest_action server-side channel shown under Run Your First Test, so the same syntax applies in every language.
  • To enable Apple Pay for your organization, please contact us via 24×7 chat support or drop a mail to support@testmuai.com.

Capabilities

CapabilityTypeDefaultRequired / OptionalDescription
applePayBooleanfalseMandatoryEnables Apple Pay on the session — provisions Wallet, a sandbox card, and the device passcode on supported real iOS devices.
applePayCardTypeArrayNoneOptionalPreferred payment network(s) in priority order. Supported values: ["master", "visa", "amex", "discover"]. The first network is preferred; the rest act as fallbacks. If omitted, a default sandbox card is provisioned.

Add the Apple Pay keys to the same LT:Options object you already use to start your Playwright session (see Run Your First Test):

const capabilities = {
"LT:Options": {
// ...your existing iOS capabilities (platformName, deviceName, platformVersion, user, accessKey, etc.)
"applePay": true,
"applePayCardType": ["master", "visa"], // priority order — master preferred, visa as fallback
},
};

Passcode Capabilities

Adding a card to Wallet requires a device passcode:

  • Public cloud — no extra capability is needed. The confirm hook handles the passcode automatically.
  • Private cloud — use the passcode capability to set a custom passcode value directly on the device. Add it inside LT:Options alongside applePay:
// Private cloud only — set a custom passcode
"LT:Options": { /* ...other caps */, "applePay": true, "passcode": "654321" }
note

On iOS 26, the lambda-applepay confirm hook enters the device passcode automatically — the custom passcode on private cloud, or the default passcode on public cloud. No separate passcode step is required.

Validation

Before either Apple Pay hook executes, the gateway validates:

  1. iOS version ≥ 14 — Apple Pay hooks are rejected on older platform versions.
  2. Apple Pay capability presentapplePay: true must be set in LT:Options.

If either check fails, the hook is not executed and an error is returned to the session.

Hooks

Apple Pay hooks are invoked through the TestMu AI server-side action channel — the native Apple Pay sheet is not reachable by Playwright directly. A small reusable wrapper keeps the calls readable:

async function ltAction(page, action, args = {}) {
return page.evaluate(
(_) => {},
`lambdatest_action: ${JSON.stringify({ action, arguments: args })}`
);
}

Hook 1 — lambda-applepay-details (pre-fill the sheet)

Sets shipping, billing, and contact details on the Apple Pay sheet. Call it before launching the sheet. Optional — use it when your merchant requires shipping/contact info.

await ltAction(page, "lambda-applepay-details", {
shippingDetails: {
firstName: "John", lastName: "Doe",
street: "1 Infinite Loop", city: "Cupertino",
state: "California", postalCode: "95014", country: "United States",
},
billingDetails: {
firstName: "John", lastName: "Doe",
street: "1 Infinite Loop", city: "Cupertino",
state: "California", postalCode: "95014", country: "United States",
email: "john.doe@example.com", phone: "+14085551234",
},
contact: {
firstName: "John", lastName: "Doe",
email: "john.doe@example.com", phone: "+14085551234",
},
});

Hook 2 — lambda-applepay (confirm / authorize payment)

Confirms the native Apple Pay sheet to authorize the transaction.

await ltAction(page, "lambda-applepay", { confirm: true });
note

On iOS 26, the confirm hook automatically enters the device passcode — one call confirms the sheet and authorizes the payment end to end. On earlier iOS versions, the passcode is entered as a separate step after confirm.

End-to-End Example

apple-pay.spec.js
const { webkit } = require("playwright");

// Reusable wrapper for any TestMu AI server-side action.
async function ltAction(page, action, args = {}) {
return page.evaluate(
(_) => {},
`lambdatest_action: ${JSON.stringify({ action, arguments: args })}`
);
}

(async () => {
const capabilities = {
"LT:Options": {
platformName: "ios",
deviceName: "iPhone 16",
platformVersion: "26",
isRealMobile: true,
user: process.env.LT_USERNAME,
accessKey: process.env.LT_ACCESS_KEY,
build: "Apple Pay 26.0",
name: "Apple Pay via Playwright",
applePay: true,
applePayCardType: ["master", "visa"],
},
};

const browser = await webkit.connect(
`wss://cdp.lambdatest.com/playwright?capabilities=${encodeURIComponent(
JSON.stringify(capabilities)
)}`
);

const context = await browser.newContext();
const page = await context.newPage();

// Navigate to your checkout page and trigger the Apple Pay sheet here...

// Optional: pre-fill shipping / billing / contact on the sheet.
await ltAction(page, "lambda-applepay-details", {
billingDetails: {
firstName: "John", lastName: "Doe",
street: "1 Infinite Loop", city: "Cupertino",
state: "California", postalCode: "95014", country: "United States",
email: "john.doe@example.com", phone: "+14085551234",
},
});

// Confirm the sheet. On iOS 26 the passcode is entered automatically.
await ltAction(page, "lambda-applepay", { confirm: true });

// Assert your post-payment state (swap for a real locator on your app).
// await page.getByText(/order confirmed/i).waitFor();

await page.close();
await context.close();
await browser.close();
})();

The ltAction helper is generic — reuse it for setTestStatus, smartui.takeScreenshot, or any other TestMu AI action.

View your Playwright test results


The TestMu AI Automation Dashboard is where you can see the results of your Playwright iOS tests after running them on the TestMu AI platform.

The below screenshot of TestMu AI Automation Dashboard shows the Playwright build on the left and the build sessions associated with the selected build on the right.

Playwright iOS build and session details on TestMu AI Automation Dashboard
note
  • Safari is the supported browser for iOS real device testing. All four languages (Node.js, Java, C#, and Python) are supported using stock Playwright packages.

  • Playwright testing on real iOS devices is currently supported on latest iOS versions (iOS 17, iOS 18, and iOS 26) across both iPhones and iPads.

Test across 3000+ combinations of browsers, real devices & OS.

×
Schedule Your Personal Demo
Book Demo

Help and Support

Related Articles