Test camera image injection with Maestro on BrowserStack
Replace the device camera feed with your own image during a Maestro test on BrowserStack App Automate.
This feature is available only under Device Cloud Pro, Device Cloud Pro + Visual Cloud, and Enterprise Pro plans. For more details, check out our pricing page.
On BrowserStack App Automate, you can replace the live camera feed in a Maestro test with an image that you upload. Your app reads the injected image as though the camera captured the image. Use camera image injection to automate flows that scan a QR code, read a barcode, or capture a document.
You choose which image to inject at each step. A single flow can scan several images in sequence, such as the front and the back of an identity document.
Prerequisites
Before you start, make sure you have the following:
- Your BrowserStack username and access key, available in the Account & Profile section of your dashboard.
- An Android app as an
.apkfile, or an iOS app as an.ipafile. - A Maestro test suite zipped inside a single parent folder, as described in Prepare your Maestro test suite.
- The image you want to inject, as a JPG, JPEG, or PNG file of up to 10 MB.
How BrowserStack enables camera testing
BrowserStack uses Sensor Instrumentation to let your app interact with device sensors, such as the camera. When you enable camera image injection, BrowserStack adds a camera module to the app you upload. The camera module overrides the camera APIs that your app calls in the Android or iOS SDK, so your app receives the uploaded image instead of a live camera frame.
Your source code stays unchanged. BrowserStack modifies only the copy of the app that runs in the test session.
Camera or barcode image injection doesn’t support:
- iOS apps signed with Enterprise certificates. These apps have the
browserstack.resignAppcapability set tofalse, but camera image injection requires this capability to betrue. - Capturing media types other than images, such as video, from the camera.
- Android apps that use code obfuscation tools like Proguard.
Supported APIs and OS versions
Camera image injection supports the camera APIs in the following table. Check with your app development team to confirm which camera APIs your app uses:
| OS | OS version | Supported APIs |
|---|---|---|
| iOS | iOS 13 and above | - didFinishPickingMediaWithInfo API of UIImagePickerController iOS SDK class for capturing an image. For more information, see the Apple Documentation for UIImagePickerControllerDelegate. - AVCapturePhoto iOS SDK class for receiving captured photos from AVCapturePhotoOutput API. For more information, see the Apple Documentation for AVCapturePhoto. - jpegStillImageNSDataRepresentation of AVCaptureStillImageOutput iOS SDK class. For more information, see the Apple Documentation for AVCaptureStillImageOutput. |
| Android | Android 6 and above | - android.hardware.camera.PreviewCallback API for API level 1-20 - android.hardware.camera2.CameraManager, android.hardware.camera2.CameraDevice, android.hardware.camera2.CameraCharacteristics, android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.media.ImageReader APIs for API level >=21 - com.google.android.gms.mlkit.ACTION_SCAN_DOCUMENT for document scanning - Camera Intent API |
Upload your app and test suite
Upload your app and your zipped Maestro test suite, then note the app_url and test_suite_url that each response returns. You need both values to start a build. For the upload commands, see Execute Maestro tests.
Upload your image to BrowserStack
Upload each image you want to inject using the following cURL command:
The response returns a media_url. This value is the media ID that you pass to your build and to your flow:
A single build accepts up to five media IDs.
Add the BrowserStack executor script to your test suite
Maestro doesn’t use the WebDriver protocol, so Maestro flows have no JavaScript executor of the kind that Appium tests use. BrowserStack provides a script that your flow calls with the runScript command instead.
At the root of your test suite’s parent folder, create a folder named bstack and save the following script as browserstack_executor.js:
Your test suite now has the following structure:
sample_parent_folder/
├── bstack/
│ └── browserstack_executor.js
├── flow1.yaml
└── flow2.yaml
Don’t edit browserstack_executor.js. The script reads the values that BrowserStack sets on the test session. Everything that varies between calls comes from the env block in your flow.
Keep the bstack folder inside the parent folder that you zip, alongside your flow files. If the bstack folder sits outside the parent folder, the runScript step can’t resolve the path to the script. For the required layout, see Prepare your Maestro test suite.
Inject the image from your flow
Add a runScript step to your flow at the point where the uploaded image must become the camera’s next frame. Add the step before your app opens the camera, because the camera captures the image that was injected most recently:
The env block sets the following two values:
-
BROWSERSTACK_EXECUTOR_ACTIONnames the action to run. Useinject_imagefor camera image injection. -
MEDIA_IDis themedia_urlthat the media upload returns. Pass a media ID that you also list incameraInjectionMediawhen you start the build.
To capture a second image later in the same flow, add another runScript step with a different MEDIA_ID. A flow can inject as often as your plan limits allow, as long as you list every MEDIA_ID in cameraInjectionMedia.
Run your test with camera image injection
Set enableCameraImageInjection to true and list your uploaded images in cameraInjectionMedia. Select the platform you test on:
The following table describes the camera image injection parameters:
| Parameter | Type | Description |
|---|---|---|
enableCameraImageInjection |
Boolean | Set to true to add the camera module to your app for the test session. Required for camera image injection. |
cameraInjectionMedia |
Array of strings | Lists the media IDs that your flow can inject, as returned by the media upload. Accepts up to five media IDs. Required for camera image injection. |
Camera image injection on Maestro has the following limitations:
- Camera image injection runs on real devices only, not on emulators or simulators.
- A build must set
enableCameraImageInjectionandcameraInjectionMediatogether. BrowserStack rejects a build that sets one parameter without the other. -
cameraInjectionMediaaccepts up to five media IDs per build.
Check the injection result in your logs
Every call to browserstack_executor.js writes a status line to your Maestro logs. A successful injection shows the following line:
[EXECUTOR] action=inject_image status=200
A failed injection adds a reason to the same line and stops the flow. The following reasons are the most common:
-
media_not_found: theMEDIA_IDin your flow isn’t one of the media IDs listed incameraInjectionMedia. -
executor_unreachable: the flow couldn’t reach the BrowserStack injection service. -
scope_denied: the build didn’t setenableCameraImageInjection, so the session doesn’t allow injection.
To read these lines, see Maestro logs.
Frequently asked questions
Do I need to change my app code?
No. BrowserStack modifies the app you upload, so your source code stays unchanged.
Can I change the image partway through a flow?
Yes. Add a runScript step wherever the flow needs a new image. The camera captures the image that was injected most recently. As a result, a flow that scans both sides of a document injects once before each capture.
What kind of apps are supported?
Camera image injection supports Android and iOS apps, including cross-platform apps. Your app must use a camera API listed in Supported APIs and OS versions.
Can I use other device features with Maestro?
Yes. Maestro also supports video injection, audio injection, biometric authentication, and setting the device timezone.
If you need help configuring your test suite, write to support@browserstack.com.
Related topics
- Prepare your Maestro test suite
- Supported commands on Maestro
- Maestro builds API reference
- Test camera image injection with Appium
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
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!