diff --git a/app-automate/README.md b/app-automate/README.md new file mode 100644 index 0000000..30a745d --- /dev/null +++ b/app-automate/README.md @@ -0,0 +1,132 @@ +# Cross-Device Automation Agent Demo (BrowserStack App Automate) + +[TestNG](http://testng.org) Integration with BrowserStack App Automate for Android and iOS. + +![BrowserStack Logo](https://d98b8t1nnulk5.cloudfront.net/production/images/layout/logo-header.png?1469004780) + +## What Does This Repo Do? + +This repository showcases the use of **BrowserStack's Cross-Device Automation Agent** for mobile app automation using TestNG and Appium. The key feature is the ability to write test steps in **Natural Language (Plain English)**, moving away from explicit Appium locators and actions. + +It contains demo scripts: +* **Android - `AppiumTest.java`**: Runs test objectives on the Wikipedia Android app using simple English commands like searching for articles and validating results. +* **iOS - `AppiumTest.java`**: Runs test objectives on the BBC News iOS app using simple English commands like navigating to Culture tab and validating page headings. + +--- + +## How It Works + +1. **Enablement:** The feature is enabled by declaring the capability `aiAuthoring: true` in your `browserstack.yml` configuration file. +2. **The Command:** Inside the test scripts, the test uses a standard Selenium `JavascriptExecutor` to pass the Natural Language instruction to the BrowserStack environment: + ```java + // Example for Android: Search for "india" on Wikipedia app + jse.executeScript("browserstack_executor: {\"action\": \"ai\", \"arguments\": [\"Tap on the \\\"Search\\\" option from below navigation bar and type \\\" india\\\" on the search bar and tap on the first suggestion\"]}"); + + // Example for iOS: Navigate to Culture tab + jse.executeScript("browserstack_executor: {\"action\": \"ai\", \"arguments\": [\"Tap on culture tab from the top navigation bar\"]}"); + ``` +3. **Execution:** The BrowserStack Cross-Device Automation Agent intercepts this command, interprets the natural language, and executes the equivalent low-level Appium actions on the mobile app. + +--- + +## Setup + +### Requirements + +1. Java 8+ + - If Java is not installed, follow these instructions: + - For Windows, download latest java version from [here](https://java.com/en/download/) and run the installer executable + - For Mac and Linux, run `java -version` to see what java version is pre-installed. If you want a different version download from [here](https://java.com/en/download/) + +2. Maven (Only required if using Maven as the build tool) + - If Maven is not downloaded, download it from [here](https://maven.apache.org/download.cgi) + - For installation, follow the instructions [here](https://maven.apache.org/install.html) + +3. Gradle (Only required if using Gradle as the build tool) + - If Gradle is not downloaded, download it from [here](https://gradle.org/releases/) + - For installation, follow the instructions [here](https://gradle.org/install/) + +--- + +## Running the Tests + +### For Android + +#### Using Maven + +- Clone the repository +- Navigate to the Android directory: `cd app-automate/android` +- Replace `YOUR_USERNAME` and `YOUR_ACCESS_KEY` with your BrowserStack access credentials in `browserstack.yml`. +- Declare capability **`aiAuthoring: true`** in `browserstack.yml` file (if not already present). +- Install dependencies `mvn compile` +- To run the test suite having cross-platform with parallelization, run `mvn test -P sample-test`. +- To run local tests, run `mvn test -P sample-local-test`. + +#### Using Gradle + +- Clone the repository +- Navigate to the Android directory: `cd app-automate/android` +- Replace `YOUR_USERNAME` and `YOUR_ACCESS_KEY` with your BrowserStack access credentials in `browserstack.yml`. +- Declare capability **`aiAuthoring: true`** in `browserstack.yml` file (if not already present). +- Install dependencies `gradle build` +- To run the test suite having cross-platform with parallelization, run `gradle sampleTest`. +- To run local tests, run `gradle sampleLocalTest`. + +### For iOS + +#### Using Maven + +- Clone the repository +- Navigate to the iOS directory: `cd app-automate/ios` +- Replace `YOUR_USERNAME` and `YOUR_ACCESS_KEY` with your BrowserStack access credentials in `browserstack.yml`. +- Declare capability **`aiAuthoring: true`** in `browserstack.yml` file (if not already present). +- Install dependencies `mvn compile` +- To run the test suite having cross-platform with parallelization, run `mvn test -P sample-test`. +- To run local tests, run `mvn test -P sample-local-test`. + +#### Using Gradle + +- Clone the repository +- Navigate to the iOS directory: `cd app-automate/ios` +- Replace `YOUR_USERNAME` and `YOUR_ACCESS_KEY` with your BrowserStack access credentials in `browserstack.yml`. +- Declare capability **`aiAuthoring: true`** in `browserstack.yml` file (if not already present). +- Install dependencies `gradle build` +- To run the test suite having cross-platform with parallelization, run `gradle sampleTest`. +- To run local tests, run `gradle sampleLocalTest`. + +Understand how many parallel sessions you need by using our [Parallel Test Calculator](https://www.browserstack.com/automate/parallel-calculator?ref=github). + +--- + +## Integrate Your Test Suite + +### Maven Integration + +* Add maven dependency of `browserstack-java-sdk` in your `pom.xml` file: + ```xml + + com.browserstack + browserstack-java-sdk + LATEST + compile + + ``` +* Modify your build plugin to run tests by adding `argLine -javaagent:${com.browserstack:browserstack-java-sdk:jar}` in the Surefire plugin configuration. +* Install dependencies `mvn compile`. + +### Gradle Integration + +* Add `compileOnly 'com.browserstack:browserstack-java-sdk:latest.release'` in dependencies in your `build.gradle`. +* Fetch Artifact Information and add `jvmArgs` property in tasks. +* Install dependencies `gradle build`. + +--- + +## Notes + +* You can view your test results on the [BrowserStack App Automate dashboard](https://www.browserstack.com/app-automate). +* For detailed documentation on Appium and Java setup with BrowserStack App Automate, please refer to the [official documentation](https://www.browserstack.com/docs/app-automate/appium). + +## Getting Help + +If you are running into any issues or have any queries, please check [Browserstack Support page](https://www.browserstack.com/support/app-automate) or [get in touch with us](https://www.browserstack.com/contact?ref=help). diff --git a/app-automate/android/.gitignore b/app-automate/android/.gitignore new file mode 100644 index 0000000..66117fc --- /dev/null +++ b/app-automate/android/.gitignore @@ -0,0 +1,12 @@ +*.png +target/ +local.log +.idea +*.iml +**/logs/* +.DS_Store +build +gradle +.gradle +gradlew* +log \ No newline at end of file diff --git a/app-automate/android/README.md b/app-automate/android/README.md new file mode 100644 index 0000000..7abe9a0 --- /dev/null +++ b/app-automate/android/README.md @@ -0,0 +1,91 @@ +# testng-appium-app-browserstack + +This repository demonstrates how to run Appium tests in [TestNG](http://testng.org) on BrowserStack App Automate using BrowserStack SDK. + +![BrowserStack Logo](https://d98b8t1nnulk5.cloudfront.net/production/images/layout/logo-header.png?1469004780) + +## Setup + +### Requirements + +1. Java 8+ + + - If Java is not installed, follow these instructions: + - For Windows, download latest java version from [here](https://java.com/en/download/) and run the installer executable + - For Mac and Linux, run `java -version` to see what java version is pre-installed. If you want a different version download from [here](https://java.com/en/download/) + +2. Maven (Only required if using Maven as the build tool) + - If Maven is not downloaded, download it from [here](https://maven.apache.org/download.cgi) + - For installation, follow the instructions [here](https://maven.apache.org/install.html) + +3. Gradle (Only required if using Gradle as the build tool) + - If Gradle is not downloaded, download it from [here](https://gradle.org/releases/) + - For installation, follow the instructions [here](https://gradle.org/install/) + +### Install the dependencies + +To install the dependencies for Android tests, run : +```sh +cd android/testng-examples +mvn clean +``` + +Or, + +To install the dependencies for iOS tests, run : + +```sh +cd ios/testng-examples +mvn clean +``` + +## Getting Started + +Getting Started with Appium tests in TestNg on BrowserStack couldn't be easier! + +### **Run Sample test :** + +- Switch to one of the following directories: [Android examples](android/testng-examples) or [iOS examples](ios/testng-examples) +- **For Maven:** Run the following command to execute tests in the Maven environment: + ```sh + mvn test -P sample-test + ``` +- **For Gradle:** Run the following command to execute tests in the Gradle environment: + ```sh + gradle clean sampleTest + ``` + +### **Use Local testing for apps that access resources hosted in development or testing environments :** + +- Simply configure the `browserstackLocal` parameter in the `browserstack.yml` file accordingly in [Android examples](android/testng-examples) or [iOS examples](ios/testng-examples). + ``` + browserstackLocal: true + ``` +- You can use the `LocalSample` app provided in both folder [Android examples](android/testng-examples) or [iOS examples](ios/testng-examples) to run your test. Change the app parameter in the `browserstack.yml` file. + +- **For Maven:** Run the following command to execute tests in the Maven environment: + ```sh + mvn test -P sample-local-test + ``` +- **For Gradle:** Run the following command to execute tests in the Gradle environment: + ```sh + gradle clean sampleLocalTest + ``` + +-similarly for gradle you can do :- gradle clean sampleLocalTest + + +**Note**: If you are facing any issues, refer [Getting Help section](#Getting-Help) + +## Integration with other Java frameworks + +For other Java frameworks samples, refer to following repositories : + +- [JUnit](https://github.com/browserstack/junit-appium-app-browserstack) +- [Java](https://github.com/browserstack/java-appium-app-browserstack) + +Note: For other test frameworks supported by App-Automate refer our [Developer documentation](https://www.browserstack.com/docs/) + +## Getting Help + +If you are running into any issues or have any queries, please check [Browserstack Support page](https://www.browserstack.com/support/app-automate) or [get in touch with us](https://www.browserstack.com/contact?ref=help). \ No newline at end of file diff --git a/app-automate/android/browserstack.yml b/app-automate/android/browserstack.yml new file mode 100644 index 0000000..9a6388b --- /dev/null +++ b/app-automate/android/browserstack.yml @@ -0,0 +1,81 @@ +# ============================= +# Set BrowserStack Credentials +# ============================= +# Add your BrowserStack userName and acccessKey here or set BROWSERSTACK_USERNAME and +# BROWSERSTACK_ACCESS_KEY as env variables +userName: vishalshivkumar_ECWceV +accessKey: CHwbbppxpBGZ5ypzTqxC + +# ====================== +# BrowserStack Reporting +# ====================== +# The following capabilities are used to set up reporting on BrowserStack: +# Set 'projectName' to the name of your project. Example, Marketing Website +projectName: BrowserStack Sample +# Set `buildName` as the name of the job / testsuite being run +buildName: Cross-Device Automation Agent - Android +# `buildIdentifier` is a unique id to differentiate every execution that gets appended to +# buildName. Choose your buildIdentifier format from the available expressions: +# ${BUILD_NUMBER} (Default): Generates an incremental counter with every execution +# ${DATE_TIME}: Generates a Timestamp with every execution. Eg. 05-Nov-19:30 +# Read more about buildIdentifiers here -> https://www.browserstack.com/docs/automate/selenium/organize-tests +buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${expression} +# Set `framework` of your test suite. Example, `testng`, `cucumber`, `cucumber-testng` +# This property is needed to send test context to BrowserStack (test name, status) +framework: testng + +source: testng:appium-sample-sdk:v1.1 + +app: bs://b78d7940823391d54091b98d7f3b223e321d133e +#app: ./LocalSample.apk #For running local tests + +# ======================================= +# Platforms (Browsers / Devices to test) +# ======================================= +# Platforms object contains all the browser / device combinations you want to test on. +# Entire list available here -> (https://www.browserstack.com/list-of-browsers-and-platforms/automate) + +platforms: + - deviceName: Samsung Galaxy S22 Ultra + osVersion: 12.0 + platformName: android + # - deviceName: Samsung Galaxy S21 + # osVersion: 11.0 + # platformName: android + # - deviceName: Google Pixel 6 Pro + # osVersion: 12.0 + # platformName: android +aiAuthoring: true +interactiveDebugging: true + +# ======================= +# Parallels per Platform +# ======================= +# The number of parallel threads to be used for each platform set. +# BrowserStack's SDK runner will select the best strategy based on the configured value +# +# Example 1 - If you have configured 3 platforms and set `parallelsPerPlatform` as 2, a total of 6 (2 * 3) parallel threads will be used on BrowserStack +# +# Example 2 - If you have configured 1 platform and set `parallelsPerPlatform` as 5, a total of 5 (1 * 5) parallel threads will be used on BrowserStack +parallelsPerPlatform: 1 + +# ========================================== +# BrowserStack Local +# (For localhost, staging/private websites) +# ========================================== +# Set browserStackLocal to true if your website under test is not accessible publicly over the internet +# Learn more about how BrowserStack Local works here -> https://www.browserstack.com/docs/automate/selenium/local-testing-introduction +browserstackLocal: true # (Default false) +#browserStackLocalOptions: +#Options to be passed to BrowserStack local in-case of advanced configurations +# localIdentifier: # (Default: null) Needed if you need to run multiple instances of local. +# forceLocal: true # (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel. +# Entire list of arguments available here -> https://www.browserstack.com/docs/automate/selenium/manage-incoming-connections + +# =================== +# Debugging features +# =================== +debug: false # # Set to true if you need screenshots for every selenium command ran +networkLogs: false # Set to true to enable HAR logs capturing +consoleLogs: errors # Remote browser's console debug levels to be printed (Default: errors) +# Available options are `disable`, `errors`, `warnings`, `info`, `verbose` (Default: errors) diff --git a/app-automate/android/build.gradle b/app-automate/android/build.gradle new file mode 100644 index 0000000..92de6d2 --- /dev/null +++ b/app-automate/android/build.gradle @@ -0,0 +1,47 @@ +plugins { + id 'java' +} + +repositories { mavenCentral() } + +dependencies { + testImplementation 'org.testng:testng:7.5' + implementation 'org.seleniumhq.selenium:selenium-java:4.13.0' + implementation 'io.appium:java-client:8.6.0' + implementation 'commons-io:commons-io:2.11.0' + implementation 'com.googlecode.json-simple:json-simple:1.1.1' + implementation 'com.browserstack:browserstack-java-sdk:latest.release' +} + +group = 'com.browserstack' +version = '1.0-SNAPSHOT' +description = 'testng-browserstack' +sourceCompatibility = '1.8' + +def browserstackSDKArtifact = configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.find { it.name == 'browserstack-java-sdk' } + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + +tasks.withType(Test) { + systemProperties = System.properties +} + +task sampleTest(type: Test) { + useTestNG() { + dependsOn cleanTest + useDefaultListeners = true + suites "src/test/resources/com/browserstack/sample-test.testng.xml" + jvmArgs "-javaagent:${browserstackSDKArtifact.file}" + } +} + +task sampleLocalTest(type: Test) { + useTestNG() { + dependsOn cleanTest + useDefaultListeners = true + suites "src/test/resources/com/browserstack/sample-local-test.testng.xml" + jvmArgs "-javaagent:${browserstackSDKArtifact.file}" + } +} diff --git a/app-automate/android/pom.xml b/app-automate/android/pom.xml new file mode 100644 index 0000000..a45d8f2 --- /dev/null +++ b/app-automate/android/pom.xml @@ -0,0 +1,127 @@ + + + 4.0.0 + + com.browserstack + testng-browserstack-android + 1.0-SNAPSHOT + jar + + testng-browserstack + https://github.com/browserstack/testng-appium-app-browserstack + + + UTF-8 + 1.8 + 1.8 + 2.19.1 + 3.0.0-M5 + default + + + + + org.testng + testng + 7.5 + + + org.seleniumhq.selenium + selenium-java + 4.13.0 + + + io.appium + java-client + 8.6.0 + + + commons-io + commons-io + 2.11.0 + + + com.googlecode.json-simple + json-simple + 1.1.1 + + + com.browserstack + browserstack-java-sdk + LATEST + compile + + + + + + + maven-dependency-plugin + 3.3.0 + + + getClasspathFilenames + + properties + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + src/test/resources/com/browserstack/sample-test.testng.xml + + -javaagent:${com.browserstack:browserstack-java-sdk:jar} + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + + + + + sample-test + + + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/com/browserstack/sample-test.testng.xml + + + + + + + + sample-local-test + + + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/com/browserstack/sample-local-test.testng.xml + + + + + + + + diff --git a/app-automate/android/settings.gradle b/app-automate/android/settings.gradle new file mode 100644 index 0000000..55607bd --- /dev/null +++ b/app-automate/android/settings.gradle @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + mavenCentral() + mavenLocal() + gradlePluginPortal() + } + + resolutionStrategy { + eachPlugin { + if (requested.id.id == "com.browserstack.gradle-sdk") { + useModule("com.browserstack:gradle-sdk:1.1.2") + } + } + } +} +rootProject.name = 'testng-browserstack-android' diff --git a/app-automate/android/src/test/java/com/browserstack/AppiumTest.java b/app-automate/android/src/test/java/com/browserstack/AppiumTest.java new file mode 100644 index 0000000..dab97e8 --- /dev/null +++ b/app-automate/android/src/test/java/com/browserstack/AppiumTest.java @@ -0,0 +1,83 @@ +package com.browserstack; + +import java.net.URL; +import java.util.Map; + +import org.openqa.selenium.JavascriptExecutor; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.options.UiAutomator2Options; + + +public class AppiumTest { + + public AndroidDriver driver; + private static final String BROWSERSTACK_HUB = "https://hub-cloud.browserstack.com/wd/hub"; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + UiAutomator2Options capabilities = new UiAutomator2Options(); + driver = new AndroidDriver(new URL(BROWSERSTACK_HUB), capabilities); + } + + @Test + public void sampleTest() throws Exception { + JavascriptExecutor jse = (JavascriptExecutor) driver; + + // AI Action 1: Search for "india" on Wikipedia + System.out.println("Action 1: Tap on the \"Search\" option from below navigation bar and type \" india\" on the search bar and tap on the first suggestion"); + jse.executeScript("browserstack_executor: {\"action\": \"ai\", \"arguments\": [\"Tap on the \\\"Search\\\" option from below navigation bar and type \\\" india\\\" on the search bar and tap on the first suggestion\"]}"); + Thread.sleep(3000); // Wait for search results + + // AI Action 2: Extract the title of the search result + System.out.println("Action 2: Extract the title of the search result..."); + Object titleResult = jse.executeScript("browserstack_executor: {\"action\": \"ai\", \"arguments\": [\"Extract the title of the search result\"]}"); + String extractedTitle = titleResult != null ? titleResult.toString() : ""; + System.out.println("Extracted Title: " + extractedTitle); + + // AI Validation: Check if the title contains "India" + System.out.println("Validation: Checking if title of the search result contains India..."); + Object validationResult = jse.executeScript("browserstack_executor: {\"action\": \"ai\", \"arguments\": [\"Validate if the title of the search result contains India\"]}"); + + // Convert AI validation result to boolean and assert + boolean isValidationPassed = false; + + if (validationResult instanceof Boolean) { + isValidationPassed = (Boolean) validationResult; + } else if (validationResult instanceof Map) { + // Check if result is an object with a "value" attribute + Map resultMap = (Map) validationResult; + if (resultMap.containsKey("value")) { + Object value = resultMap.get("value"); + if (value instanceof Boolean) { + isValidationPassed = (Boolean) value; + } else if (value instanceof String) { + isValidationPassed = Boolean.parseBoolean((String) value); + } else if (value != null) { + isValidationPassed = Boolean.parseBoolean(value.toString()); + } + } + } else if (validationResult instanceof String) { + isValidationPassed = Boolean.parseBoolean((String) validationResult); + } + + System.out.println("AI Validation Result: " + isValidationPassed); + + // Standard TestNG assertion using the AI validation output + Assert.assertTrue(isValidationPassed, + "Article title should contain 'India' but validation failed"); + + System.out.println("Test completed successfully!"); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (driver != null) { + driver.quit(); + } + } +} diff --git a/app-automate/android/src/test/resources/com/browserstack/sample-local-test.testng.xml b/app-automate/android/src/test/resources/com/browserstack/sample-local-test.testng.xml new file mode 100644 index 0000000..49e888d --- /dev/null +++ b/app-automate/android/src/test/resources/com/browserstack/sample-local-test.testng.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app-automate/android/src/test/resources/com/browserstack/sample-test.testng.xml b/app-automate/android/src/test/resources/com/browserstack/sample-test.testng.xml new file mode 100644 index 0000000..b348da7 --- /dev/null +++ b/app-automate/android/src/test/resources/com/browserstack/sample-test.testng.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app-automate/ios/.gitignore b/app-automate/ios/.gitignore new file mode 100644 index 0000000..66117fc --- /dev/null +++ b/app-automate/ios/.gitignore @@ -0,0 +1,12 @@ +*.png +target/ +local.log +.idea +*.iml +**/logs/* +.DS_Store +build +gradle +.gradle +gradlew* +log \ No newline at end of file diff --git a/app-automate/ios/LocalSample.ipa b/app-automate/ios/LocalSample.ipa new file mode 100644 index 0000000..a937349 Binary files /dev/null and b/app-automate/ios/LocalSample.ipa differ diff --git a/app-automate/ios/browserstack.yml b/app-automate/ios/browserstack.yml new file mode 100644 index 0000000..5e4463d --- /dev/null +++ b/app-automate/ios/browserstack.yml @@ -0,0 +1,82 @@ +# ============================= +# Set BrowserStack Credentials +# ============================= +# Add your BrowserStack userName and accessKey here or set BROWSERSTACK_USERNAME and +# BROWSERSTACK_ACCESS_KEY as env variables +userName: vishalshivkumar_ECWceV +accessKey: CHwbbppxpBGZ5ypzTqxC + +# ====================== +# BrowserStack Reporting +# ====================== +# The following capabilities are used to set up reporting on BrowserStack: +# Set 'projectName' to the name of your project. Example, Marketing Website +projectName: BrowserStack Sample +# Set `buildName` as the name of the job / testsuite being run +buildName: Cross-Device Automation Agent - iOS +# `buildIdentifier` is a unique id to differentiate every execution that gets appended to +# buildName. Choose your buildIdentifier format from the available expressions: +# ${BUILD_NUMBER} (Default): Generates an incremental counter with every execution +# ${DATE_TIME}: Generates a Timestamp with every execution. Eg. 05-Nov-19:30 +# Read more about buildIdentifiers here -> https://www.browserstack.com/docs/automate/selenium/organize-tests +buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${expression} +# Set `framework` of your test suite. Example, `testng`, `cucumber`, `cucumber-testng` +# This property is needed to send test context to BrowserStack (test name, status) +framework: testng + +source: testng:appium-sample-sdk:v1.1 + +app: bs://ecb6354f5c66a78e20f70eceae8c63c990645248 +aiAuthoring: true + + +#app: ./LocalSample.ipa #For running local tests + +# ======================================= +# Platforms (Browsers / Devices to test) +# ======================================= +# Platforms object contains all the browser / device combinations you want to test on. +# Entire list available here -> (https://www.browserstack.com/list-of-browsers-and-platforms/automate) + +platforms: + # - deviceName: iPhone 14 Pro + # osVersion: 16 + # platformName: ios + # - deviceName: iPhone 13 Pro + # osVersion: 15 + # platformName: ios + - deviceName: iPhone 15 + osVersion: 17 + platformName: ios + +# ======================= +# Parallels per Platform +# ======================= +# The number of parallel threads to be used for each platform set. +# BrowserStack's SDK runner will select the best strategy based on the configured value +# +# Example 1 - If you have configured 3 platforms and set `parallelsPerPlatform` as 2, a total of 6 (2 * 3) parallel threads will be used on BrowserStack +# +# Example 2 - If you have configured 1 platform and set `parallelsPerPlatform` as 5, a total of 5 (1 * 5) parallel threads will be used on BrowserStack +parallelsPerPlatform: 1 + +# ========================================== +# BrowserStack Local +# (For localhost, staging/private websites) +# ========================================== +# Set browserStackLocal to true if your website under test is not accessible publicly over the internet +# Learn more about how BrowserStack Local works here -> https://www.browserstack.com/docs/automate/selenium/local-testing-introduction +browserstackLocal: true # (Default false) +#browserStackLocalOptions: +#Options to be passed to BrowserStack local in-case of advanced configurations +# localIdentifier: # (Default: null) Needed if you need to run multiple instances of local. +# forceLocal: true # (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel. +# Entire list of arguments available here -> https://www.browserstack.com/docs/automate/selenium/manage-incoming-connections + +# =================== +# Debugging features +# =================== +debug: false # # Set to true if you need screenshots for every selenium command ran +networkLogs: false # Set to true to enable HAR logs capturing +consoleLogs: errors # Remote browser's console debug levels to be printed (Default: errors) +# Available options are `disable`, `errors`, `warnings`, `info`, `verbose` (Default: errors) diff --git a/app-automate/ios/build.gradle b/app-automate/ios/build.gradle new file mode 100644 index 0000000..92de6d2 --- /dev/null +++ b/app-automate/ios/build.gradle @@ -0,0 +1,47 @@ +plugins { + id 'java' +} + +repositories { mavenCentral() } + +dependencies { + testImplementation 'org.testng:testng:7.5' + implementation 'org.seleniumhq.selenium:selenium-java:4.13.0' + implementation 'io.appium:java-client:8.6.0' + implementation 'commons-io:commons-io:2.11.0' + implementation 'com.googlecode.json-simple:json-simple:1.1.1' + implementation 'com.browserstack:browserstack-java-sdk:latest.release' +} + +group = 'com.browserstack' +version = '1.0-SNAPSHOT' +description = 'testng-browserstack' +sourceCompatibility = '1.8' + +def browserstackSDKArtifact = configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.find { it.name == 'browserstack-java-sdk' } + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + +tasks.withType(Test) { + systemProperties = System.properties +} + +task sampleTest(type: Test) { + useTestNG() { + dependsOn cleanTest + useDefaultListeners = true + suites "src/test/resources/com/browserstack/sample-test.testng.xml" + jvmArgs "-javaagent:${browserstackSDKArtifact.file}" + } +} + +task sampleLocalTest(type: Test) { + useTestNG() { + dependsOn cleanTest + useDefaultListeners = true + suites "src/test/resources/com/browserstack/sample-local-test.testng.xml" + jvmArgs "-javaagent:${browserstackSDKArtifact.file}" + } +} diff --git a/app-automate/ios/pom.xml b/app-automate/ios/pom.xml new file mode 100644 index 0000000..be9d229 --- /dev/null +++ b/app-automate/ios/pom.xml @@ -0,0 +1,127 @@ + + + 4.0.0 + + com.browserstack + testng-browserstack-ios + 1.0-SNAPSHOT + jar + + testng-browserstack + https://github.com/browserstack/testng-appium-app-browserstack + + + UTF-8 + 1.8 + 1.8 + 2.19.1 + 3.0.0-M5 + default + + + + + org.testng + testng + 7.5 + + + org.seleniumhq.selenium + selenium-java + 4.13.0 + + + io.appium + java-client + 8.6.0 + + + commons-io + commons-io + 2.11.0 + + + com.googlecode.json-simple + json-simple + 1.1.1 + + + com.browserstack + browserstack-java-sdk + LATEST + compile + + + + + + + maven-dependency-plugin + 3.3.0 + + + getClasspathFilenames + + properties + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + + src/test/resources/com/browserstack/sample-test.testng.xml + + -javaagent:${com.browserstack:browserstack-java-sdk:jar} + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + + + + + sample-test + + + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/com/browserstack/sample-test.testng.xml + + + + + + + + sample-local-test + + + + org.apache.maven.plugins + maven-surefire-plugin + + + src/test/resources/com/browserstack/sample-local-test.testng.xml + + + + + + + + diff --git a/app-automate/ios/settings.gradle b/app-automate/ios/settings.gradle new file mode 100644 index 0000000..e77c63f --- /dev/null +++ b/app-automate/ios/settings.gradle @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + mavenCentral() + mavenLocal() + gradlePluginPortal() + } + + resolutionStrategy { + eachPlugin { + if (requested.id.id == "com.browserstack.gradle-sdk") { + useModule("com.browserstack:gradle-sdk:1.1.2") + } + } + } +} +rootProject.name = 'testng-browserstack-ios' diff --git a/app-automate/ios/src/test/java/com/browserstack/AppiumTest.java b/app-automate/ios/src/test/java/com/browserstack/AppiumTest.java new file mode 100644 index 0000000..62cc181 --- /dev/null +++ b/app-automate/ios/src/test/java/com/browserstack/AppiumTest.java @@ -0,0 +1,85 @@ +package com.browserstack; + +import java.net.URL; +import java.util.Map; + +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.MutableCapabilities; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.options.XCUITestOptions; + + +public class AppiumTest { + + public IOSDriver driver; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + MutableCapabilities options = new XCUITestOptions(); + driver = new IOSDriver(new URL("https://hub-cloud.browserstack.com/wd/hub"),options); + System.out.println(driver); + } + + + @Test + public void sampleTest() throws Exception { + JavascriptExecutor jse = (JavascriptExecutor) driver; + + // AI Action 1: Select culture tab + System.out.println("Action 1: Select culture tab"); + jse.executeScript("browserstack_executor: {\"action\": \"ai\", \"arguments\": [\"Tap on culture tab from the top navigation bar\"]}"); + Thread.sleep(3000); // Wait for culture tab to load + + // AI Action 2: Extract the page heading + System.out.println("Action 2: Extract the page heading..."); + Object headingResult = jse.executeScript("browserstack_executor: {\"action\": \"ai\", \"arguments\": [\"Extract the main heading text displayed at the top of the page below the BBC logo\"]}"); + String extractedHeading = headingResult != null ? headingResult.toString() : ""; + System.out.println("Extracted Heading: " + extractedHeading); + Thread.sleep(3000); + + // AI Validation: Check if the page heading is Culture + System.out.println("Validation: Checking if the page heading is Culture"); + Object validationResult = jse.executeScript("browserstack_executor: {\"action\": \"ai\", \"arguments\": [\"Check if the main heading text at the top of the page is Culture\"]}"); + + // Convert AI validation result to boolean and assert + boolean isValidationPassed = false; + + if (validationResult instanceof Boolean) { + isValidationPassed = (Boolean) validationResult; + } else if (validationResult instanceof Map) { + // Check if result is an object with a "value" attribute + Map resultMap = (Map) validationResult; + if (resultMap.containsKey("value")) { + Object value = resultMap.get("value"); + if (value instanceof Boolean) { + isValidationPassed = (Boolean) value; + } else if (value instanceof String) { + isValidationPassed = Boolean.parseBoolean((String) value); + } else if (value != null) { + isValidationPassed = Boolean.parseBoolean(value.toString()); + } + } + } else if (validationResult instanceof String) { + isValidationPassed = Boolean.parseBoolean((String) validationResult); + } + + System.out.println("AI Validation Result: " + isValidationPassed); + + // Standard TestNG assertion using the AI validation output + Assert.assertTrue(isValidationPassed, + "Page heading should be Culture but validation failed"); + + System.out.println("Test completed successfully!"); + } + + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + driver.quit(); + } +} diff --git a/app-automate/ios/src/test/resources/com/browserstack/sample-local-test.testng.xml b/app-automate/ios/src/test/resources/com/browserstack/sample-local-test.testng.xml new file mode 100644 index 0000000..49e888d --- /dev/null +++ b/app-automate/ios/src/test/resources/com/browserstack/sample-local-test.testng.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/app-automate/ios/src/test/resources/com/browserstack/sample-test.testng.xml b/app-automate/ios/src/test/resources/com/browserstack/sample-test.testng.xml new file mode 100644 index 0000000..b348da7 --- /dev/null +++ b/app-automate/ios/src/test/resources/com/browserstack/sample-test.testng.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/automate/.gitignore b/automate/.gitignore new file mode 100644 index 0000000..6abef23 --- /dev/null +++ b/automate/.gitignore @@ -0,0 +1,13 @@ +*.png +target/ +local.log +.idea +*.iml +.gradle +build/ +.DS_Store +gradle +gradlew +gradlew.bat +log +browserstack.err diff --git a/README.md b/automate/README.md similarity index 100% rename from README.md rename to automate/README.md diff --git a/browserstack.yml b/automate/browserstack.yml similarity index 59% rename from browserstack.yml rename to automate/browserstack.yml index 9ecdb14..33757ad 100644 --- a/browserstack.yml +++ b/automate/browserstack.yml @@ -1,16 +1,16 @@ -userName: YOUR_USERNAME -accessKey: YOUR_ACCESS_KEY +userName: vishalshivkumar_ECWceV +accessKey: CHwbbppxpBGZ5ypzTqxC framework: true platforms: - os: Windows osVersion: 10 browserName: Chrome - browserVersion: 120.0 + browserVersion: latest browserstackLocal: true buildName: browserstack-AI agent authoring for Automate(Latest) projectName: BrowserStack Sample aiAuthoring: true # setting this capability to true will help in running browserstack NL Authoring commands - +interactiveDebugging: true # setting this capability to true will help in using BrowserStack Interactive Debugging feature diff --git a/build.gradle b/automate/build.gradle similarity index 100% rename from build.gradle rename to automate/build.gradle diff --git a/config/sample-local-test.testng.xml b/automate/config/sample-local-test.testng.xml similarity index 100% rename from config/sample-local-test.testng.xml rename to automate/config/sample-local-test.testng.xml diff --git a/config/sample-test.testng.xml b/automate/config/sample-test.testng.xml similarity index 100% rename from config/sample-test.testng.xml rename to automate/config/sample-test.testng.xml diff --git a/pom.xml b/automate/pom.xml similarity index 100% rename from pom.xml rename to automate/pom.xml diff --git a/src/test/java/com/browserstack/BstackAIAuthoring.java b/automate/src/test/java/com/browserstack/BstackAIAuthoring.java similarity index 100% rename from src/test/java/com/browserstack/BstackAIAuthoring.java rename to automate/src/test/java/com/browserstack/BstackAIAuthoring.java