diff --git a/.github/workflows/maven-workflow-run.yml b/.github/workflows/maven-workflow-run.yml new file mode 100644 index 0000000..6eef44b --- /dev/null +++ b/.github/workflows/maven-workflow-run.yml @@ -0,0 +1,106 @@ +# This job is to test different maven profiles in sdk branch again Pull Request raised +# This workflow targets Java with Maven execution + +name: Java SDK Test workflow for Maven on workflow_dispatch + +on: + workflow_dispatch: + inputs: + commit_sha: + description: 'The full commit id to build' + required: true + +jobs: + comment-run: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + max-parallel: 3 + matrix: + java: [ '8', '11', '17' ] + os: [ 'macos-latest', 'windows-latest', 'ubuntu-latest' ] + name: Cucumber Appium Repo ${{ matrix.Java }} - ${{ matrix.os }} Sample + env: + BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} + BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.event.inputs.commit_sha }} + - uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 + id: status-check-in-progress + env: + job_name: Cucumber Appium Repo ${{ matrix.Java }} - ${{ matrix.os }} Sample + commit_sha: ${{ github.event.inputs.commit_sha }} + with: + github-token: ${{ github.token }} + script: | + const result = await github.rest.checks.create({ + owner: context.repo.owner, + repo: context.repo.repo, + name: process.env.job_name, + head_sha: process.env.commit_sha, + status: 'in_progress' + }).catch((err) => ({status: err.status, response: err.response})); + console.log(`The status-check response : ${result.status} Response : ${JSON.stringify(result.response)}`) + if (result.status !== 201) { + console.log('Failed to create check run') + } + - name: Set up Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: ${{ matrix.java }} + - name: Run android mvn test + run: | + cd android + mvn compile + mvn test + - name: Run android mvn profile sample-local-test + run: | + cd android + mvn compile + mvn test -P sample-local-test -D"browserstack.app"="./LocalSample.apk" + - name: Run android mvn profile sample-test + run: | + cd android + mvn compile + mvn test -P sample-test + - name: Run ios mvn test + run: | + cd ios + mvn compile + mvn test + - name: Run ios mvn profile sample-local-test + run: | + cd ios + mvn compile + mvn test -P sample-local-test -D"browserstack.app"="./LocalSample.ipa" + - name: Run ios mvn profile sample-test + run: | + cd ios + mvn compile + mvn test -P sample-test + - if: always() + uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 + id: status-check-completed + env: + conclusion: ${{ job.status }} + job_name: Cucumber Appium Repo ${{ matrix.Java }} - ${{ matrix.os }} Sample + commit_sha: ${{ github.event.inputs.commit_sha }} + with: + github-token: ${{ github.token }} + script: | + const result = await github.rest.checks.create({ + owner: context.repo.owner, + repo: context.repo.repo, + name: process.env.job_name, + head_sha: process.env.commit_sha, + status: 'completed', + conclusion: process.env.conclusion + }).catch((err) => ({status: err.status, response: err.response})); + console.log(`The status-check response : ${result.status} Response : ${JSON.stringify(result.response)}`) + if (result.status !== 201) { + console.log('Failed to create check run') + } diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ffe1d3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.png +target/ +local.log +.idea +*.iml +.DS_Store +**/logs/* +reports/ +logs/ diff --git a/README.md b/README.md index e615d10..e2d488a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,69 @@ # cucumber-java-appium-app-browserstack -This repository demonstrates how to run Appium tests in Cucumber Java on BrowserStack App Automate. + +This repository demonstrates how to run Appium tests in Cucumber Testng 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 + - 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) + +### Install the dependencies + +To install the dependencies for Android tests, run : +```sh +cd android/ +mvn clean +``` + +Or, + +To install the dependencies for iOS tests, run : + +```sh +cd ios/ +mvn clean +``` + +## Getting Started + +Getting Started with Appium tests in Cucumber TestNg on BrowserStack couldn't be easier! + +### **Run Sample test :** + +- Switch to one of the following directories: [Android examples](android) or [iOS examples](ios) +- Run the following maven command `mvn test -P sample-test` + +### **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) or [iOS examples](ios). + ``` + browserstackLocal: true + ``` +- You can use the `LocalSample` app provided in both folder [Android examples](android) or [iOS examples](ios) to run your test. Change the app parameter in the `browserstack.yml` file and run the tests with the following command: `mvn test -P sample-local-test` + + +**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/android/LocalSample.apk b/android/LocalSample.apk new file mode 100644 index 0000000..f31c574 Binary files /dev/null and b/android/LocalSample.apk differ diff --git a/android/WikipediaSample.apk b/android/WikipediaSample.apk new file mode 100644 index 0000000..03d19e6 Binary files /dev/null and b/android/WikipediaSample.apk differ diff --git a/android/browserstack.yml b/android/browserstack.yml new file mode 100644 index 0000000..bad55f6 --- /dev/null +++ b/android/browserstack.yml @@ -0,0 +1,76 @@ +# ============================= +# Set BrowserStack Credentials +# ============================= +# Add your BrowserStack userName and acccessKey here or set BROWSERSTACK_USERNAME and +# BROWSERSTACK_ACCESS_KEY as env variables +userName: BROWSERSTACK_USERNAME +accessKey: BROWSERSTACK_ACCESS_KEY + +# ====================== +# 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 Samples +# Set `buildName` as the name of the job / testsuite being run +buildName: browserstack build +# `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: cucumber-testng + +source: cucumber-java:appium-sample-main:v1.0 + +app: ./WikipediaSample.apk +# 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 + platformVersion: 12.0 + platformName: android + - deviceName: Samsung Galaxy S21 + platformVersion: 11.0 + platformName: android + - deviceName: Google Pixel 6 Pro + platformVersion: 12.0 + platformName: android + +# ======================= +# 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 diff --git a/android/pom.xml b/android/pom.xml new file mode 100644 index 0000000..8f530c7 --- /dev/null +++ b/android/pom.xml @@ -0,0 +1,156 @@ + + 4.0.0 + + com.browserstack + cucumber-java-appium-app-browserstack + 0.0.1-SNAPSHOT + jar + + cucumber-java-appium-app-browserstack + http://maven.apache.org + + + UTF-8 + 1.8 + 1.8 + 7.4.1 + 7.4.0 + 4.13.0 + 8.6.0 + 1.0.6 + 1.1.1 + LATEST + + + + + org.testng + testng + ${testng.version} + test + + + io.cucumber + cucumber-java + ${cucumber.version} + test + + + io.cucumber + cucumber-testng + ${cucumber.version} + test + + + org.seleniumhq.selenium + selenium-java + ${selenium-java.version} + test + + + io.appium + java-client + ${java-client.version} + + + com.browserstack + browserstack-java-sdk + ${browserstack-java-sdk.version} + compile + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 8 + 8 + + + + maven-dependency-plugin + + + getClasspathFilenames + + properties + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + src/test/resources/testng.xml + + + -javaagent:${com.browserstack:browserstack-java-sdk:jar} + + + true + src/test/resources/features/test + + + + + + + + sample-test + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + src/test/resources/testng.xml + + + -javaagent:${com.browserstack:browserstack-java-sdk:jar} + + + true + src/test/resources/features/test + + + + + + + + sample-local-test + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + src/test/resources/testng.xml + + + -javaagent:${com.browserstack:browserstack-java-sdk:jar} + + + true + src/test/resources/features/localtest + + + + + + + + + diff --git a/android/src/test/java/com/browserstack/RunWebDriverCucumberTests.java b/android/src/test/java/com/browserstack/RunWebDriverCucumberTests.java new file mode 100644 index 0000000..3be242f --- /dev/null +++ b/android/src/test/java/com/browserstack/RunWebDriverCucumberTests.java @@ -0,0 +1,15 @@ +package com.browserstack; + +import io.cucumber.testng.*; + +@CucumberOptions( + glue = "com.browserstack.stepdefs", + features = "src/test/resources/features/test", + plugin = { + "pretty", + "html:reports/tests/cucumber/cucumber-pretty.html", + "testng:reports/tests/cucumber/testng/cucumber.xml", + "json:reports/tests/cucumber/json/cucumberTestReport.json" + } +) +public class RunWebDriverCucumberTests extends AbstractTestNGCucumberTests {} diff --git a/android/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java b/android/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java new file mode 100644 index 0000000..77e8c27 --- /dev/null +++ b/android/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java @@ -0,0 +1,97 @@ +package com.browserstack.stepdefs; + +import io.appium.java_client.android.AndroidDriver; +import io.cucumber.java.After; +import io.cucumber.java.Before; +import io.cucumber.java.Scenario; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.apache.commons.io.FileUtils; +import org.openqa.selenium.*; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.time.Duration; +import java.util.HashMap; +import java.util.List; + +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; +import org.testng.Assert; +import io.appium.java_client.AppiumBy; + +public class StackDemoSteps { + private WebDriver driver; + + @Before + public void setUp() throws MalformedURLException { + MutableCapabilities capabilities = new MutableCapabilities(); + HashMap bstackOptions = new HashMap<>(); + bstackOptions.putIfAbsent("source", "cucumber-java:appium-sample-main:v1.0"); + capabilities.setCapability("bstack:options", bstackOptions); + driver = new AndroidDriver( + new URL("https://hub.browserstack.com/wd/hub"), capabilities); + } + + @Given("I try to search using Wikipedia App") + public void I_try_to_search_wikipedia_app() throws Throwable { + WebElement searchElement = (WebElement) new WebDriverWait(driver, Duration.ofSeconds(30)).until( + ExpectedConditions.elementToBeClickable(AppiumBy.accessibilityId("Search Wikipedia"))); + searchElement.click(); + } + + + @Then("I search with keyword BrowserStack") + public void I_search_with_keyword_browserstack() throws InterruptedException { + WebElement insertTextElement = (WebElement) new WebDriverWait(driver, Duration.ofSeconds(30)).until( + ExpectedConditions.elementToBeClickable(AppiumBy.id("org.wikipedia.alpha:id/search_src_text"))); + insertTextElement.sendKeys("BrowserStack"); + Thread.sleep(5000); + } + + @Then("The search results should be listed") + public void search_results_should_be_listed() { + List allProductsName = driver.findElements(AppiumBy.className("android.widget.TextView")); + Assert.assertTrue(allProductsName.size() > 0); + } + + @When("I start test on the Local Sample App") + public void I_start_test_on_the_local_sample_app() { + WebElement searchElement = (WebElement) new WebDriverWait(driver, Duration.ofSeconds(30)).until( + ExpectedConditions.elementToBeClickable(AppiumBy.id("com.example.android.basicnetworking:id/test_action"))); + searchElement.click(); + WebElement insertTextElement = (WebElement) new WebDriverWait(driver, Duration.ofSeconds(30)).until( + ExpectedConditions.elementToBeClickable(AppiumBy.className("android.widget.TextView"))); + } + + @Then("I should see {string}") + public void I_should_see(String localString) throws InterruptedException, IOException { + WebElement testElement = null; + List allTextViewElements = driver.findElements(AppiumBy.className("android.widget.TextView")); + Thread.sleep(10); + for (WebElement textElement : allTextViewElements) { + if (textElement.getText().contains("The active connection is")) { + testElement = textElement; + } + } + + if (testElement == null) { + File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); + FileUtils.copyFile(scrFile, new File(System.getProperty("user.dir") + "screenshot.png")); + System.out.println("Screenshot stored at " + System.getProperty("user.dir") + "screenshot.png"); + throw new Error("Cannot find the needed TextView element from app"); + } + String matchedString = testElement.getText(); + System.out.println(matchedString); + Assert.assertTrue(matchedString.contains("The active connection is wifi")); + Assert.assertTrue(matchedString.contains(localString)); + } + + @After + public void teardown(Scenario scenario) throws Exception { + Thread.sleep(2000); + driver.quit(); + } +} diff --git a/android/src/test/resources/features/localtest/Local.feature b/android/src/test/resources/features/localtest/Local.feature new file mode 100644 index 0000000..134fc19 --- /dev/null +++ b/android/src/test/resources/features/localtest/Local.feature @@ -0,0 +1,5 @@ +Feature: BrowserStack Local Testing + + Scenario: BStack Local Test - Can check tunnel working + When I start test on the Local Sample App + Then I should see "Up and running" diff --git a/android/src/test/resources/features/test/StackDemo.feature b/android/src/test/resources/features/test/StackDemo.feature new file mode 100644 index 0000000..c0f5a7a --- /dev/null +++ b/android/src/test/resources/features/test/StackDemo.feature @@ -0,0 +1,6 @@ +Feature: BrowserStack Demo + + Scenario: BStack Sample Test - Search BrowserStack + Given I try to search using Wikipedia App + Then I search with keyword BrowserStack + Then The search results should be listed diff --git a/android/src/test/resources/testng.xml b/android/src/test/resources/testng.xml new file mode 100644 index 0000000..28c168b --- /dev/null +++ b/android/src/test/resources/testng.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/ios/BStackSampleApp.ipa b/ios/BStackSampleApp.ipa new file mode 100644 index 0000000..c1891b8 Binary files /dev/null and b/ios/BStackSampleApp.ipa differ diff --git a/ios/LocalSample.ipa b/ios/LocalSample.ipa new file mode 100644 index 0000000..a937349 Binary files /dev/null and b/ios/LocalSample.ipa differ diff --git a/ios/browserstack.yml b/ios/browserstack.yml new file mode 100644 index 0000000..9730d8c --- /dev/null +++ b/ios/browserstack.yml @@ -0,0 +1,77 @@ +# ============================= +# Set BrowserStack Credentials +# ============================= +# Add your BrowserStack userName and accessKey here or set BROWSERSTACK_USERNAME and +# BROWSERSTACK_ACCESS_KEY as env variables +userName: BROWSERSTACK_USERNAME +accessKey: BROWSERSTACK_ACCESS_KEY + +# ====================== +# 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 Samples +# Set `buildName` as the name of the job / testsuite being run +buildName: browserstack build +# `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: cucumber-testng + +source: cucumber-java:appium-sample-main:v1.0 + +app: ./BStackSampleApp.ipa +#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 + platformVersion: 16 + platformName: ios + - deviceName: iPhone 13 Pro + platformVersion: 15 + platformName: ios + - deviceName: iPhone XS + platformVersion: 14 + 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 diff --git a/ios/pom.xml b/ios/pom.xml new file mode 100644 index 0000000..8f530c7 --- /dev/null +++ b/ios/pom.xml @@ -0,0 +1,156 @@ + + 4.0.0 + + com.browserstack + cucumber-java-appium-app-browserstack + 0.0.1-SNAPSHOT + jar + + cucumber-java-appium-app-browserstack + http://maven.apache.org + + + UTF-8 + 1.8 + 1.8 + 7.4.1 + 7.4.0 + 4.13.0 + 8.6.0 + 1.0.6 + 1.1.1 + LATEST + + + + + org.testng + testng + ${testng.version} + test + + + io.cucumber + cucumber-java + ${cucumber.version} + test + + + io.cucumber + cucumber-testng + ${cucumber.version} + test + + + org.seleniumhq.selenium + selenium-java + ${selenium-java.version} + test + + + io.appium + java-client + ${java-client.version} + + + com.browserstack + browserstack-java-sdk + ${browserstack-java-sdk.version} + compile + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 8 + 8 + + + + maven-dependency-plugin + + + getClasspathFilenames + + properties + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + src/test/resources/testng.xml + + + -javaagent:${com.browserstack:browserstack-java-sdk:jar} + + + true + src/test/resources/features/test + + + + + + + + sample-test + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + src/test/resources/testng.xml + + + -javaagent:${com.browserstack:browserstack-java-sdk:jar} + + + true + src/test/resources/features/test + + + + + + + + sample-local-test + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + src/test/resources/testng.xml + + + -javaagent:${com.browserstack:browserstack-java-sdk:jar} + + + true + src/test/resources/features/localtest + + + + + + + + + diff --git a/ios/src/test/java/com/browserstack/RunWebDriverCucumberTests.java b/ios/src/test/java/com/browserstack/RunWebDriverCucumberTests.java new file mode 100644 index 0000000..3be242f --- /dev/null +++ b/ios/src/test/java/com/browserstack/RunWebDriverCucumberTests.java @@ -0,0 +1,15 @@ +package com.browserstack; + +import io.cucumber.testng.*; + +@CucumberOptions( + glue = "com.browserstack.stepdefs", + features = "src/test/resources/features/test", + plugin = { + "pretty", + "html:reports/tests/cucumber/cucumber-pretty.html", + "testng:reports/tests/cucumber/testng/cucumber.xml", + "json:reports/tests/cucumber/json/cucumberTestReport.json" + } +) +public class RunWebDriverCucumberTests extends AbstractTestNGCucumberTests {} diff --git a/ios/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java b/ios/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java new file mode 100644 index 0000000..453a7e3 --- /dev/null +++ b/ios/src/test/java/com/browserstack/stepdefs/StackDemoSteps.java @@ -0,0 +1,97 @@ +package com.browserstack.stepdefs; + +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.options.XCUITestOptions; +import io.cucumber.java.After; +import io.cucumber.java.Before; +import io.cucumber.java.Scenario; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.apache.commons.io.FileUtils; +import org.openqa.selenium.*; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.time.Duration; +import java.util.HashMap; + +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; +import org.testng.Assert; +import io.appium.java_client.AppiumBy; + +public class StackDemoSteps { + private IOSDriver driver; + + @Before + public void setUp() throws MalformedURLException { + MutableCapabilities capabilities = new XCUITestOptions(); + HashMap bstackOptions = new HashMap<>(); + bstackOptions.putIfAbsent("source", "cucumber-java:appium-sample-main:v1.0"); + capabilities.setCapability("bstack:options", bstackOptions); + driver = new IOSDriver( + new URL("https://hub.browserstack.com/wd/hub"), capabilities); + } + + @Given("I try to find Text Button in Sample App") + public void I_try_to_find_text_sample_app() throws Throwable { + WebElement textButton = (WebElement) new WebDriverWait(driver, Duration.ofSeconds(30)).until( + ExpectedConditions.elementToBeClickable(AppiumBy.accessibilityId("Text Button"))); + textButton.click(); + } + + + @When("I type in 'hello@browserstack.com' in the Text Input field") + public void I_type_hello_text_input_field() throws InterruptedException { + WebElement textInput = (WebElement) new WebDriverWait(driver, Duration.ofSeconds(30)).until( + ExpectedConditions.elementToBeClickable(AppiumBy.accessibilityId("Text Input"))); + textInput.sendKeys("hello@browserstack.com"+"\n"); + Thread.sleep(5000); + } + + @Then("I should get the entered text in the Text Output field") + public void I_should_get_entered_text_in_text_output() { + WebElement textOutput = (WebElement) new WebDriverWait(driver, Duration.ofSeconds(30)).until( + ExpectedConditions.elementToBeClickable(AppiumBy.accessibilityId("Text Output"))); + Assert.assertEquals(textOutput.getText(),"hello@browserstack.com"); + } + + @When("I start test on the Local Sample App") + public void I_start_test_on_the_local_sample_app() { + WebElement testButton = (WebElement) new WebDriverWait(driver, Duration.ofSeconds(30)).until( + ExpectedConditions.elementToBeClickable(AppiumBy.accessibilityId("TestBrowserStackLocal"))); + testButton.click(); + WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); + wait.until(new ExpectedCondition() { + @Override + public Boolean apply(WebDriver d) { + String result = d.findElement(AppiumBy.accessibilityId("ResultBrowserStackLocal")).getAttribute("value"); + return result != null && result.length() > 0; + } + }); + } + + @Then("I should see {string}") + public void I_should_see(String localString) throws InterruptedException, IOException { + WebElement resultElement = (WebElement) driver.findElement(AppiumBy.accessibilityId("ResultBrowserStackLocal")); + + String resultString = resultElement.getText().toLowerCase(); + System.out.println(resultString); + if(resultString.contains("not working")) { + File scrFile = (File) ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); + FileUtils.copyFile(scrFile, new File(System.getProperty("user.dir") + "/screenshot.png")); + System.out.println("Screenshot stored at " + System.getProperty("user.dir") + "/screenshot.png"); + throw new Error("Unexpected BrowserStackLocal test result"); + } + Assert.assertTrue(resultString.contains(localString.toLowerCase())); + } + + @After + public void teardown(Scenario scenario) throws Exception { + Thread.sleep(2000); + driver.quit(); + } +} diff --git a/ios/src/test/resources/features/localtest/Local.feature b/ios/src/test/resources/features/localtest/Local.feature new file mode 100644 index 0000000..134fc19 --- /dev/null +++ b/ios/src/test/resources/features/localtest/Local.feature @@ -0,0 +1,5 @@ +Feature: BrowserStack Local Testing + + Scenario: BStack Local Test - Can check tunnel working + When I start test on the Local Sample App + Then I should see "Up and running" diff --git a/ios/src/test/resources/features/test/StackDemo.feature b/ios/src/test/resources/features/test/StackDemo.feature new file mode 100644 index 0000000..680a0c3 --- /dev/null +++ b/ios/src/test/resources/features/test/StackDemo.feature @@ -0,0 +1,6 @@ +Feature: BrowserStack test + + Scenario: BStack Sample Test - Verify if displayed text matches entered text + Given I try to find Text Button in Sample App + When I type in 'hello@browserstack.com' in the Text Input field + Then I should get the entered text in the Text Output field diff --git a/ios/src/test/resources/testng.xml b/ios/src/test/resources/testng.xml new file mode 100644 index 0000000..28c168b --- /dev/null +++ b/ios/src/test/resources/testng.xml @@ -0,0 +1,9 @@ + + + + + + + + +