diff --git a/.github/workflows/Semgrep.yml b/.github/workflows/Semgrep.yml new file mode 100644 index 0000000..95c5710 --- /dev/null +++ b/.github/workflows/Semgrep.yml @@ -0,0 +1,47 @@ +# Name of this GitHub Actions workflow. +name: Semgrep + +on: + # Scan changed files in PRs (diff-aware scanning): + # The branches below must be a subset of the branches above + pull_request: + branches: ["master", "main"] + push: + branches: ["master", "main"] + schedule: + - cron: '0 6 * * *' + + +permissions: + contents: read + +jobs: + semgrep: + # User definable name of this GitHub Actions job. + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + name: semgrep/ci + # If you are self-hosting, change the following `runs-on` value: + runs-on: ubuntu-latest + + container: + # A Docker image with Semgrep installed. Do not change this. + image: returntocorp/semgrep:1.166.0 + # Skip any PR created by dependabot to avoid permission issues: + if: (github.actor != 'dependabot[bot]') + + steps: + # Fetch project source with GitHub Actions Checkout. + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + # Run the "semgrep ci" command on the command line of the docker image. + - run: semgrep ci --sarif --output=semgrep.sarif + env: + # Add the rules that Semgrep uses by setting the SEMGREP_RULES environment variable. + SEMGREP_RULES: p/default # more at semgrep.dev/explore + + - name: Upload SARIF file for GitHub Advanced Security Dashboard + uses: github/codeql-action/upload-sarif@6c089f53dd51dc3fc7e599c3cb5356453a52ca9e # v2.20.0 + with: + sarif_file: semgrep.sarif + if: always() \ No newline at end of file diff --git a/.github/workflows/maven-workflow-run.yml b/.github/workflows/maven-workflow-run.yml new file mode 100644 index 0000000..19a0d5c --- /dev/null +++ b/.github/workflows/maven-workflow-run.yml @@ -0,0 +1,122 @@ +# This job is to test different maven profiles in sdk branch against full commit-id provided +# 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: TestNG 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: TestNG 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 mvn test for testng android + run: | + cd android/testng-examples + mvn compile + mvn test + - name: Run mvn profile sample-test for testng android + run: | + cd android/testng-examples + mvn compile + mvn test -P sample-test + - name: Run mvn profile sample-local-test for testng android + run: | + cd android/testng-examples + mvn compile + mvn test -P sample-local-test -D"browserstack.app"="./LocalSample.apk" + - name: Run Gradle sample-test for testng Android + run: | + cd android/testng-examples + gradle clean sampleTest + - name: Run Gradle sampleLocalTest for testng Android + run: | + cd android/testng-examples + gradle clean sampleLocalTest -D"browserstack.app"="./LocalSample.apk" + - name: Run mvn test for testng ios + run: | + cd ios/testng-examples + mvn compile + mvn test + - name: Run mvn profile sample-test for testng ios + run: | + cd ios/testng-examples + mvn compile + mvn test -P sample-test + - name: Run mvn profile sample-local-test for testng ios + run: | + cd ios/testng-examples + mvn compile + mvn test -P sample-local-test -D"browserstack.app"="./LocalSample.ipa" + - name: Run Gradle sample-test for testng ios + run: | + cd ios/testng-examples + gradle clean sampleTest + - name: Run Gradle sampleLocalTest for testng ios + run: | + cd ios/testng-examples + gradle clean sample-local-test -D"browserstack.app"="./LocalSample.ipa" + - if: always() + uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 + id: status-check-completed + env: + conclusion: ${{ job.status }} + job_name: TestNG 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 index aaf6345..f5c4409 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,9 @@ target/ local.log .idea *.iml -.DS_Store **/logs/* +.DS_Store +build +gradle +.gradle +gradlew* diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..ed09dd5 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @browserstack/app-automate-public-repos diff --git a/README.md b/README.md index 3a558c2..7abe9a0 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,14 @@ This repository demonstrates how to run Appium tests in [TestNG](http://testng.o - 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 +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 : @@ -42,7 +46,14 @@ 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) -- Run the following maven command `mvn test -P sample-test` +- **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 :** @@ -50,7 +61,18 @@ Getting Started with Appium tests in TestNg on BrowserStack couldn't be easier! ``` 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 and run the tests with the following command: `mvn test -P sample-local-test` +- 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) diff --git a/android/testng-examples/WikipediaSample.apk b/android/testng-examples/WikipediaSample.apk index 03d19e6..286e346 100644 Binary files a/android/testng-examples/WikipediaSample.apk and b/android/testng-examples/WikipediaSample.apk differ diff --git a/android/testng-examples/browserstack.yml b/android/testng-examples/browserstack.yml index 8451886..7975029 100644 --- a/android/testng-examples/browserstack.yml +++ b/android/testng-examples/browserstack.yml @@ -39,11 +39,11 @@ platforms: - deviceName: Samsung Galaxy S22 Ultra osVersion: 12.0 platformName: android - - deviceName: Samsung Galaxy S21 - osVersion: 11.0 + - deviceName: Google Pixel 8 Pro + osVersion: 14.0 platformName: android - - deviceName: Google Pixel 6 Pro - osVersion: 12.0 + - deviceName: OnePlus 11R + osVersion: 13.0 platformName: android # ======================= diff --git a/android/testng-examples/build.gradle b/android/testng-examples/build.gradle new file mode 100644 index 0000000..92de6d2 --- /dev/null +++ b/android/testng-examples/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/android/testng-examples/settings.gradle b/android/testng-examples/settings.gradle new file mode 100644 index 0000000..55607bd --- /dev/null +++ b/android/testng-examples/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/android/testng-examples/src/test/java/com/browserstack/FirstTest.java b/android/testng-examples/src/test/java/com/browserstack/FirstTest.java index 2a6ca7d..ad63a40 100644 --- a/android/testng-examples/src/test/java/com/browserstack/FirstTest.java +++ b/android/testng-examples/src/test/java/com/browserstack/FirstTest.java @@ -15,6 +15,10 @@ public class FirstTest extends AppiumTest { @Test public void test() throws Exception { + WebElement skipButton = (WebElement) new WebDriverWait(driver, Duration.ofSeconds(30)).until( + ExpectedConditions.presenceOfElementLocated(AppiumBy.id("org.wikipedia.alpha:id/fragment_onboarding_skip_button"))); + skipButton.click(); + WebElement searchElement = (WebElement) new WebDriverWait(driver, Duration.ofSeconds(30)).until( ExpectedConditions.elementToBeClickable(AppiumBy.accessibilityId("Search Wikipedia"))); diff --git a/ios/testng-examples/browserstack.yml b/ios/testng-examples/browserstack.yml index e190462..b66443d 100644 --- a/ios/testng-examples/browserstack.yml +++ b/ios/testng-examples/browserstack.yml @@ -36,14 +36,14 @@ app: ./BStackSampleApp.ipa # Entire list available here -> (https://www.browserstack.com/list-of-browsers-and-platforms/automate) platforms: - - deviceName: iPhone 14 Pro + - deviceName: iPhone 14 Pro Max osVersion: 16 platformName: ios - - deviceName: iPhone 13 Pro + - deviceName: iPhone 13 osVersion: 15 platformName: ios - - deviceName: iPhone XS - osVersion: 14 + - deviceName: iPhone 15 + osVersion: 17 platformName: ios # ======================= diff --git a/ios/testng-examples/build.gradle b/ios/testng-examples/build.gradle new file mode 100644 index 0000000..92de6d2 --- /dev/null +++ b/ios/testng-examples/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/ios/testng-examples/settings.gradle b/ios/testng-examples/settings.gradle new file mode 100644 index 0000000..e77c63f --- /dev/null +++ b/ios/testng-examples/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'