Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added apps/regression.apk
Binary file not shown.
69 changes: 69 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,75 @@
</plugins>
</build>
</profile>
<profile>
<id>biometric</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
-javaagent:${com.browserstack:browserstack-java-sdk:jar}
</argLine>
<systemPropertyVariables>
<browserstack-local>false</browserstack-local>
<browserstack.config>src/test/resources/conf/capabilities/browserstack-media.yml</browserstack.config>
</systemPropertyVariables>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/conf/runners/biometric-testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>image-injection</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
-javaagent:${com.browserstack:browserstack-java-sdk:jar}
</argLine>
<systemPropertyVariables>
<browserstack-local>false</browserstack-local>
<browserstack.config>src/test/resources/conf/capabilities/browserstack-media.yml</browserstack.config>
</systemPropertyVariables>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/conf/runners/image-injection-testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>biometric-and-image-injection</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
-javaagent:${com.browserstack:browserstack-java-sdk:jar}
</argLine>
<systemPropertyVariables>
<browserstack-local>false</browserstack-local>
<browserstack.config>src/test/resources/conf/capabilities/browserstack-media.yml</browserstack.config>
</systemPropertyVariables>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/conf/runners/biometric-and-image-injection-testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>geolocation</id>
<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.browserstack.advance_use_cases;

import io.appium.java_client.MobileBy;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.net.MalformedURLException;
import java.net.URL;

public class BiometricAuthTest {

private AndroidDriver driver;
private WebDriverWait wait;

@BeforeMethod
public void setUp() throws MalformedURLException {
DesiredCapabilities capabilities = new DesiredCapabilities();
// BrowserStack SDK (browserstack-media.yml) overrides this URL automatically
driver = new AndroidDriver(
new URL("http://127.0.0.1:4723/wd/hub"),
capabilities
);
wait = new WebDriverWait(driver, 10);
}

@Test
public void testBiometricAuthentication() {
// Click on biometric prompt button
WebElement bioPromptButton = wait.until(
ExpectedConditions.elementToBeClickable(
MobileBy.id("com.example.all_in_one:id/bio_prompt")
)
);
bioPromptButton.click();

// Click on prompt button
WebElement promptButton = wait.until(
ExpectedConditions.elementToBeClickable(
MobileBy.id("com.example.all_in_one:id/prompt")
)
);
promptButton.click();

// Simulate successful biometric authentication via BrowserStack executor
// Wait briefly for the biometric prompt to appear before executing
wait.until(ExpectedConditions.not(
ExpectedConditions.presenceOfAllElementsLocatedBy(
MobileBy.id("com.example.all_in_one:id/prompt")
)
));
driver.executeScript(
"browserstack_executor: {\"action\":\"biometric\", \"arguments\": {\"biometricMatch\": \"pass\"}}"
);
}

@AfterMethod
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}
122 changes: 122 additions & 0 deletions src/test/java/com/browserstack/advance_use_cases/ImageInjection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package com.browserstack.advance_use_cases;

import io.appium.java_client.MobileBy;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.net.MalformedURLException;
import java.net.URL;

public class ImageInjection {

private AndroidDriver driver;
private WebDriverWait wait;
private WebDriverWait shortWait;

@BeforeMethod
public void setUp() throws MalformedURLException {
DesiredCapabilities capabilities = new DesiredCapabilities();
// BrowserStack SDK (browserstack-media.yml) overrides this URL and injects
// enableCameraImageInjection: true automatically from the yml config
driver = new AndroidDriver(
new URL("http://127.0.0.1:4723/wd/hub"),
capabilities
);
wait = new WebDriverWait(driver, 45);
shortWait = new WebDriverWait(driver, 5);
}

@Test
public void testCameraImageInjection() {
// Click on Camera Intent button on the home screen
WebElement cameraIntentButton = wait.until(
ExpectedConditions.elementToBeClickable(
MobileBy.id("com.example.all_in_one:id/camintent")
)
);
cameraIntentButton.click();

// Click on the camera button to open the camera
WebElement cameraButton = wait.until(
ExpectedConditions.elementToBeClickable(
MobileBy.id("com.example.all_in_one:id/camera_button")
)
);
cameraButton.click();

// Allow "While using the app" camera permission if prompted
try {
WebElement allowForegroundButton = shortWait.until(
ExpectedConditions.elementToBeClickable(
MobileBy.id("com.android.permissioncontroller:id/permission_allow_foreground_only_button")
)
);
allowForegroundButton.click();
} catch (Exception e) {
// Permission dialog may not appear if already granted
}

// Allow any additional permission prompts (e.g., storage, media)
try {
WebElement allowButton = shortWait.until(
ExpectedConditions.elementToBeClickable(
MobileBy.id("com.android.permissioncontroller:id/permission_allow_button")
)
);
allowButton.click();
} catch (Exception e) {
// Permission dialog may not appear if already granted
}

// Handle "Turn on Location tags?" dialog if it appears
try {
WebElement turnOnButton = shortWait.until(
ExpectedConditions.elementToBeClickable(
MobileBy.xpath("//android.widget.Button[@text='Turn on']")
)
);
turnOnButton.click();
} catch (Exception e) {
// Location tags dialog may not appear
}

// Wait for the camera viewfinder/shutter to be ready before injecting
WebElement shutterButton = wait.until(
ExpectedConditions.elementToBeClickable(
MobileBy.xpath("//*[@content-desc='Shutter' or @content-desc='Take photo' or contains(@resource-id,'shutter')]")
)
);

// Inject the image AFTER camera is confirmed open and shutter is visible
driver.executeScript(
"browserstack_executor: {\"action\":\"cameraImageInjection\", \"arguments\": {\"imageUrl\": \"media://22892692ccf96ca859fbe0eaf9ecc410e5fa855e\"}}"
);

// Wait for injected image to appear in viewfinder, then tap shutter
wait.until(ExpectedConditions.elementToBeClickable(
MobileBy.xpath("//*[@content-desc='Shutter' or @content-desc='Take photo' or contains(@resource-id,'shutter')]")
));
shutterButton.click();

// Tap Done/Save to confirm the captured photo (Samsung Camera on Galaxy S23)
WebElement doneButton = wait.until(
ExpectedConditions.elementToBeClickable(
MobileBy.xpath("//*[@content-desc='Done' or @content-desc='Save' or @content-desc='OK' or @text='Done' or @text='Save' or @resource-id='com.sec.android.app.camera:id/okay' or @resource-id='com.sec.android.app.camera:id/done_button']")
)
);
doneButton.click();
}

@AfterMethod
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}
31 changes: 31 additions & 0 deletions src/test/resources/conf/capabilities/browserstack-media.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
userName: kriyademo_ozbSWp
accessKey: G6pRTrBB3popqRNCdkt7

app: apps/regression.apk

framework: testng

platforms:
- platformName: android
deviceName: Samsung Galaxy S23
platformVersion: "13.0"

parallelsPerPlatform: 1

autoGrantPermissions: true

interactiveDebugging: true

buildName: Sample Mobile App Testing - Android
projectName: L1Docket

# Appium Options
idleTimeout: 90
autoAcceptAlerts: true

enableBiometric: true
enableCameraImageInjection: true
enableCameraPreview: true
# Debugging
debug: true
networkLogs: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="BiometricAndImageInjection">
<test name="Biometric Authentication Test">
<classes>
<class name="com.browserstack.advance_use_cases.BiometricAuthTest"/>
</classes>
</test>
<test name="Camera Image Injection Test">
<classes>
<class name="com.browserstack.advance_use_cases.ImageInjection"/>
</classes>
</test>
</suite>
9 changes: 9 additions & 0 deletions src/test/resources/conf/runners/biometric-testng.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="BiometricAuth">
<test name="Biometric Authentication Test">
<classes>
<class name="com.browserstack.advance_use_cases.BiometricAuthTest"/>
</classes>
</test>
</suite>
9 changes: 9 additions & 0 deletions src/test/resources/conf/runners/image-injection-testng.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="ImageInjection">
<test name="Camera Image Injection Test">
<classes>
<class name="com.browserstack.advance_use_cases.ImageInjection"/>
</classes>
</test>
</suite>
Loading