Skip to main content
No Result Found
Connect and get help from 7,000+ developers on our Discord community. Ask the CommunityAsk the Community

Integrate your Maestro test suite with App Percy

Run App Percy visual tests on your Maestro mobile flows using the @percy/maestro-app SDK on BrowserStack Maestro sessions.

Use the @percy/maestro-app SDK to add App Percy visual testing to your Maestro flows. You add a screenshot step to a flow, then run that flow on a BrowserStack Maestro session, where App Percy captures the screen and uploads it to your Percy project.

App Percy with Maestro runs only on BrowserStack Maestro sessions, on Android and iOS. Local maestro test runs aren’t supported and screenshot uploads fail.

Prerequisites

Before you begin, ensure you have the following:

Install the SDK

Install the SDK and the Percy CLI as development dependencies:

npm install --save-dev @percy/maestro-app @percy/cli

The SDK ships a percy/ directory that contains the flow and script files your Maestro flow references at runtime. You can reference this directory in either of the following ways before you zip your test suite for upload to BrowserStack.

Mode A: Reference under node_modules

Keep the SDK in node_modules and reference it from there in your flow. Include the node_modules/@percy/maestro-app/percy directory when you zip your test suite.

Mode B: Vendor copy (recommended)

Copy the SDK’s percy/ directory into your workspace to produce a smaller zip:

cp -r node_modules/@percy/maestro-app/percy ./percy

Your workspace then has the following layout:

your-maestro-workspace/
  percy/
    flows/
      percy-init.yaml
      percy-screenshot.yaml
    scripts/
      percy-healthcheck.js
      percy-screenshot.js
  your-flow.yaml

Capture a screenshot

To capture a screenshot at any point in your flow, add a runFlow step that references the SDK’s percy-screenshot.yaml and sets the SCREENSHOT_NAME environment variable:

- runFlow:
    file: percy/flows/percy-screenshot.yaml
    env:
      SCREENSHOT_NAME: Homepage

The first screenshot step runs a lazy healthcheck and initializes App Percy, so you don’t need a separate setup step.

SCREENSHOT_NAME must match the pattern ^[a-zA-Z0-9_-]+$. Names with spaces, dots, or slashes are rejected with an HTTP 400 response.

Run your tests

Run your flow through the Percy CLI:

npx percy app:exec -- maestro test your-flow.yaml

App Percy starts, creates a build, captures each screenshot in the flow, uploads the screenshots to your project, and then stops.

Configuration

Set the following environment variables to control how App Percy captures each screenshot. On BrowserStack Maestro sessions, the device variables are injected for you, so you only set the ones you want to override.

Variable Required Default Purpose
SCREENSHOT_NAME Yes N/A Name for the screenshot. Must match ^[a-zA-Z0-9_-]+$.
PERCY_DEVICE_NAME No Injected on BrowserStack Device identifier, such as Pixel 7. BrowserStack sets this from the session device.
PERCY_OS_VERSION No Injected on BrowserStack OS version, such as 13 on Android or 17 on iOS. BrowserStack sets this from the session device.
PERCY_ORIENTATION No portrait Screen orientation, either portrait or landscape.
PERCY_REGIONS No N/A JSON array of region masks.
PERCY_SYNC No false Set to true to wait for comparison results.
PERCY_FULLSCREEN No false Set to true when the screen has no system chrome.
PERCY_STATUS_BAR_HEIGHT No Android 120, iOS 100 Height in image pixels to mask at the top of the screen.
PERCY_NAV_BAR_HEIGHT No Android 100, iOS 80 Height in image pixels to mask at the bottom of the screen.

Status bar and navigation bar masking

App Percy masks the device status bar and navigation bar so that the clock, battery, and other dynamic system elements don’t trigger false visual differences. The defaults differ by platform:

Variable Android default iOS default
PERCY_STATUS_BAR_HEIGHT 120 100
PERCY_NAV_BAR_HEIGHT 100 80

Device pixel densities vary, so the default heights don’t fit every device. Override PERCY_STATUS_BAR_HEIGHT and PERCY_NAV_BAR_HEIGHT per device when the mask doesn’t cover the full bar. For example, an iPhone with a Dynamic Island needs a taller status bar mask than the iOS default.

Regions

Use the PERCY_REGIONS environment variable to mark areas of a screenshot for a specific comparison algorithm. Set it to a JSON array, where each object defines a region and the algorithm to apply.

The following algorithms are available:

  • ignore: Excludes the region from comparison. Any change inside the region is ignored.
  • standard: Compares the region with the standard sensitivity.
  • intelliignore: Uses AI to ignore dynamic content such as advertisements and carousels.
  • layout: Checks structural layout with a pixel-level tolerance.

Coordinate-based regions

Define a region by its pixel boundaries:

PERCY_REGIONS: '[{"top":0,"bottom":50,"left":0,"right":1080,"algorithm":"ignore"}]'

Element-based regions

Define a region by a UI element. The supported locators differ by platform.

On Android, use resource-id, text, content-desc, or class:

PERCY_REGIONS: '[{"element":{"resource-id":"com.app:id/clock"},"algorithm":"ignore"}]'

On iOS, use id, the accessibility identifier, or class:

PERCY_REGIONS: '[{"element":{"id":"clock-label"},"algorithm":"ignore"}]'

Run on BrowserStack

When you trigger a Maestro build through the BrowserStack App Automate API, pass your Percy token in the appPercy object of the build payload. This field is the same on both Android and iOS.

Use the appPercy field to pass your Percy token. The percyOptions field is silently dropped, so screenshots won’t reach your project if you use it.

The following request triggers an Android build:

curl -u "BROWSERSTACK_USERNAME:BROWSERSTACK_ACCESS_KEY" \
  -X POST "https://api-cloud.browserstack.com/app-automate/maestro/v2/android/build" \
  -H "Content-Type: application/json" \
  -d '{
    "app": "<APP_URL>",
    "testSuite": "<TEST_SUITE_URL>",
    "devices": ["Samsung Galaxy S22-12.0"],
    "project": "my-percy-maestro-project",
    "appPercy": {
      "PERCY_TOKEN": "<PERCY_TOKEN>"
    }
  }'

The following request triggers an iOS build and passes an extra Percy variable through the env sub-object:

curl -u "BROWSERSTACK_USERNAME:BROWSERSTACK_ACCESS_KEY" \
  -X POST "https://api-cloud.browserstack.com/app-automate/maestro/v2/ios/build" \
  -H "Content-Type: application/json" \
  -d '{
    "app": "<APP_URL>",
    "testSuite": "<TEST_SUITE_URL>",
    "devices": ["iPhone 14-16"],
    "project": "my-percy-maestro-project",
    "appPercy": {
      "PERCY_TOKEN": "<PERCY_TOKEN>",
      "env": {
        "PERCY_BRANCH": "main"
      }
    }
  }'

Pass any PERCY_* variable through the appPercy.env sub-object.

Unsupported features

The following features aren’t supported in version 1.0.0 of the SDK:

  • Session-to-build correlation through browserstack_executor.
  • Full-page or scrollable capture.
  • Animation freezing and Percy-specific CSS.
  • XPath region selectors on Android.
  • Automatic device-metadata detection on iOS.
  • Local maestro test runtime.

The following features are planned for a later release:

  • The PERCY_IGNORE_ERRORS and PERCY_ENABLED switches.
  • The text and xpath element selectors on iOS.
  • Rendering of PERCY_LABELS on the dashboard.

We're sorry to hear that. Please share your feedback so we can do better

Contact our Support team for immediate help while we work on improving our docs.

We're continuously improving our docs. We'd love to know what you liked





Thank you for your valuable feedback

Is this page helping you?

Yes
No

We're sorry to hear that. Please share your feedback so we can do better

Contact our Support team for immediate help while we work on improving our docs.

We're continuously improving our docs. We'd love to know what you liked





Thank you for your valuable feedback!

Talk to an Expert
Download Copy Check Circle