diff --git a/.github/workflows/best-practice.yml b/.github/workflows/best-practice.yml
index 21605db7..209bcf7e 100644
--- a/.github/workflows/best-practice.yml
+++ b/.github/workflows/best-practice.yml
@@ -1,29 +1,32 @@
-# This workflow will build a Java project with Maven
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
-
name: Best Practices Tests
on:
+ schedule:
+ - cron: '35 22 * * *'
+ workflow_dispatch:
push:
branches: [ main ]
+ paths:
+ - '**/best-practice/**'
+ - 'pom.*'
pull_request:
+ paths:
+ - '**/best-practice/**'
+ - 'pom.*'
jobs:
build:
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ubuntu-latest]
+ runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
- - name: Set up JDK 1.8
- uses: actions/setup-java@v1
- with:
- java-version: 1.8
- - name: Run tests
- continue-on-error: true
- env:
- SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
- SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
- SCREENER_API_KEY: ${{ secrets.SCREENER_API_KEY }}
- run: mvn test -pl best-practice -Dtest=\!RealDevice* -X
\ No newline at end of file
+ - uses: actions/checkout@v4
+ - name: Set up Java
+ uses: actions/setup-java@v4
+ with:
+ java-version: 11
+ distribution: "temurin"
+ - name: Run tests
+ continue-on-error: true
+ env:
+ SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
+ SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
+ run: mvn test -pl best-practice
diff --git a/.github/workflows/gitpod.yml b/.github/workflows/gitpod.yml
new file mode 100644
index 00000000..cb5e6f18
--- /dev/null
+++ b/.github/workflows/gitpod.yml
@@ -0,0 +1,41 @@
+# This workflow will build a Java project with Maven
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Gitpod Tests Tests
+
+on:
+ schedule:
+ - cron: '35 21 * * *'
+ workflow_dispatch:
+ push:
+ branches: [ main ]
+ paths:
+ - '**/gitpod/**'
+ - 'pom.*'
+ pull_request:
+ paths:
+ - '**/gitpod/**'
+ - 'pom.*'
+
+jobs:
+ # appium
+ selenium:
+ runs-on: ubuntu-latest
+ container:
+ # !!!IMPORTANT!!! THIS MUST ALWAYS MATCH WHAT IS IN GITPOD.YML; SAUCE LABS CUSTOMERS RELY ON THIS!!!!:
+ image: maven:3.8.6-jdk-11
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Java
+ uses: actions/setup-java@v4
+ with:
+ java-version: 11
+ distribution: "temurin"
+ - name: Run tests
+ env:
+ SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
+ SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
+ BUILD: 'selenium-build-whatever'
+ BROWSER_NAME: chrome
+ # !!!IMPORTANT!!! THIS MUST ALWAYS MATCH WHAT IS IN GITPOD.YML; SAUCE LABS CUSTOMERS RELY ON THIS!!!!:
+ run: mvn test -pl gitpod
diff --git a/.github/workflows/junit4.yml b/.github/workflows/junit4.yml
index 58d3407a..cd850ee4 100644
--- a/.github/workflows/junit4.yml
+++ b/.github/workflows/junit4.yml
@@ -1,28 +1,46 @@
-# This workflow will build a Java project with Maven
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
-
name: JUnit 4 Tests
on:
+ schedule:
+ - cron: '35 23 * * *'
+ workflow_dispatch:
push:
branches: [ main ]
+ paths:
+ - '**/selenium-junit4-examples/**'
+ - 'pom.*'
pull_request:
+ paths:
+ - '**/selenium-junit4-examples/**'
+ - 'pom.*'
+
jobs:
+ formatting:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: axel-op/googlejavaformat-action@v3
+ with:
+ args: "--replace"
+ files: "selenium-junit4-examples/**/*.java"
+ skip-commit: true
+ - name: Print diffs
+ if: success() || failure()
+ run: git --no-pager diff --exit-code
+
build:
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ubuntu-latest]
+ runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
- - name: Set up JDK 1.8
- uses: actions/setup-java@v1
- with:
- java-version: 1.8
- - name: Run JUnit 4 Tests
- env:
- SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
- SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
- SCREENER_API_KEY: ${{ secrets.SCREENER_API_KEY }}
- run: mvn test -pl selenium-junit4-examples -X
+ - uses: actions/checkout@v4
+ - name: Set up Java
+ uses: actions/setup-java@v4
+ with:
+ java-version: 11
+ distribution: "temurin"
+ - name: Run JUnit 4 Tests
+ working-directory: ./selenium-junit4-examples
+ env:
+ SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
+ SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
+ run: mvn test
diff --git a/.github/workflows/mac-windows.yml b/.github/workflows/mac-windows.yml
deleted file mode 100644
index c6c0c94c..00000000
--- a/.github/workflows/mac-windows.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-# This workflow will build a Java project with Maven
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
-
-name: Windows and Mac OS tests
-
-on:
- push:
- branches: [ main ]
- pull_request:
-
-jobs:
- build:
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [windows-latest, macos-latest]
- steps:
- - uses: actions/checkout@v2
- - name: Set up JDK 1.8
- uses: actions/setup-java@v1
- with:
- java-version: 1.8
- - name: Run tests
- continue-on-error: true
- env:
- SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
- SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
- SCREENER_API_KEY: ${{ secrets.SCREENER_API_KEY }}
- run: mvn test -pl best-practice -Dtest=DesktopTests* -X
\ No newline at end of file
diff --git a/.github/workflows/playwright-examples.yml b/.github/workflows/playwright-examples.yml
new file mode 100644
index 00000000..fcdfb875
--- /dev/null
+++ b/.github/workflows/playwright-examples.yml
@@ -0,0 +1,46 @@
+name: Playwright JUnit 5 Tests
+
+on:
+ schedule:
+ - cron: '50 21 * * *'
+ workflow_dispatch:
+ push:
+ branches: [ main ]
+ paths:
+ - '**/playwright-examples/**'
+ - 'pom.*'
+ pull_request:
+ paths:
+ - '**/playwright-examples/**'
+ - 'pom.*'
+
+jobs:
+ formatting:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: axel-op/googlejavaformat-action@v3
+ with:
+ args: "--replace"
+ files: "playwright-examples/**/*.java"
+ skip-commit: true
+ - name: Print diffs
+ if: success() || failure()
+ run: git --no-pager diff --exit-code
+
+
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Java
+ uses: actions/setup-java@v4
+ with:
+ java-version: 11
+ distribution: "temurin"
+ - name: Run JUnit 5 tests
+ working-directory: ./playwright-examples
+ env:
+ SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
+ SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
+ run: mvn test
diff --git a/.github/workflows/real-devices.yml b/.github/workflows/real-devices.yml
index d110dfe7..78bce1ed 100644
--- a/.github/workflows/real-devices.yml
+++ b/.github/workflows/real-devices.yml
@@ -1,11 +1,18 @@
-# This workflow will build a Java project with Maven
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
name: Real Devices
on:
+ schedule:
+ - cron: '35 20 * * *'
+ workflow_dispatch:
push:
branches: [ main ]
+ paths:
+ - '**/appium/**'
+ - 'pom.*'
pull_request:
+ paths:
+ - '**/appium/**'
+ - 'pom.*'
env:
SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
@@ -16,14 +23,15 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
- os: [ubuntu-latest]
+ os: [ ubuntu-latest ]
steps:
- - uses: actions/checkout@v2
- - name: Set up JDK 1.8
- uses: actions/setup-java@v1
- with:
- java-version: 1.8
- - name: RDC Native App Android
- run: mvn test -pl appium/appium-app/appium-app-examples -Dtest=AndroidNativeAppTest -Dregion=eu -X
- - name: RDC Native App IOS
- run: mvn test -pl appium/appium-app/appium-app-examples -Dtest=IOSNativeAppTest -Dregion=eu -X
+ - uses: actions/checkout@v4
+ - name: Set up Java
+ uses: actions/setup-java@v4
+ with:
+ java-version: 11
+ distribution: "temurin"
+ - name: RDC Native App Android
+ run: mvn test -pl appium/appium-app/appium-app-examples -Dtest=AndroidNativeAppTest -Dregion=eu
+ - name: RDC Native App IOS
+ run: mvn test -pl appium/appium-app/appium-app-examples -Dtest=IOSNativeAppTest -Dregion=eu
diff --git a/.github/workflows/selenium-cucumber-examples.yml b/.github/workflows/selenium-cucumber-examples.yml
index f5a50f85..bedf11d0 100644
--- a/.github/workflows/selenium-cucumber-examples.yml
+++ b/.github/workflows/selenium-cucumber-examples.yml
@@ -1,27 +1,34 @@
-# This workflow will build a Java project with Maven
-# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
-
name: Cucumber Tests
on:
+ schedule:
+ - cron: '35 19 * * *'
+ workflow_dispatch:
push:
branches: [ main ]
+ paths:
+ - '**/selenium-cucumber-examples/**'
+ - 'pom.*'
pull_request:
+ paths:
+ - '**/selenium-cucumber-examples/**'
+ - 'pom.*'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
- os: [ubuntu-latest]
+ os: [ ubuntu-latest ]
steps:
- - uses: actions/checkout@v2
- - name: Set up JDK 1.8
- uses: actions/setup-java@v1
- with:
- java-version: 1.8
- - name: Run tests
- env:
- SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
- SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
- run: mvn test -pl selenium-cucumber-examples -X
+ - uses: actions/checkout@v4
+ - name: Set up Java
+ uses: actions/setup-java@v4
+ with:
+ java-version: 11
+ distribution: "temurin"
+ - name: Run tests
+ env:
+ SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
+ SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
+ run: mvn test -pl selenium-cucumber-examples -X
diff --git a/.github/workflows/selenium-examples.yml b/.github/workflows/selenium-examples.yml
index 2dd5a065..ba69c6ab 100644
--- a/.github/workflows/selenium-examples.yml
+++ b/.github/workflows/selenium-examples.yml
@@ -4,24 +4,46 @@
name: Selenium JUnit 5 Tests
on:
+ schedule:
+ - cron: '50 23 * * *'
+ workflow_dispatch:
push:
branches: [ main ]
+ paths:
+ - '**/selenium-examples/**'
+ - 'pom.*'
pull_request:
+ paths:
+ - '**/selenium-examples/**'
+ - 'pom.*'
jobs:
+ formatting:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: axel-op/googlejavaformat-action@v3
+ with:
+ args: "--replace"
+ files: "selenium-examples/**/*.java"
+ skip-commit: true
+ - name: Print diffs
+ if: success() || failure()
+ run: git --no-pager diff --exit-code
+
+
build:
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ubuntu-latest]
+ runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
- - name: Set up JDK 1.8
- uses: actions/setup-java@v1
- with:
- java-version: 1.8
- - name: Run tests
- env:
- SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
- SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
- run: mvn test -pl selenium-examples -X
+ - uses: actions/checkout@v4
+ - name: Set up Java
+ uses: actions/setup-java@v4
+ with:
+ java-version: 11
+ distribution: "temurin"
+ - name: Run JUnit 5 tests
+ working-directory: ./selenium-examples
+ env:
+ SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
+ SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
+ run: mvn test
diff --git a/.github/workflows/testng.yml b/.github/workflows/testng.yml
index 45285b24..ccd8d2a5 100644
--- a/.github/workflows/testng.yml
+++ b/.github/workflows/testng.yml
@@ -4,24 +4,34 @@
name: TestNg Tests
on:
+ schedule:
+ - cron: '50 22 * * *'
+ workflow_dispatch:
push:
branches: [ main ]
+ paths:
+ - '**/selenium-testng-examples/**'
+ - 'pom.*'
pull_request:
+ paths:
+ - '**/selenium-testng-examples/**'
+ - 'pom.*'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
- os: [ubuntu-latest]
+ os: [ ubuntu-latest ]
steps:
- - uses: actions/checkout@v2
- - name: Set up JDK 1.8
- uses: actions/setup-java@v1
- with:
- java-version: 1.8
- - name: Run testng tests
- env:
- SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
- SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
- run: mvn test -pl selenium-testng-examples -X
+ - uses: actions/checkout@v4
+ - name: Set up Java
+ uses: actions/setup-java@v4
+ with:
+ java-version: 11
+ distribution: "temurin"
+ - name: Run testng tests
+ env:
+ SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
+ SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
+ run: mvn test -pl selenium-testng-examples
diff --git a/.github/workflows/upload_my_demo_app.yml b/.github/workflows/upload_my_demo_app.yml
new file mode 100644
index 00000000..722aec13
--- /dev/null
+++ b/.github/workflows/upload_my_demo_app.yml
@@ -0,0 +1,60 @@
+name: Upload My Demo App monthly
+
+on:
+ workflow_call:
+ workflow_dispatch:
+ schedule:
+ - cron: '0 19 * * *'
+
+env:
+ SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
+ SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
+
+jobs:
+ upload_android:
+ name: Upload My Demo App Android
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ datacenter: [ eu-central-1, us-west-1 ]
+ steps:
+ - name: Download My Demo App Android
+ uses: wei/curl@v1.1.1
+ with:
+ args: -L -o SauceLabs-Demo-App.apk https://github.com/saucelabs/my-demo-app-android/releases/download/2.0.2/mda-2.0.2-23.apk
+ - name: Upload My Demo App Android
+ uses: wei/curl@v1.1.1
+ with:
+ args: -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" --location --request POST 'https://api.${{ matrix.datacenter }}.saucelabs.com/v1/storage/upload' --form 'payload=@"SauceLabs-Demo-App.apk"' --form 'name="SauceLabs-Demo-App.apk"'
+
+ download_ios_zip:
+ name: Upload My Demo App iOS zip
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ datacenter: [ eu-central-1, us-west-1 ]
+ steps:
+ - name: Download My Demo App iOS zip
+ uses: wei/curl@v1.1.1
+ with:
+ args: -L -o SauceLabs-Demo-App.Simulator.zip https://github.com/saucelabs/my-demo-app-ios/releases/download/2.0.2/SauceLabs-Demo-App.Simulator.zip
+ - name: Upload My Demo App iOS zip
+ uses: wei/curl@v1.1.1
+ with:
+ args: -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" --location --request POST 'https://api.${{ matrix.datacenter }}.saucelabs.com/v1/storage/upload' --form 'payload=@"SauceLabs-Demo-App.Simulator.zip"' --form 'name="SauceLabs-Demo-App.Simulator.zip"'
+
+ download_ios_ipa:
+ name: Upload My Demo App iOS ipa
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ datacenter: [ eu-central-1, us-west-1 ]
+ steps:
+ - name: Download My Demo App iOS ipa
+ uses: wei/curl@v1.1.1
+ with:
+ args: -L -o SauceLabs-Demo-App.ipa https://github.com/saucelabs/my-demo-app-ios/releases/download/2.0.2/SauceLabs-Demo-App.ipa
+ - name: Upload My Demo App iOS ipa
+ uses: wei/curl@v1.1.1
+ with:
+ args: -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" --location --request POST 'https://api.${{ matrix.datacenter }}.saucelabs.com/v1/storage/upload' --form 'payload=@"SauceLabs-Demo-App.ipa"' --form 'name="SauceLabs-Demo-App.ipa"'
diff --git a/.gitpod.yml b/.gitpod.yml
index 1c2612b6..422d260a 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -1,5 +1,5 @@
# List the start up tasks. Learn more: https://www.gitpod.io/docs/configure/workspaces/tasks
-image: maven:3.6.3-jdk-8
+image: maven:3.6.3-jdk-11
tasks:
- name: Script Task
init: |
diff --git a/README.md b/README.md
index bc8f0515..b4fc6319 100644
--- a/README.md
+++ b/README.md
@@ -1,135 +1,149 @@
# Java Demonstration Scripts
-Welcome to Java Demo Scripts designed by Solution Architects to provide examples of how to use Sauce Labs technologies. This repository contains
-everything that you need to get started with web, mobile, visual, functional and all other types of automation using Java.
+Welcome to Java Demo Scripts, a set of examples showing how to use Sauce
+Labs technologies. This repository contains everything you need to start with
+web, mobile, functional, and all other types of
+Java automation.
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
-[![Codacy Badge](https://api.codacy.com/project/badge/Grade/564ddfb012db40048781b7b6c954d099)](https://app.codacy.com/gh/saucelabs-training/demo-java?utm_source=github.com&utm_medium=referral&utm_content=saucelabs-training/demo-java&utm_campaign=Badge_Grade_Dashboard)
+
[![Best Practices Tests](https://github.com/saucelabs-training/demo-java/actions/workflows/best-practice.yml/badge.svg)](https://github.com/saucelabs-training/demo-java/actions/workflows/best-practice.yml)
-[![Selenium JUnit 5 Tests](https://github.com/saucelabs-training/demo-java/actions/workflows/selenium-examples.yml/badge.svg)](https://github.com/saucelabs-training/demo-java/actions/workflows/selenium-examples.yml)
+
+[![JUnit 5 Tests](https://github.com/saucelabs-training/demo-java/actions/workflows/selenium-examples.yml/badge.svg)](https://github.com/saucelabs-training/demo-java/actions/workflows/selenium-examples.yml)
+
[![JUnit 4 Tests](https://github.com/saucelabs-training/demo-java/actions/workflows/junit4.yml/badge.svg)](https://github.com/saucelabs-training/demo-java/actions/workflows/junit4.yml)
+
[![TestNg Tests](https://github.com/saucelabs-training/demo-java/actions/workflows/testng.yml/badge.svg)](https://github.com/saucelabs-training/demo-java/actions/workflows/testng.yml)
-[![Selenium Cucumber Examples](https://github.com/saucelabs-training/demo-java/actions/workflows/cucumber.yml/badge.svg)](https://github.com/saucelabs-training/demo-java/actions/workflows/cucumber.yml)
+
+[![Cucumber Tests](https://github.com/saucelabs-training/demo-java/actions/workflows/selenium-cucumber-examples.yml/badge.svg)](https://github.com/saucelabs-training/demo-java/actions/workflows/selenium-cucumber-examples.yml)
+
[![Real Devices](https://github.com/saucelabs-training/demo-java/actions/workflows/real-devices.yml/badge.svg)](https://github.com/saucelabs-training/demo-java/actions/workflows/real-devices.yml)
## 🥇Most Popular
-* [Web automation best practices framework with multiple testing strategies. Crafted by industry experts with decades of experience.](./best-practice/)
-* [Quick start test, Junit 5](./selenium-examples/src/test/java/com/saucedemo/selenium/demo/SeleniumTest.java)
-* [Quick start test, Junit 4](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SeleniumTest.java)
-* [Quick start test, TestNg](./selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SeleniumTest.java)
-* [iOS real device, native app, Junit4](./appium-examples/src/test/java/com/appium_app/simple_example/IOSNativeAppTest.java)
-* [Front-end performance testing](./selenium-examples/src/test/java/com/saucedemo/selenium/PerformanceTest.java)
-* [Visual E2E test](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SimpleVisualE2ETest.java)
-* [Sauce Connect usage](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SauceConnectTest.java)
+
+* [Best practices with multiple testing strategies](./best-practice/)
+* [Quick start test, Junit 5](./selenium-examples/src/test/java/com/saucedemo/selenium/demo/SeleniumTest.java)
+* [Quick start test, Junit 4](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SeleniumTest.java)
+* [Quick start test, TestNg](./selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SeleniumTest.java)
+* [iOS real device, native app, Junit4](./appium-examples/src/test/java/com/appium_app/simple_example/IOSNativeAppTest.java)
+* [Front-end performance testing](./selenium-examples/src/test/java/com/saucedemo/selenium/PerformanceTest.java)
+* [Visual E2E test](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SimpleVisualE2ETest.java)
+* [Sauce Connect usage](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SauceConnectTest.java)
## Best Practices
-* [Desktop](./best-practice/src/test/java/com/saucedemo/tests/DesktopTests.java) `junit4` `sauce-bindings`
-* [Emu/Sim Web](./best-practice/src/test/java/com/saucedemo/tests/EmuSimWebAppTests.java) `junit4` `sauce-bindings`
-* [Performance](./best-practice/src/test/java/com/saucedemo/tests/PerformanceTests.java) `junit4` `sauce-bindings`
-* [RealDevice](./best-practice/src/test/java/com/saucedemo/tests/RealDeviceWebTests.java) `junit4` `sauce-bindings`
-* [Visual E2E](./best-practice/src/test/java/com/saucedemo/tests/VisualCrossPlatformTests.java) `junit4` `sauce-bindings`
+
+* [Desktop](./best-practice/src/test/java/com/saucedemo/tests/DesktopTests.java) `junit4` `sauce-bindings`
+* [Emu/Sim Web](./best-practice/src/test/java/com/saucedemo/tests/EmuSimWebAppTests.java) `junit4` `sauce-bindings`
+* [Performance](./best-practice/src/test/java/com/saucedemo/tests/PerformanceTests.java) `junit4` `sauce-bindings`
+* [RealDevice](./best-practice/src/test/java/com/saucedemo/tests/RealDeviceWebTests.java) `junit4` `sauce-bindings`
## đź–ĄWeb automation
- Sauce Bindings With TestRunner Examples
- * [Junit 5](./selenium-examples/src/test/java/com/saucedemo/selenium/demo/SaucebindingsJunitTest.java) `junit5` `sauce-bindings`
- * [Junit 4](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SauceBindingsJunit4Test.java) `junit4` `sauce-bindings`
- * [TestNg](./selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTestngTest.java) `testng` `sauce-bindings`
+ * [Junit 5](./selenium-examples/src/test/java/com/saucedemo/selenium/demo/SaucebindingsJunitTest.java) `junit5` `sauce-bindings`
+ * [Junit 4](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SauceBindingsJunit4Test.java) `junit4` `sauce-bindings`
+ * [TestNg](./selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTestngTest.java) `testng` `sauce-bindings`
- Sauce Bindings Examples
- * [Junit 5](./selenium-examples/src/test/java/com/saucedemo/selenium/demo/SauceBindingsTest.java) `junit4` `sauce-bindings`
- * [Junit 4](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SauceBindingsTest.java) `junit4` `sauce-bindings`
- * [TestNg](./selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTest.java) `junit4` `sauce-bindings`
+ * [Junit 5](./selenium-examples/src/test/java/com/saucedemo/selenium/demo/SauceBindingsTest.java) `junit4` `sauce-bindings`
+ * [Junit 4](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SauceBindingsTest.java) `junit4` `sauce-bindings`
+ * [TestNg](./selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTest.java) `junit4` `sauce-bindings`
- Selenium Examples
- * [Accessibility Test with Sauce Bindings](/selenium-examples/src/test/java/com/saucedemo/selenium/accessibility/SauceBindingsTest.java) `junit4` `sauce-bindings`
- * [Accessibility Test with Deque Axe](/selenium-examples/src/test/java/com/saucedemo/selenium/accessibility/DequeAxeTest.java) `junit4`
- * [Cucumber web test](./selenium-cucumber-examples/src/test/java/com/saucedemo/selenium/cucumber/RunTestsAT.java)
- * [Windows authentication](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/WindowsAuthentication.java) `junit4`
- * [Cross Browser/Platform in Parallel w/ TestNG](./selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/CrossBrowserPlatformTest.java) `testng`
- * [Performance, front-end with Sauce Bindings](/selenium-examples/src/test/java/com/saucedemo/selenium/PerformanceTest.java) `junit5` `sauce-bindings`
- * [Single Browser in Parallel w/ TestNG](./selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/ParallelSingleBrowserTest.java) `testng`
- * [Visual e2e test](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SimpleVisualE2ETest.java) `visual` `junit4`
- * [Visual e2e test with branching strategy](./blob/54a4bfde9040d71f88f3b3aff79a047474d01be9/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SimpleVisualE2ETest.java#L115-L158) `visual` `junit4`
+ * [Accessibility Test with Sauce Bindings](/selenium-examples/src/test/java/com/saucedemo/selenium/accessibility/SauceBindingsTest.java) `junit4` `sauce-bindings`
+ * [Accessibility Test with Deque Axe](/selenium-examples/src/test/java/com/saucedemo/selenium/accessibility/DequeAxeTest.java) `junit4`
+ * [Cucumber web test](./selenium-cucumber-examples/src/test/java/com/saucedemo/selenium/cucumber/RunTestsAT.java)
+ * [Windows authentication](./selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/WindowsAuthentication.java) `junit4`
+ * [Cross Browser/Platform in Parallel w/ TestNG](./selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/CrossBrowserPlatformTest.java) `testng`
+ * [Performance, front-end with Sauce Bindings](/selenium-examples/src/test/java/com/saucedemo/selenium/PerformanceTest.java) `junit5` `sauce-bindings`
+ * [Single Browser in Parallel w/ TestNG](./selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/ParallelSingleBrowserTest.java) `testng`
## 📱Mobile automation
[đź“š Mobile Testing Training Tutorials](./TRAINING.md)
- Real Devices
- * [iOS native app](./appium-examples/src/test/java/com/appium_app/simple_example/IOSNativeAppTest.java)
- * [Android native app](./appium-examples/src/test/java/com/appium_app/simple_example/AndroidNativeAppTest.java)
- * [Upload app to Sauce Storage](./appium-examples/src/test/java/com/helpers/push_apps_to_storage.sh)
- * [Image Injection](./appium-examples/src/test/java/com/appium_app/image_injection)
- * [Biometric Login](./appium-examples/src/test/java/com/appium_app/biometric_login)
- * [Cucumber w/ Appium](./appium-junit4-cucumber-examples/src/test/resources/LoginPage.feature) `junit4` `cucumber`
+ * [iOS native app](./appium-examples/src/test/java/com/appium_app/simple_example/IOSNativeAppTest.java)
+ * [Android native app](./appium-examples/src/test/java/com/appium_app/simple_example/AndroidNativeAppTest.java)
+ * [Upload app to Sauce Storage](./appium-examples/src/test/java/com/helpers/push_apps_to_storage.sh)
+ * [Image Injection](./appium-examples/src/test/java/com/appium_app/image_injection)
+ * [Biometric Login](./appium-examples/src/test/java/com/appium_app/biometric_login)
+ * [Cucumber w/ Appium](./appium-junit4-cucumber-examples/src/test/resources/LoginPage.feature) `junit4` `cucumber`
- Emulators and Simulators
- * [iOS native app](./appium-examples/src/test/java/com/appium_app/simple_example/IOSNativeAppTest.java)
- * [Android native app](./appium-examples/src/test/java/com/appium_app/simple_example/AndroidNativeAppTest.java)
- * [Biometric Login](./appium-examples/src/test/java/com/appium_app/biometric_login)
+ * [iOS native app](./appium-examples/src/test/java/com/appium_app/simple_example/IOSNativeAppTest.java)
+ * [Android native app](./appium-examples/src/test/java/com/appium_app/simple_example/AndroidNativeAppTest.java)
+ * [Biometric Login](./appium-examples/src/test/java/com/appium_app/biometric_login)
## ⚙️Setup
-* Install [Git](https://github.com/saucelabs-training/demo-java/blob/main/docs/prerequisites.md#install-git)
-* Install [IntelliJ (or another IDE)](https://github.com/saucelabs-training/demo-java/blob/main/docs/prerequisites.md#install-intellij)
-* Install [JDK](https://github.com/saucelabs-training/demo-java/blob/main/docs/prerequisites.md#install-the-jdk)
-* Install [Maven](https://github.com/saucelabs-training/demo-java/blob/main/docs/prerequisites.md#install-maven)
+* Install [Git](https://github.com/saucelabs-training/demo-java/blob/main/docs/prerequisites.md#install-git)
+
+* Install [IntelliJ (or another IDE)](https://github.com/saucelabs-training/demo-java/blob/main/docs/prerequisites.md#install-intellij)
+
+* Install [JDK](https://github.com/saucelabs-training/demo-java/blob/main/docs/prerequisites.md#install-the-jdk)
+
+* Install [Maven](https://github.com/saucelabs-training/demo-java/blob/main/docs/prerequisites.md#install-maven)
### Import the Project
1. Create a directory on your machine.
-2. Clone this repository into said directory.
+2. Clone this repository into the said directory.
```
$ git clone https://github.com/saucelabs-training/demo-java.git
```
-3. Import the project into your IntelliJ (or IDE of your choice) as a **Maven Project**.
+3. Import the project into IntelliJ (or the IDE of your choice) as a Maven Project.
4. Click through the prompts, and confirm when it asks to **Import from Sources**
5. Choose the **demo-java** directory as the **root** directory of the project.
### Set Your Sauce Labs Credentials
-1. Copy your Sauce Labs **username** and **accessKey** in the [User Settings](https://app.saucelabs.com/user-settings) section of the [Sauce Labs Dashboard](https://app.saucelabs.com/dashboard/builds).
-2. Open a Terminal window (command prompt for Windows) and set your Sauce Labs Environment variables:
+
+1. Copy your Sauce Labs **username** and **accessKey** in
+ the [User Settings](https://app.saucelabs.com/user-settings) section of
+ the [Sauce Labs Dashboard](https://app.saucelabs.com/dashboard/builds).
+2. Open a Terminal window (command prompt for Windows) and set your Sauce Labs Environment
+ variables:
**Mac OSX:**
```
$ export SAUCE_USERNAME="your username"
$ export SAUCE_ACCESS_KEY="your accessKey"
- $ export SCREENER_API_KEY="your screener key"
```
**Windows:**
```
> set SAUCE_USERNAME="username"
> set SAUCE_ACCESS_KEY="accessKey"
- > set SCREENER_API_KEY="your screener key"
```
- > To set an environment variables permanently in Windows, you must append it to the `PATH` variable.
-
- > Go to **Control Panel > System > Windows version > Advanced System Settings > Environment Variables > System Variables > Edit > New**
-
+ > To set an environment variable permanently in Windows, you must append it to the `PATH`
+ variable.
+
+ > Go to **Control Panel > System > Windows version > Advanced System Settings > Environment
+ Variables > System Variables > Edit > New**
+
> Then set the "Name" and "Value" for each variable
-
+
3. Test the environment variables
- **Mac OSX:**
+ **Mac OSX:**
```
$ echo $SAUCE_USERNAME
$ echo $SAUCE_ACCESS_KEY
```
- ***WARNING FOR UNIX USERS!***
-
- *If you have problems setting your environment variables, run the following commands in your terminal:*
+ ***WARNING FOR UNIX USERS!***
+
+ *If you have problems setting your environment variables, run the following commands in your
+ terminal:*
```
$ launchctl setenv SAUCE_USERNAME $SAUCE_USERNAME
$ launchctl setenv SAUCE_ACCESS_KEY $SAUCE_ACCESS_KEY
```
- **Windows:**
+ **Windows:**
```
> echo %SAUCE_USERNAME%
> echo %SAUCE_ACCESS_KEY%
@@ -150,18 +164,27 @@ everything that you need to get started with web, mobile, visual, functional and
$ mvn test -pl best-practice -Dtest=DesktopTests
```
-
- You can run different tests from different modules. Check out some examples by looking at the [CI YML files](./.github/workflows)
-## Contributing
+ You can run different tests from different modules. Check out some examples by looking at
+ the [CI YML files](./.github/workflows)
-This repository is maintained by the Solutions Architect team at Sauce Labs. **We welcome all ideas and contributions!**
+## Contributing
-Guidance for contributing can be found [here](./CONTRIBUTING.md)
+Sauce Labs maintains this repository. **We welcome all ideas
+and contributions!**
+Guidance for contributing can be found [here](./CONTRIBUTING.md)
## Disclaimer
-> The code in these scripts is provided on an "AS-IS" basis without warranty of any kind, either express or implied, including without limitation any implied warranties of condition, uninterrupted use, merchantability, fitness for a particular purpose, or non-infringement. These scripts are provided for educational and demonstration purposes only, and should not be used in production. Issues regarding these scripts should be submitted through GitHub. These scripts are maintained by the Technical Services team at Sauce Labs.
+> The code in these scripts is provided on an "AS-IS" basis without warranty of any kind, either
+> express or implied, including without limitation any implied warranties of condition,
+> uninterrupted
+> use, merchantability, fitness for a particular purpose, or non-infringement. These scripts are
+> provided for educational and demonstration purposes only and should not be used in production.
+> Issues regarding these scripts should be submitted through GitHub. These scripts are maintained by
+> the Technical Services team at Sauce Labs.
>
-> Some examples in this repository, such as `appium-example`, `parallel-testing`, and `headless`, may require a different account tier beyond free trial. Please contact the [Sauce Labs Sales Team](https://saucelabs.com/contact) for support and information.
+> Some examples in this repository, such as `appium-example`, `parallel-testing`, and `headless`,
+> may require a different account tier beyond free trial. Please contact
+> the [Sauce Labs Sales Team](https://saucelabs.com/contact) for support and information.
diff --git a/appium-junit4-cucumber-examples/pom.xml b/appium-junit4-cucumber-examples/pom.xml
index 5217e9f9..46858afd 100644
--- a/appium-junit4-cucumber-examples/pom.xml
+++ b/appium-junit4-cucumber-examples/pom.xml
@@ -2,29 +2,38 @@
-
- demo-java
- com.saucelabs
- 1.0-SNAPSHOT
- ../pom.xml
-
+
4.0.0
+ Sauce Labs Appium/Junit4/Cucumber Examples
+
+
+ 9.3.0
+
+ com.saucelabsappium-junit4-cucumber-examples
+ 1.0-SNAPSHOT
+
-
-
io.cucumbercucumber-java
- 7.3.3
+ 7.20.1testio.cucumbercucumber-junit
- 7.3.3
+ 7.20.1
+ test
+
+
+
+ io.appium
+ java-client
+ ${appium.version}test
+
diff --git a/appium-junit4-cucumber-examples/src/test/java/com/realdevices/RunCucumberTest.java b/appium-junit4-cucumber-examples/src/test/java/com/realdevices/RunCucumberTest.java
index 7123ae10..d59ecd8c 100644
--- a/appium-junit4-cucumber-examples/src/test/java/com/realdevices/RunCucumberTest.java
+++ b/appium-junit4-cucumber-examples/src/test/java/com/realdevices/RunCucumberTest.java
@@ -5,6 +5,6 @@
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
-@CucumberOptions(plugin = {"pretty"}, features = "src/test/resources")
+@CucumberOptions(features = "src/test/resources")
public class RunCucumberTest {
}
diff --git a/appium-junit4-cucumber-examples/src/test/java/com/realdevices/StepDefinitions.java b/appium-junit4-cucumber-examples/src/test/java/com/realdevices/StepDefinitions.java
index a93fc46e..e0f8c6b5 100644
--- a/appium-junit4-cucumber-examples/src/test/java/com/realdevices/StepDefinitions.java
+++ b/appium-junit4-cucumber-examples/src/test/java/com/realdevices/StepDefinitions.java
@@ -64,7 +64,27 @@ public void setUp(Scenario scenario) throws MalformedURLException {
@io.cucumber.java.After
public void tearDown(Scenario scenario){
- driver.quit();
+ try {
+ if (scenario.isFailed()) {
+ if (driver != null) {
+ System.out.println("Test Failed!");
+ driver.executeScript("sauce:job-result=failed");
+ driver.quit();
+ }
+
+ } else {
+ if (driver != null) {
+ System.out.println("Test Passed!");
+ driver.executeScript("sauce:job-result=passed");
+ driver.quit();
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ System.out.println("Release driver");
+ driver.quit();
+ }
}
@Given("I open the iOS application")
diff --git a/appium/appium-app/appium-app-best-practice/pom.xml b/appium/appium-app/appium-app-best-practice/pom.xml
index 39f78914..c614fac6 100644
--- a/appium/appium-app/appium-app-best-practice/pom.xml
+++ b/appium/appium-app/appium-app-best-practice/pom.xml
@@ -1,58 +1,85 @@
-
-
- demo-java
- com.saucelabs
- 1.0-SNAPSHOT
- ../../../pom.xml
-
- 4.0.0
-
- appium-app-best-practice
-
-
- src/test/resources/config
- myDemoTests.xml
- 7.5
- 8.3.0
-
-
-
-
- org.testng
- testng
- ${testng.version}
-
-
-
- org.assertj
- assertj-core
- 3.10.0
-
-
-
- io.appium
- java-client
- ${appium.version}
- test
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 3.0.0-M4
-
-
- ${testngXmlDir}/${testngXmlFile}
-
-
-
-
-
-
-
\ No newline at end of file
+
+ 4.0.0
+
+ appium-app-best-practice
+
+
+ src/test/resources/config
+ myDemoTests.xml
+ 7.10.2
+ 9.3.0
+ 4.25.0
+
+
+
+
+ org.testng
+ testng
+ ${testng.version}
+
+
+
+ org.assertj
+ assertj-core
+ 3.26.3
+
+
+
+
+ io.appium
+ java-client
+ ${appium.version}
+ test
+
+
+ org.seleniumhq.selenium
+ selenium-api
+
+
+ org.seleniumhq.selenium
+ selenium-remote-driver
+
+
+ org.seleniumhq.selenium
+ selenium-support
+
+
+
+
+ org.seleniumhq.selenium
+ selenium-api
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-remote-driver
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-support
+ ${selenium.version}
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.5.1
+
+
+ ${testngXmlDir}/${testngXmlFile}
+
+
+
+
+
+
+
diff --git a/appium/appium-app/appium-app-examples/README.md b/appium/appium-app/appium-app-examples/README.md
index 8db4b692..e575cf1a 100644
--- a/appium/appium-app/appium-app-examples/README.md
+++ b/appium/appium-app/appium-app-examples/README.md
@@ -5,7 +5,9 @@ This folder contains Appium examples
* [Simple examples to get you started with your native appium testing](./src/test/java/com/examples/simple_example)
* [Using biometric login on Sauce Labs](./src/test/java/com/examples/biometric_login)
* [Using image injection on Sauce Labs](./src/test/java/com/examples/image_injection)
+* [Using network throttling on Sauce Labs](./src/test/java/com/examples/network_throttling)
* [Using gestures](./src/test/java/com/examples/gestures)
* [Upload and download file](./src/test/java/com/examples/up_download_file)
* [Using deep link](./src/test/java/com/examples/deep_link)
* [Test your allowlisting app](./src/test/java/com/examples/allowlist)
+* [Using Appium Image Selectors](./src/test/java/com/examples/find_by_image)
diff --git a/appium/appium-app/appium-app-examples/pom.xml b/appium/appium-app/appium-app-examples/pom.xml
index 7a1a1336..d36e4f42 100644
--- a/appium/appium-app/appium-app-examples/pom.xml
+++ b/appium/appium-app/appium-app-examples/pom.xml
@@ -1,61 +1,90 @@
-
-
- demo-java
- com.saucelabs
- 1.0-SNAPSHOT
- ../../../pom.xml
-
- 4.0.0
-
- appium-app-examples
-
-
- 3.0.0-M5
- 8.3.0
-
-
-
-
-
-
-
- commons-logging
- commons-logging
- 1.2
-
-
-
- org.assertj
- assertj-core
- 3.10.0
-
-
-
- io.appium
- java-client
- ${appium.version}
- test
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- ${maven.surefire.version}
-
- all
- 30
- true
- false
-
-
-
-
-
-
-
\ No newline at end of file
+
+ 4.0.0
+
+ appium-app-examples
+
+
+ 3.5.1
+ 9.3.0
+ 4.25.0
+
+
+
+
+
+
+ commons-logging
+ commons-logging
+ 1.3.4
+
+
+
+ org.assertj
+ assertj-core
+ 3.26.3
+
+
+
+
+ io.appium
+ java-client
+ ${appium.version}
+ test
+
+
+ org.seleniumhq.selenium
+ selenium-api
+
+
+ org.seleniumhq.selenium
+ selenium-remote-driver
+
+
+ org.seleniumhq.selenium
+ selenium-support
+
+
+
+
+ org.seleniumhq.selenium
+ selenium-api
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-remote-driver
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-support
+ ${selenium.version}
+
+
+ junit
+ junit
+ 4.13.2
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven.surefire.version}
+
+ all
+ 30
+ true
+ false
+
+
+
+
+
+
+
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/allowlist/IOSAllowlistTest.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/allowlist/IOSAllowlistTest.java
index d7ae5286..1858a087 100644
--- a/appium/appium-app/appium-app-examples/src/test/java/com/examples/allowlist/IOSAllowlistTest.java
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/allowlist/IOSAllowlistTest.java
@@ -1,7 +1,18 @@
package com.examples.allowlist;
+import static com.helpers.Constants.SAUCE_EU_URL;
+import static com.helpers.Constants.SAUCE_US_URL;
+import static com.helpers.Constants.region;
+import static org.assertj.core.api.Assertions.assertThat;
+
import com.helpers.SauceAppiumTestWatcher;
import io.appium.java_client.ios.IOSDriver;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -13,117 +24,106 @@
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.time.Duration;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-
-import static com.helpers.Constants.*;
-import static org.assertj.core.api.Assertions.assertThat;
-
public class IOSAllowlistTest {
- @Rule
- public TestName name = new TestName();
-
- //This rule allows us to set test status with Junit
- @Rule
- public SauceAppiumTestWatcher resultReportingTestWatcher = new SauceAppiumTestWatcher();
-
- private IOSDriver driver;
-
- @Before
- public void setUp() throws MalformedURLException {
- System.out.println("Sauce iOS Native App - Before hook");
-
- MutableCapabilities capabilities = new MutableCapabilities();
- MutableCapabilities sauceOptions = new MutableCapabilities();
- URL url;
- String appName;
-
- switch (region) {
- case "us":
- url = new URL(SAUCE_US_URL);
- break;
- case "eu":
- default:
- url = new URL(SAUCE_EU_URL);
- break;
- }
-
- capabilities.setCapability("platformName", "iOS");
- capabilities.setCapability("appium:automationName", "XCuiTest");
-
- //Allocate any avilable iPhone device with version 14
- capabilities.setCapability("appium:deviceName", "iPhone.*");
- capabilities.setCapability("appium:platformVersion", "14");
-
- // Use bundleId to open an app that is already installed on the device.
- capabilities.setCapability("appium:bundleId", "com.apple.Preferences");
-
- sauceOptions.setCapability("name", name.getMethodName());
- sauceOptions.setCapability("build", "myApp-job-1");
- List tags = Arrays.asList("sauceDemo_ios", "iOS", "allowlist");
- sauceOptions.setCapability("tags", tags);
- sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
- sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
- capabilities.setCapability("sauce:options", sauceOptions);
-
- try {
- driver = new IOSDriver(url, capabilities);
- } catch (Exception e){
- System.out.println("Error to create iOS Driver: " + e.getMessage());
- }
-
- //Setting the driver so that we can report results
- resultReportingTestWatcher.setDriver(driver);
- }
+ @Rule public TestName name = new TestName();
- @Test
- public void openSettingsApp() throws MalformedURLException {
+ // This rule allows us to set test status with Junit
+ @Rule public SauceAppiumTestWatcher resultReportingTestWatcher = new SauceAppiumTestWatcher();
- // Run our buisness flow on the App
- // In this case - open the 'privacy' setting
- RemoteWebElement settingsTable = (RemoteWebElement)driver.findElement(By.xpath("//XCUIElementTypeApplication[@name=\"Settings\"]"));
- String elementID = settingsTable.getId();
+ private IOSDriver driver;
- HashMap scrollObject = new HashMap();
- scrollObject.put("element", elementID);
- scrollObject.put("predicateString", "label == 'Privacy' AND name == 'Privacy' AND type == 'XCUIElementTypeCell'");
- scrollObject.put("direction", "down");
- driver.executeScript("mobile:scroll", scrollObject);
+ public static void waiting(int sec) {
+ try {
+ Thread.sleep(sec * 1000);
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ @Before
+ public void setUp() throws MalformedURLException {
+ System.out.println("Sauce iOS Native App - Before hook");
+
+ MutableCapabilities capabilities = new MutableCapabilities();
+ MutableCapabilities sauceOptions = new MutableCapabilities();
+ URL url;
+
+ switch (region) {
+ case "us":
+ url = new URL(SAUCE_US_URL);
+ break;
+ case "eu":
+ default:
+ url = new URL(SAUCE_EU_URL);
+ break;
+ }
- WebElement privacyBtn = driver.findElement(By.xpath("//XCUIElementTypeStaticText[@name=\"Privacy\"]"));
- privacyBtn.click();
+ capabilities.setCapability("platformName", "iOS");
+ capabilities.setCapability("appium:automationName", "XCuiTest");
- // Verification - Check the title is Privacy
- assertThat(isDisplayed(By.xpath("//XCUIElementTypeStaticText[@name=\"Privacy\"]"), 5)).as("Verify Privacy Setting is displayed").isTrue();
- // Only needed for the recording video :-)
- waiting(2);
+ // Allocate any avilable iPhone device with version 14
+ capabilities.setCapability("appium:deviceName", "iPhone.*");
+ capabilities.setCapability("appium:platformVersion", "14");
- }
+ // Use bundleId to open an app that is already installed on the device.
+ capabilities.setCapability("appium:bundleId", "com.apple.Preferences");
- public Boolean isDisplayed(By locator, long timeoutInSeconds) {
- try {
- WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeoutInSeconds));
- wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
- } catch (org.openqa.selenium.TimeoutException exception) {
- return false;
- }
- return true;
- }
+ sauceOptions.setCapability("name", name.getMethodName());
+ sauceOptions.setCapability("build", "myApp-job-1");
+ List tags = Arrays.asList("sauceDemo_ios", "iOS", "allowlist");
+ sauceOptions.setCapability("tags", tags);
+ sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
+ sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
+ capabilities.setCapability("sauce:options", sauceOptions);
- public static void waiting(int sec){
- try
- {
- Thread.sleep(sec*1000);
- }
- catch(InterruptedException ex)
- {
- Thread.currentThread().interrupt();
- }
+ try {
+ driver = new IOSDriver(url, capabilities);
+ } catch (Exception e) {
+ System.out.println("Error to create iOS Driver: " + e.getMessage());
}
+ // Setting the driver so that we can report results
+ resultReportingTestWatcher.setDriver(driver);
+ }
+
+ @Test
+ public void openSettingsApp() throws MalformedURLException {
+
+ // Run our buisness flow on the App
+ // In this case - open the 'privacy' setting
+ RemoteWebElement settingsTable =
+ (RemoteWebElement)
+ driver.findElement(By.xpath("//XCUIElementTypeApplication[@name=\"Settings\"]"));
+ String elementID = settingsTable.getId();
+
+ HashMap scrollObject = new HashMap();
+ scrollObject.put("element", elementID);
+ scrollObject.put(
+ "predicateString",
+ "label == 'Privacy' AND name == 'Privacy' AND type == 'XCUIElementTypeCell'");
+ scrollObject.put("direction", "down");
+ driver.executeScript("mobile:scroll", scrollObject);
+
+ WebElement privacyBtn =
+ driver.findElement(By.xpath("//XCUIElementTypeStaticText[@name=\"Privacy\"]"));
+ privacyBtn.click();
+
+ // Verification - Check the title is Privacy
+ assertThat(isDisplayed(By.xpath("//XCUIElementTypeStaticText[@name=\"Privacy\"]"), 5))
+ .as("Verify Privacy Setting is displayed")
+ .isTrue();
+ // Only needed for the recording video :-)
+ waiting(2);
+ }
+
+ public Boolean isDisplayed(By locator, long timeoutInSeconds) {
+ try {
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeoutInSeconds));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
+ } catch (org.openqa.selenium.TimeoutException exception) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/deep_link/DeepLinkIosRDCTest.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/deep_link/DeepLinkIosRDCTest.java
new file mode 100644
index 00000000..b4dd719d
--- /dev/null
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/deep_link/DeepLinkIosRDCTest.java
@@ -0,0 +1,99 @@
+package com.examples.deep_link;
+
+import com.google.common.collect.ImmutableMap;
+import com.helpers.SauceAppiumTestWatcher;
+import io.appium.java_client.ios.IOSDriver;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.openqa.selenium.MutableCapabilities;
+import org.openqa.selenium.support.ui.ExpectedCondition;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import static com.helpers.Constants.SAUCE_EU_URL;
+import static com.helpers.Constants.SAUCE_US_URL;
+import static com.helpers.Constants.region;
+
+public class DeepLinkIosRDCTest {
+
+ @Rule
+ public TestName name = new TestName();
+
+ //This rule allows us to set test status with Junit
+ @Rule
+ public SauceAppiumTestWatcher resultReportingTestWatcher = new SauceAppiumTestWatcher();
+
+ private IOSDriver driver;
+
+ @Before
+ public void setUp() throws MalformedURLException {
+ MutableCapabilities capabilities = new MutableCapabilities();
+ MutableCapabilities sauceOptions = new MutableCapabilities();
+ URL url;
+
+ switch (region) {
+ case "us":
+ url = new URL(SAUCE_US_URL);
+ break;
+ case "eu":
+ default:
+ url = new URL(SAUCE_EU_URL);
+ break;
+ }
+
+ capabilities.setCapability("platformName", "iOS");
+ capabilities.setCapability("appium:automationName", "XCuiTest");
+ capabilities.setCapability("appium:deviceName", "iPhone 15.*");
+ // The feature only works since iOS 17
+ capabilities.setCapability("appium:platformVersion", "17");
+ capabilities.setCapability("appium:newCommandTimeout", 240);
+ String appName = "iOS.MyDemoAppRN.ipa";
+ capabilities.setCapability("app", "storage:filename=" +appName);
+
+ sauceOptions.setCapability("name", name.getMethodName());
+ sauceOptions.setCapability("build", "deepLink-job-1");
+ List tags = Arrays.asList("sauceDemo", "iOS","Deep Link");
+ sauceOptions.setCapability("tags", tags);
+ sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
+ sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
+ // iOS 17+ requires Appium 2+
+ sauceOptions.setCapability("appiumVersion", "latest");
+
+ capabilities.setCapability("sauce:options", sauceOptions);
+
+ driver = new IOSDriver(url, capabilities);
+
+ //Setting the driver so that we can report results
+ resultReportingTestWatcher.setDriver(driver);
+ }
+
+ @Test
+ public void openPageWithDeepLink () {
+ System.out.println("Sauce - open page with deep link");
+
+ // https://github.com/appium/appium-xcuitest-driver/blob/master/docs/reference/execute-methods.md#mobile-deeplink
+ driver.executeScript("mobile: deepLink", ImmutableMap.of(
+ "url", "https://saucelabs.com"
+ ));
+
+ // Verify we are in the Safari app
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
+ wait.until((ExpectedCondition) webDriver -> {
+ @SuppressWarnings("unchecked")
+ Map activeAppInfo = (Map) driver.executeScript(
+ "mobile: activeAppInfo"
+ );
+ return Objects.equals(activeAppInfo.get("bundleId"), "com.apple.mobilesafari");
+ });
+ }
+
+}
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/find_by_image/AndroidFindByImageTest.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/find_by_image/AndroidFindByImageTest.java
new file mode 100644
index 00000000..f82784a7
--- /dev/null
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/find_by_image/AndroidFindByImageTest.java
@@ -0,0 +1,170 @@
+package com.examples.find_by_image;
+
+import com.helpers.SauceAppiumTestWatcher;
+import io.appium.java_client.AppiumBy;
+import io.appium.java_client.android.AndroidDriver;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.openqa.selenium.*;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.List;
+
+import static com.helpers.Constants.*;
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Android Native App Tests
+ */
+public class AndroidFindByImageTest {
+
+ By productsScreenLocator = By.id("com.saucelabs.mydemoapp.android:id/productTV");
+ By productItemTitleLocator = By.id("com.saucelabs.mydemoapp.android:id/productTV");
+
+
+ @Rule
+ public TestName name = new TestName();
+
+ //This rule allows us to set test status with Junit
+ @Rule
+ public SauceAppiumTestWatcher resultReportingTestWatcher = new SauceAppiumTestWatcher();
+
+ private AndroidDriver driver;
+
+ @Before
+ public void setup() throws MalformedURLException {
+ System.out.println("Sauce Android Native App - Before hook");
+ MutableCapabilities capabilities = new MutableCapabilities();
+ MutableCapabilities sauceOptions = new MutableCapabilities();
+ URL url;
+
+ switch (region) {
+ case "us":
+ url = new URL(SAUCE_US_URL);
+ System.out.println("Sauce REGION US");
+ break;
+ case "eu":
+ default:
+ url = new URL(SAUCE_EU_URL);
+ System.out.println("Sauce REGION EU");
+ break;
+ }
+
+ // For all capabilities please check
+ // https://appium.io/docs/en/2.0/guides/caps/
+ // Use the platform configuration https://saucelabs.com/platform/platform-configurator#/
+ // to find the emulators/real devices names, OS versions and appium versions you can use for your testings
+ capabilities.setCapability("platformName", "Android");
+ capabilities.setCapability("appium:automationName", "UiAutomator2");
+ capabilities.setCapability("appium:deviceName", "^Samsung.*");
+ capabilities.setCapability("appium:platformVersion", "1[2-4]");
+ sauceOptions.setCapability("resigningEnabled", true);
+ sauceOptions.setCapability("sauceLabsNetworkCaptureEnabled", true);
+ String appName = "SauceLabs-Demo-App.apk";
+ capabilities.setCapability("appium:app", "storage:filename=" +appName);
+
+ // Sauce capabilities
+ sauceOptions.setCapability("name", name.getMethodName());
+ sauceOptions.setCapability("appiumVersion", "latest");
+ sauceOptions.setCapability("build", "myApp-job-findImage-1");
+ List tags = Arrays.asList("sauceDemo", "Android", "FindByImage");
+ sauceOptions.setCapability("tags", tags);
+ sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
+ sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
+ capabilities.setCapability("sauce:options", sauceOptions);
+
+ // appium:settings capabilities
+ MutableCapabilities settingsOptions = new MutableCapabilities();
+ settingsOptions.setCapability("imageMatchThreshold", 0.4);
+ settingsOptions.setCapability("getMatchedImageResult", true);
+
+ capabilities.setCapability("appium:settings", settingsOptions);
+
+ try {
+ driver = new AndroidDriver(url, capabilities);
+ } catch (Exception e){
+ System.out.println("Error to create Android Driver: " + e.getMessage());
+ return;
+ }
+ //Setting the driver so that we can report results
+ resultReportingTestWatcher.setDriver(driver);
+ }
+
+ @Test
+ public void verifySelectingBackPackProduct() throws MalformedURLException {
+ //Wait for the application to start and load the initial screen (products screen)
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(productsScreenLocator));
+
+ // find the Backpack product by image
+ // Please read about that here: https://github.com/appium/appium/blob/master/packages/images-plugin/docs/find-by-image.md?utm_source=beamer&utm_medium=sidebar&utm_campaign=Now-available-Appium-Image-Selectors-and-Elements-support-on-Real-Device-Cloud&utm_content=ctalink
+ // And here: https://changelog.saucelabs.com/en/now-available-appium-image-selectors-and-elements-support-on-real-device-cloud-qMPpYR6O
+ String backpackImage = encoder("src/test/java/com/examples/find_by_image/androidBackpackImage.png");
+ WebElement backpackImageElement = driver.findElement(AppiumBy.image(backpackImage));
+
+ // Start **********************************************************************
+ // No need to do it. Only if you want to see the image that Appium capture
+ // The image is saved as an image file "output_image.png"
+ String returnImage = backpackImageElement.getAttribute("visual");
+ // Decode Base64 string to image bytes
+ byte[] imageBytes = Base64.getDecoder().decode(returnImage);
+
+ // Convert byte array into BufferedImage
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes)) {
+ BufferedImage image = ImageIO.read(bis);
+
+ // Write the image to a file
+ File outputFile = new File("src/test/java/com/examples/find_by_image/output_image.png");
+ ImageIO.write(image, "png", outputFile);
+ System.out.println("Image has been written successfully");
+ } catch (IOException e) {
+ System.err.println("Unable to convert Base64 string to image");
+ }
+ // End ************************************************************************
+
+ // Click on the image
+ backpackImageElement.click();
+
+ //Verify we are in the backpack product item page
+ assertThat(isTextAsExpected(productItemTitleLocator, "Backpack", 5)).as("Verify product item title").isTrue();
+ }
+
+ public Boolean isTextAsExpected(By locator, String expectedText ,long timeoutInSeconds) {
+ try {
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeoutInSeconds));
+ wait.until(ExpectedConditions.attributeContains(locator, "text", expectedText ));
+ } catch (org.openqa.selenium.TimeoutException exception) {
+ // Report the error to Sauce log
+ driver.executeScript("sauce:context=Error - The title is not " + expectedText);
+ return false;
+ }
+ return true;
+ }
+
+ public String encoder(String imagePath) {
+ String base64Image = "";
+ File file = new File(imagePath);
+ try (FileInputStream imageInFile = new FileInputStream(file)) {
+ // Reading a Image file from file system
+ byte imageData[] = new byte[(int) file.length()];
+ imageInFile.read(imageData);
+ base64Image = Base64.getEncoder().encodeToString(imageData);
+ } catch (FileNotFoundException e) {
+ System.out.println("Image not found" + e);
+ } catch (IOException ioe) {
+ System.out.println("Exception while reading the Image " + ioe);
+ }
+ return base64Image;
+ }
+}
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/find_by_image/androidBackpackImage.png b/appium/appium-app/appium-app-examples/src/test/java/com/examples/find_by_image/androidBackpackImage.png
new file mode 100644
index 00000000..f27a7b7a
Binary files /dev/null and b/appium/appium-app/appium-app-examples/src/test/java/com/examples/find_by_image/androidBackpackImage.png differ
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/gestures/GestureSwipeAndroidNativeAppTest.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/gestures/GestureSwipeAndroidNativeAppTest.java
new file mode 100644
index 00000000..5607eadd
--- /dev/null
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/gestures/GestureSwipeAndroidNativeAppTest.java
@@ -0,0 +1,234 @@
+package com.examples.gestures;
+
+// I recommend watching this webinar about this topic:
+// Swiping your way through Appium by Wim Selles
+// https://www.youtube.com/watch?v=oAJ7jwMNFVU
+// The demo App:
+// https://github.com/saucelabs/my-demo-app-android
+
+import com.google.common.collect.ImmutableMap;
+import com.helpers.SauceAppiumTestWatcher;
+import io.appium.java_client.AppiumBy;
+import io.appium.java_client.android.AndroidDriver;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.openqa.selenium.*;
+import org.openqa.selenium.interactions.Pause;
+import org.openqa.selenium.interactions.PointerInput;
+import org.openqa.selenium.interactions.Sequence;
+import org.openqa.selenium.remote.RemoteWebElement;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static com.helpers.Constants.*;
+
+/**
+ * Android Native App Tests
+ */
+public class GestureSwipeAndroidNativeAppTest {
+
+ @Rule
+ public TestName name = new TestName();
+
+ //This rule allows us to set test status with Junit
+ @Rule
+ public SauceAppiumTestWatcher resultReportingTestWatcher = new SauceAppiumTestWatcher();
+
+ private AndroidDriver driver;
+ By productsTitle = By.id("com.saucelabs.mydemoapp.android:id/productTV");
+ By allProductsOfCatalog = By.id("com.saucelabs.mydemoapp.android:id/productRV");
+
+ @Before
+ public void setup() throws MalformedURLException {
+ System.out.println("Sauce Android Native App - BeforeMethod hook");
+ MutableCapabilities capabilities = new MutableCapabilities();
+ MutableCapabilities sauceOptions = new MutableCapabilities();
+ URL url;
+
+ switch (region) {
+ case "us":
+ url = new URL(SAUCE_US_URL);
+ System.out.println("Sauce REGION US");
+ break;
+ case "eu":
+ default:
+ url = new URL(SAUCE_EU_URL);
+ System.out.println("Sauce REGION EU");
+ break;
+ }
+
+ //find a device in the cloud
+ capabilities.setCapability("platformName", "Android");
+ capabilities.setCapability("appium:automationName", "UiAutomator2");
+ //Allocate any avilable samsung device with Android version 12
+ capabilities.setCapability("appium:deviceName", "Samsung.*");
+ capabilities.setCapability("appium:platformVersion", "1[2-3]");
+ String appName = "my-demo-app-android.apk";
+ capabilities.setCapability("appium:app", "storage:filename=" +appName);
+
+ // Sauce capabilities
+ sauceOptions.setCapability("name", name.getMethodName());
+ sauceOptions.setCapability("build", "myApp-job-1");
+ List tags = Arrays.asList("sauceDemo", "Android", "Demo", "gestures-swipe");
+ sauceOptions.setCapability("tags", tags);
+ sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
+ sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
+
+ sauceOptions.setCapability("resigningEnabled", true);
+ sauceOptions.setCapability("sauceLabsNetworkCaptureEnabled", true);
+ sauceOptions.setCapability("appiumVersion", "2.0.0");
+
+ capabilities.setCapability("sauce:options", sauceOptions);
+
+ try {
+ driver = new AndroidDriver(url, capabilities);
+ } catch (Exception e){
+ System.out.println("Error to create Android Driver: " + e.getMessage());
+ return;
+ }
+ //Setting the driver so that we can report results
+ resultReportingTestWatcher.setDriver(driver);
+ }
+
+
+ @Test
+ public void swipeUp() throws MalformedURLException {
+
+ // From:
+ // https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md
+
+ // waiting for the page to be visible
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(productsTitle));
+
+
+ // Get the screen dimension
+ Dimension size = driver.manage().window().getSize();
+ int screenWidth = size.width;
+ int screenHeight = size.height;
+
+ System.out.println("Screen Width: " + screenWidth);
+ System.out.println("Screen Height: " + screenHeight);
+
+
+ //https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md#mobile-swipegesture
+ ((JavascriptExecutor) driver).executeScript("mobile: swipeGesture", ImmutableMap.of(
+ "left", 0, "top", 0, "width", screenWidth, "height", screenHeight,
+ "direction", "up",
+ "percent", 1.00
+ ));
+
+ waiting(5); // For video and demo purpose
+
+ }
+
+ @Test
+ public void swipeUpOnElement() throws MalformedURLException {
+
+ // From:
+ // https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md
+
+ // waiting for the page to be visible
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(productsTitle));
+
+
+ WebElement element = (WebElement) driver.findElement(allProductsOfCatalog);
+ String elementId = ((RemoteWebElement) element).getId();
+
+ //https://github.com/appium/appium-uiautomator2-driver/blob/master/docs/android-mobile-gestures.md#mobile-swipegesture
+ ((JavascriptExecutor) driver).executeScript("mobile: swipeGesture", ImmutableMap.of(
+ "elementId", elementId,
+ "direction", "up",
+ "percent", 1.00
+ ));
+
+ waiting(5); // For video and demo purpose
+
+ }
+
+ @Test
+ public void swipeUpUsingUIAutomator() throws MalformedURLException {
+
+ // waiting for the page to be visible
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(productsTitle));
+
+ // Find element by the element text -> if needed - swipe to this element
+ WebElement product = driver.findElement(AppiumBy.androidUIAutomator("new UiScrollable(new UiSelector().scrollable(true)).scrollIntoView(new UiSelector().text(\"Sauce Labs Onesie\"));"));
+ waiting(5); // For video and demo purpose
+ System.out.println("Sauce - the product text is " + product.getText());
+ }
+
+ @Test
+ public void swipeUpUsingW3CActions() throws MalformedURLException {
+
+ // Good article: https://www.linkedin.com/pulse/guide-perform-appium-20-w3c-mobile-actions-swipe-ꜱᴀɴᴋᴇᴛ-ᴊᴏꜱʜɪ
+ // This swipe can be used for both Android and iOS.
+
+ // waiting for the page to be visible
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(productsTitle));
+
+
+ // 1. The rectangle of the element to scroll
+ WebElement element = (WebElement) driver.findElement(allProductsOfCatalog);
+ Rectangle rect = element.getRect();
+
+ // 2. Determine the x and y position of initial touch
+ // we scroll up/down and the x doesn't change
+ int centerX = rect.x + (int)(rect.width /2);
+
+ int startY;
+ int endY;
+
+ // Swipe Up
+ startY = rect.y + (int) (rect.height * 0.8);
+ // The end Y position
+ endY = rect.y + (int) (rect.height * 0.2);
+
+
+ // 3. swipe
+ // finger
+ PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
+ Sequence tapPoint = new Sequence(finger, 1);
+ // Move finger into start position
+ tapPoint.addAction(finger.createPointerMove(Duration.ofMillis(0), PointerInput.Origin.viewport(), centerX, startY));
+ // Finger comes down into context with screen
+ tapPoint.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
+ // Pause for a little bit
+ tapPoint.addAction(new Pause(finger, Duration.ofMillis(100)));
+ // Finger move to end position
+ tapPoint.addAction(finger.createPointerMove(Duration.ofMillis(500), PointerInput.Origin.viewport(), centerX, endY));
+ // Finger gets up, off the screen
+ tapPoint.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
+
+ // Perform the scroll
+ driver.perform(Collections.singletonList(tapPoint));
+
+ waiting(5); // For video and demo purpose
+
+ }
+
+ private void waiting(int sec){
+ try
+ {
+ Thread.sleep(sec*1000);
+ }
+ catch(InterruptedException ex)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+
+}
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/image_injection/ImageInjectionAndroidTest.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/image_injection/ImageInjectionAndroidTest.java
index d4ba7497..eadebbf1 100644
--- a/appium/appium-app/appium-app-examples/src/test/java/com/examples/image_injection/ImageInjectionAndroidTest.java
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/image_injection/ImageInjectionAndroidTest.java
@@ -66,7 +66,7 @@ public void setup() throws IOException {
//find a device in the cloud
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("appium:automationName", "UiAutomator2");
- //Allocate any avilable samsung device with Android version 12
+ //Allocate any available samsung device with Android version 12
capabilities.setCapability("appium:deviceName", "Samsung.*");
capabilities.setCapability("appium:platformVersion", "12");
String appName = "Android.MyDemoAppRN.apk";
@@ -114,7 +114,8 @@ public void imageInjectionAndroid() throws InterruptedException {
qCCodeMenu.click();
// inject the image - provide the transformed image to the device with this command
- String qrCodeImage = encoder("src/test/java/com/appium_app/image_injection/images/qr-code.png");
+ String qrCodeImage = encoder("src/test/java/com/examples/image_injection/images/qr-code.png");
+
driver.executeScript("sauce:inject-image=" + qrCodeImage);
// Verify that the browser is running
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/image_injection/ImageInjectionIosTest.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/image_injection/ImageInjectionIosTest.java
index a836fda7..122e1c0f 100644
--- a/appium/appium-app/appium-app-examples/src/test/java/com/examples/image_injection/ImageInjectionIosTest.java
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/image_injection/ImageInjectionIosTest.java
@@ -1,8 +1,7 @@
package com.examples.image_injection;
-
import com.helpers.SauceAppiumTestWatcher;
-import io.appium.java_client.MobileBy;
+import io.appium.java_client.AppiumBy;
import io.appium.java_client.ios.IOSDriver;
import org.junit.Before;
import org.junit.Rule;
@@ -99,11 +98,11 @@ public void imageInjectionIOS() throws InterruptedException {
//wait for the product field to be visible and store that element into a variable
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
- WebElement menu = wait.until(ExpectedConditions.visibilityOfElementLocated(MobileBy.AccessibilityId(ios_testMenu)));
+ WebElement menu = wait.until(ExpectedConditions.visibilityOfElementLocated(AppiumBy.accessibilityId(ios_testMenu)));
menu.click();
// *** selec Menu QR Code
- WebElement qCCodeMenu = wait.until(ExpectedConditions.visibilityOfElementLocated(MobileBy.AccessibilityId(testMenuItemQRCode)));
+ WebElement qCCodeMenu = wait.until(ExpectedConditions.visibilityOfElementLocated(AppiumBy.accessibilityId(testMenuItemQRCode)));
qCCodeMenu.click();
// inject the image - provide the transformed image to the device with this command
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/mid_session_app_installs/MidSessionAppInstallsAndroidTest.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/mid_session_app_installs/MidSessionAppInstallsAndroidTest.java
index aa9c63e6..418d0c72 100644
--- a/appium/appium-app/appium-app-examples/src/test/java/com/examples/mid_session_app_installs/MidSessionAppInstallsAndroidTest.java
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/mid_session_app_installs/MidSessionAppInstallsAndroidTest.java
@@ -3,7 +3,6 @@
import com.google.common.collect.ImmutableMap;
import com.helpers.SauceAppiumTestWatcher;
import io.appium.java_client.android.AndroidDriver;
-import lombok.var;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -19,117 +18,109 @@
import static com.helpers.Constants.*;
-/**
- * Android Native App Tests
- */
+/** Android Native App Tests */
public class MidSessionAppInstallsAndroidTest {
- By productsScreenLocator = By.xpath("//*[@content-desc=\"products screen\"]");
- By sortButtonLocator = By.xpath("//*[@content-desc=\"sort button\"]");
- By sortModalLocator = By.xpath("//*[@content-desc=\"active option\"]");
-
-
- @Rule
- public TestName name = new TestName();
-
- //This rule allows us to set test status with Junit
- @Rule
- public SauceAppiumTestWatcher resultReportingTestWatcher = new SauceAppiumTestWatcher();
-
- private AndroidDriver driver;
-
- @Before
- public void setup() throws MalformedURLException {
- System.out.println("Sauce Android Native App - Before hook");
- MutableCapabilities capabilities = new MutableCapabilities();
- MutableCapabilities sauceOptions = new MutableCapabilities();
- URL url;
-
- switch (region) {
- case "us":
- url = new URL(SAUCE_US_URL);
- System.out.println("Sauce REGION US");
- break;
- case "eu":
- default:
- url = new URL(SAUCE_EU_URL);
- System.out.println("Sauce REGION EU");
- break;
- }
-
- // For all capabilities please check
- // http://appium.io/docs/en/writing-running-appium/caps/#general-capabilities
- // Use the platform configuration https://saucelabs.com/platform/platform-configurator#/
- // to find the emulators/real devices names, OS versions and appium versions you can use for your testings
-
- capabilities.setCapability("platformName", "Android");
- capabilities.setCapability("appium:automationName", "UiAutomator2");
- capabilities.setCapability("appium:deviceName", "Samsung.*");
- sauceOptions.setCapability("resigningEnabled", true);
- sauceOptions.setCapability("sauceLabsNetworkCaptureEnabled", true);
- capabilities.setCapability("appium:platformVersion", "13");
- String appName = "mda-1.0.14-17.apk";
- capabilities.setCapability("appium:app", "storage:filename=" +appName);
-
- // Sauce capabilities
- sauceOptions.setCapability("name", name.getMethodName());
- sauceOptions.setCapability("build", "myApp-job-1");
- List tags = Arrays.asList("sauceDemo", "Android", "Demo", "mid-session-app-installs");
- sauceOptions.setCapability("tags", tags);
- sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
- sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
-
- capabilities.setCapability("sauce:options", sauceOptions);
-
- try {
- driver = new AndroidDriver(url, capabilities);
- } catch (Exception e){
- System.out.println("Error to create Android Driver: " + e.getMessage());
- return;
- }
- //Setting the driver so that we can report results
- resultReportingTestWatcher.setDriver(driver);
+ @Rule public TestName name = new TestName();
+ // This rule allows us to set test status with Junit
+ @Rule public SauceAppiumTestWatcher resultReportingTestWatcher = new SauceAppiumTestWatcher();
+ By productsScreenLocator = By.xpath("//*[@content-desc=\"products screen\"]");
+ By sortButtonLocator = By.xpath("//*[@content-desc=\"sort button\"]");
+ By sortModalLocator = By.xpath("//*[@content-desc=\"active option\"]");
+ private AndroidDriver driver;
+
+ @Before
+ public void setup() throws MalformedURLException {
+ System.out.println("Sauce Android Native App - Before hook");
+ MutableCapabilities capabilities = new MutableCapabilities();
+ MutableCapabilities sauceOptions = new MutableCapabilities();
+ URL url;
+
+ switch (region) {
+ case "us":
+ url = new URL(SAUCE_US_URL);
+ System.out.println("Sauce REGION US");
+ break;
+ case "eu":
+ default:
+ url = new URL(SAUCE_EU_URL);
+ System.out.println("Sauce REGION EU");
+ break;
}
- @Test
- public void upgradeAppInMidSession() throws MalformedURLException {
- // Navigate to the "About" page
- navigateToAbout();
-
- // Install a new version
- var results = driver.executeScript("mobile:installApp", ImmutableMap.of("appPath", "storage:filename=mda-1.0.17-20.apk"));
- System.out.println(results);
-
- // Launch the new app
- driver.executeScript("mobile: startActivity", ImmutableMap.of("intent", "com.saucelabs.mydemoapp.android/.view.activities.SplashActivity"));
-
- waiting(3);
-
- // Navigate to the "About" page
- navigateToAbout();
- }
-
- private void navigateToAbout(){
- driver.findElement(By.id("com.saucelabs.mydemoapp.android:id/menuIV")).click();
- List menuItems = driver.findElements(By.id("com.saucelabs.mydemoapp.android:id/itemTV"));
- // About is the 6 item
- menuItems.get(5).click();
- // For the Video...
- waiting(5);
+ // For all capabilities please check
+ // http://appium.io/docs/en/writing-running-appium/caps/#general-capabilities
+ // Use the platform configuration https://saucelabs.com/platform/platform-configurator#/
+ // to find the emulators/real devices names, OS versions and appium versions you can use for
+ // your testings
+
+ capabilities.setCapability("platformName", "Android");
+ capabilities.setCapability("appium:automationName", "UiAutomator2");
+ capabilities.setCapability("appium:deviceName", "Samsung.*");
+ sauceOptions.setCapability("resigningEnabled", true);
+ sauceOptions.setCapability("sauceLabsNetworkCaptureEnabled", true);
+ capabilities.setCapability("appium:platformVersion", "13");
+ String appName = "mda-1.0.14-17.apk";
+ capabilities.setCapability("appium:app", "storage:filename=" + appName);
+
+ // Sauce capabilities
+ sauceOptions.setCapability("name", name.getMethodName());
+ sauceOptions.setCapability("build", "myApp-job-1");
+ List tags = Arrays.asList("sauceDemo", "Android", "Demo", "mid-session-app-installs");
+ sauceOptions.setCapability("tags", tags);
+ sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
+ sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
+
+ capabilities.setCapability("sauce:options", sauceOptions);
+
+ try {
+ driver = new AndroidDriver(url, capabilities);
+ } catch (Exception e) {
+ System.out.println("Error to create Android Driver: " + e.getMessage());
+ return;
}
- private void waiting(int sec){
- try
- {
- Thread.sleep(sec*1000);
- }
- catch(InterruptedException ex)
- {
- Thread.currentThread().interrupt();
- }
+ // Setting the driver so that we can report results
+ resultReportingTestWatcher.setDriver(driver);
+ }
+
+ @Test
+ public void upgradeAppInMidSession() throws MalformedURLException {
+ // Navigate to the "About" page
+ navigateToAbout();
+
+ // Install a new version
+ Object results =
+ driver.executeScript(
+ "mobile:installApp", ImmutableMap.of("appPath", "storage:filename=mda-1.0.17-20.apk"));
+ System.out.println(results);
+
+ // Launch the new app
+ driver.executeScript(
+ "mobile: startActivity",
+ ImmutableMap.of(
+ "intent", "com.saucelabs.mydemoapp.android/.view.activities.SplashActivity"));
+
+ waiting(3);
+
+ // Navigate to the "About" page
+ navigateToAbout();
+ }
+
+ private void navigateToAbout() {
+ driver.findElement(By.id("com.saucelabs.mydemoapp.android:id/menuIV")).click();
+ List menuItems =
+ driver.findElements(By.id("com.saucelabs.mydemoapp.android:id/itemTV"));
+ // About is the 6 item
+ menuItems.get(5).click();
+ // For the Video...
+ waiting(5);
+ }
+
+ private void waiting(int sec) {
+ try {
+ Thread.sleep(sec * 1000);
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
}
-
-
-
-
-
+ }
}
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/network_throttling/NetworkThrottlingAndroidRDCTest.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/network_throttling/NetworkThrottlingAndroidRDCTest.java
new file mode 100644
index 00000000..d1ab6adc
--- /dev/null
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/network_throttling/NetworkThrottlingAndroidRDCTest.java
@@ -0,0 +1,152 @@
+package com.examples.network_throttling;
+
+import com.google.common.collect.ImmutableMap;
+import com.helpers.SauceAppiumTestWatcher;
+import io.appium.java_client.AppiumBy;
+import io.appium.java_client.android.AndroidDriver;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.openqa.selenium.By;
+import org.openqa.selenium.MutableCapabilities;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Duration;
+
+import static com.helpers.Constants.SAUCE_EU_URL;
+import static com.helpers.Constants.SAUCE_US_URL;
+import static com.helpers.Constants.region;
+
+public class NetworkThrottlingAndroidRDCTest {
+
+ private final static By viewMenuButton = new AppiumBy.ByAccessibilityId("View menu");
+ private final static By webviewButton = By.xpath("//android.widget.TextView[@resource-id=\"com.saucelabs.mydemoapp.android:id/itemTV\" and @text=\"WebView\"]");
+ private final static By urlInput = By.id("com.saucelabs.mydemoapp.android:id/urlET");
+ private final static By goButton = new AppiumBy.ByAccessibilityId("Tap to view content of given url");
+ private final static By moreInfoButton = new AppiumBy.ByAccessibilityId("Show more info");
+
+ @Rule
+ public TestName name = new TestName();
+
+ // This rule allows us to set test status with Junit
+ @Rule
+ public SauceAppiumTestWatcher resultReportingTestWatcher = new SauceAppiumTestWatcher();
+
+ private AndroidDriver driver;
+ private WebDriverWait wait;
+
+ @Before
+ public void setUp() throws MalformedURLException {
+ MutableCapabilities capabilities = new MutableCapabilities();
+ MutableCapabilities sauceOptions = new MutableCapabilities();
+
+ capabilities.setCapability("platformName", "android");
+ capabilities.setCapability("appium:deviceName", ".*");
+ capabilities.setCapability("appium:automationName", "uiautomator2");
+
+ // Sauce capabilities
+ sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
+ sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
+ sauceOptions.setCapability("appiumVersion", "latest");
+
+ String appName = "SauceLabs-Demo-App.apk";
+
+ String testName = name.getMethodName();
+ switch (testName) {
+ case "regularNetworkSpeedTest":
+ System.out.println("Running regular network speed test");
+ capabilities.setCapability("appium:app", "storage:filename=" + appName);
+ sauceOptions.setCapability("name", "Regular network speed test");
+ break;
+ case "throttledNetworkProfileTest":
+ System.out.println("Running throttled 2G Slow test");
+ capabilities.setCapability("appium:app", "storage:filename=" + appName);
+ sauceOptions.setCapability("name", "Throttled 2G Slow test");
+ // Set a predefined network profile
+ sauceOptions.setCapability("networkProfile", "2G");
+ break;
+ case "throttledCustomNetworkConditionsTest":
+ System.out.println("Running throttled custom network conditions test");
+ capabilities.setCapability("appium:app", "storage:filename=" + appName);
+ sauceOptions.setCapability("name", "Throttled custom network conditions test");
+ // Set custom network conditions
+ sauceOptions.setCapability("networkConditions", ImmutableMap.of(
+ "downloadSpeed", 5000,
+ "uploadSpeed", 3000,
+ "latency", 200,
+ "loss", 5
+ ));
+ break;
+ case "throttledNetworkSpeedWebTest":
+ System.out.println("Running throttled 2G Slow web test");
+ capabilities.setCapability("browserName", "Chrome");
+ sauceOptions.setCapability("name", "Throttled 2G Slow web test");
+ // Set a predefined network profile
+ sauceOptions.setCapability("networkProfile", "2G");
+ break;
+ default:
+ System.out.println("No test configuration found for " + testName);
+ break;
+ }
+
+ capabilities.setCapability("sauce:options", sauceOptions);
+
+ try {
+ driver = new AndroidDriver(getAppiumUrl(), capabilities);
+ } catch (Exception e){
+ System.out.println("Error to create the Android Driver: " + e.getMessage());
+ throw e;
+ }
+
+ // Setting the driver so that we can report results
+ resultReportingTestWatcher.setDriver(driver);
+ }
+
+ @Test
+ public void regularNetworkSpeedTest() {
+ testNetworkConditions();
+ }
+
+ @Test
+ public void throttledNetworkProfileTest() {
+ testNetworkConditions();
+ }
+
+ @Test
+ public void throttledCustomNetworkConditionsTest() {
+ testNetworkConditions();
+ }
+
+ @Test
+ public void throttledNetworkSpeedWebTest() {
+ driver.get("https://www.fast.com");
+ wait = new WebDriverWait(driver, Duration.ofSeconds(30));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("show-more-details-link")));
+ }
+
+ private void testNetworkConditions() {
+ wait = new WebDriverWait(driver, Duration.ofSeconds(5));
+
+ wait.until(ExpectedConditions.presenceOfElementLocated(viewMenuButton)).click();
+ wait.until(ExpectedConditions.presenceOfElementLocated(webviewButton)).click();
+ wait.until(ExpectedConditions.presenceOfElementLocated(urlInput)).sendKeys("fast.com");
+ wait.until(ExpectedConditions.presenceOfElementLocated(goButton)).click();
+
+ wait = new WebDriverWait(driver, Duration.ofSeconds(45));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(moreInfoButton));
+ }
+
+ private URL getAppiumUrl() throws MalformedURLException {
+ switch (region) {
+ case "us":
+ return new URL(SAUCE_US_URL);
+ case "eu":
+ default:
+ return new URL(SAUCE_EU_URL);
+ }
+ }
+}
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/network_throttling/NetworkThrottlingIosRDCTest.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/network_throttling/NetworkThrottlingIosRDCTest.java
new file mode 100644
index 00000000..c9fae2d5
--- /dev/null
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/network_throttling/NetworkThrottlingIosRDCTest.java
@@ -0,0 +1,149 @@
+package com.examples.network_throttling;
+
+import com.google.common.collect.ImmutableMap;
+import com.helpers.SauceAppiumTestWatcher;
+import io.appium.java_client.ios.IOSDriver;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.openqa.selenium.By;
+import org.openqa.selenium.MutableCapabilities;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.WebDriverWait;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Duration;
+
+import static com.helpers.Constants.SAUCE_EU_URL;
+import static com.helpers.Constants.SAUCE_US_URL;
+import static com.helpers.Constants.region;
+
+public class NetworkThrottlingIosRDCTest {
+
+ private final static By moreTabButton = By.xpath("//XCUIElementTypeButton[@name=\"More-tab-item\"]");
+ private final static By webviewButton = By.xpath("//XCUIElementTypeButton[@name=\"Webview-menu-item\"]");
+ private final static By urlInput = By.xpath("//XCUIElementTypeTextField[@value=\"https://www.website.com\"]");
+ private final static By goButton = By.xpath("//XCUIElementTypeButton[@name=\"Go To Site\"]");
+ private final static By moreInfoLink = By.xpath("//XCUIElementTypeLink[@name=\"Show more info\"]");
+
+ @Rule
+ public TestName name = new TestName();
+
+ // This rule allows us to set test status with Junit
+ @Rule
+ public SauceAppiumTestWatcher resultReportingTestWatcher = new SauceAppiumTestWatcher();
+
+ private IOSDriver driver;
+ private WebDriverWait wait;
+
+ @Before
+ public void setUp() throws MalformedURLException {
+ MutableCapabilities capabilities = new MutableCapabilities();
+ MutableCapabilities sauceOptions = new MutableCapabilities();
+
+ capabilities.setCapability("platformName", "ios");
+ capabilities.setCapability("appium:deviceName", ".*");
+
+ // Sauce capabilities
+ sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
+ sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
+
+ String appName = "SauceLabs-Demo-App.ipa";
+
+ String testName = name.getMethodName();
+ switch (testName) {
+ case "regularNetworkSpeedTest":
+ System.out.println("Running regular network speed test");
+ capabilities.setCapability("appium:app", "storage:filename=" + appName);
+ sauceOptions.setCapability("name", "Regular network speed test");
+ break;
+ case "throttledNetworkProfileTest":
+ System.out.println("Running throttled 2G Slow test");
+ capabilities.setCapability("appium:app", "storage:filename=" + appName);
+ sauceOptions.setCapability("name", "Throttled 2G Slow test");
+ // Set a predefined network profile
+ sauceOptions.setCapability("networkProfile", "2G");
+ break;
+ case "throttledCustomNetworkConditionsTest":
+ System.out.println("Running throttled custom network conditions test");
+ capabilities.setCapability("appium:app", "storage:filename=" + appName);
+ sauceOptions.setCapability("name", "Throttled custom network conditions test");
+ // Set custom network conditions
+ sauceOptions.setCapability("networkConditions", ImmutableMap.of(
+ "downloadSpeed", 5000,
+ "uploadSpeed", 3000,
+ "latency", 200,
+ "loss", 5
+ ));
+ break;
+ case "throttledNetworkSpeedWebTest":
+ System.out.println("Running throttled 2G Slow web test");
+ capabilities.setCapability("browserName", "Safari");
+ sauceOptions.setCapability("name", "Throttled 2G Slow web test");
+ // Set a predefined network profile
+ sauceOptions.setCapability("networkProfile", "2G");
+ break;
+ default:
+ System.out.println("No test configuration found for " + testName);
+ break;
+ }
+
+ capabilities.setCapability("sauce:options", sauceOptions);
+
+ try {
+ driver = new IOSDriver(getAppiumUrl(), capabilities);
+ } catch (Exception e) {
+ System.out.println("Error to create the iOS Driver: " + e.getMessage());
+ throw e;
+ }
+
+ // Setting the driver so that we can report results
+ resultReportingTestWatcher.setDriver(driver);
+ }
+
+ @Test
+ public void regularNetworkSpeedTest() {
+ testNetworkConditions();
+ }
+
+ @Test
+ public void throttledNetworkProfileTest() {
+ testNetworkConditions();
+ }
+
+ @Test
+ public void throttledCustomNetworkConditionsTest() {
+ testNetworkConditions();
+ }
+
+ @Test
+ public void throttledNetworkSpeedWebTest() {
+ driver.get("https://www.fast.com");
+ wait = new WebDriverWait(driver, Duration.ofSeconds(30));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("show-more-details-link")));
+ }
+
+ private void testNetworkConditions() {
+ wait = new WebDriverWait(driver, Duration.ofSeconds(5));
+
+ wait.until(ExpectedConditions.presenceOfElementLocated(moreTabButton)).click();
+ wait.until(ExpectedConditions.presenceOfElementLocated(webviewButton)).click();
+ wait.until(ExpectedConditions.presenceOfElementLocated(urlInput)).sendKeys("fast.com");
+ wait.until(ExpectedConditions.presenceOfElementLocated(goButton)).click();
+
+ wait = new WebDriverWait(driver, Duration.ofSeconds(30));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(moreInfoLink));
+ }
+
+ private URL getAppiumUrl() throws MalformedURLException {
+ switch (region) {
+ case "us":
+ return new URL(SAUCE_US_URL);
+ case "eu":
+ default:
+ return new URL(SAUCE_EU_URL);
+ }
+ }
+}
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/network_throttling/README.md b/appium/appium-app/appium-app-examples/src/test/java/com/examples/network_throttling/README.md
new file mode 100644
index 00000000..00d54bd7
--- /dev/null
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/network_throttling/README.md
@@ -0,0 +1,77 @@
+# Using Network Throttling on Sauce Labs Real Devices
+This folder contains examples for using Network Throttling on real devices for:
+
+- [iOS real devices on the Sauce Labs Cloud](#run-tests-on-sauce-labs-ios-real-devices)
+- [Android real devices on the Sauce Labs Cloud](#run-tests-on-sauce-labs-android-real-devices)
+
+## Important information
+### Environment variables for Sauce Labs
+The examples in this repository use environment variables, make sure you've added the following
+
+ # For Sauce Labs Emulators/Simulators/Real devices
+ export SAUCE_USERNAME=********
+ export SAUCE_ACCESS_KEY=*******
+
+### Demo app(s)
+The Android demo app that has been used for all these tests can be found [here](https://github.com/saucelabs/my-demo-app-android/releases).
+The iOS demo app that has been used for all these tests can be found [here](https://github.com/saucelabs/my-demo-app-ios/releases).
+
+> The advice is to download the files to an `apps` folder in the root of this folder.
+
+Make sure that when you downloaded the files from the releases page, that you rename the apps to the following:
+
+- `mda-{#.#.#}.apk` => `SauceLabs-Demo-App.apk`
+
+**If you don't do that then the scripts can't find the apps!**
+
+### Upload apps to Sauce Storage
+If you want to use Android emulators, Android real devices, iOS simulators or iOS real devices in the Sauce Labs platform, you need to upload
+the apps to the Sauce Storage.
+
+#### Manual upload
+Execute the following steps to manually upload the apps:
+- Login to the Sauce Labs platform
+- Go to **LIVE** > **Mobile App**
+- Click on **App Upload** and OR select the folder, OR drag the apps to the screen to upload them
+
+#### Automated upload
+You can find a script to upload them to, OR the US, OR EU DC in [this](../../helpers/push_apps_to_storage.sh)-file. You can push the files to the
+storage by doing the following from the folder `appium-app-examples`:
+
+ cd src/test/java/com/helpers/
+ push_apps_to_storage.sh
+
+## Run tests on Sauce Labs iOS real devices
+If you want to run the tests on iOS Sauce Labs Real Devices then you can run the iOS test with
+
+ // If using the US DC
+ mvn clean test -Dtest=NetworkThrottlingIosRDCTest -Dregion=us
+
+ // If using the EU DC
+ mvn clean test -Dtest=NetworkThrottlingIosRDCTest -Dregion=eu
+
+The tests, which can be found [here](NetworkThrottlingIosRDCTest.java), will be executed on:
+
+- Any available iPhone or iPad
+
+> The devices use *dynamic* allocation, meaning they will try to find an available device that matches a regular
+expression.
+> NOTE: Make sure you are in the folder `appium-app-examples` when you execute this command
+
+
+## Run tests on Sauce Labs Android real devices
+If you want to run the tests on Android Sauce Labs Real Devices then you can run the Android test with
+
+ // If using the US DC
+ mvn clean test -Dtest=NetworkThrottlingAndroidRDCTest -Dregion=us
+
+ // If using the EU DC
+ mvn clean test -Dtest=NetworkThrottlingAndroidRDCTest -Dregion=eu
+
+The tests, which can be found [here](NetworkThrottlingAndroidRDCTest.java), will be executed on:
+
+- Any available Android device
+
+> The devices use *dynamic* allocation, meaning they will try to find an available device that matches a regular
+expression.
+> NOTE: Make sure you are in the folder `appium-app-examples` when you execute this command
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/AndroidNativeAppTest.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/AndroidNativeAppTest.java
index 267f5793..cff5ad37 100644
--- a/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/AndroidNativeAppTest.java
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/AndroidNativeAppTest.java
@@ -1,6 +1,8 @@
package com.examples.simple_example;
import com.helpers.SauceAppiumTestWatcher;
+import io.appium.java_client.AppiumBy;
+import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import org.junit.Before;
import org.junit.Rule;
@@ -25,9 +27,9 @@
*/
public class AndroidNativeAppTest {
- By productsScreenLocator = By.xpath("//*[@content-desc=\"products screen\"]");
- By sortButtonLocator = By.xpath("//*[@content-desc=\"sort button\"]");
- By sortModalLocator = By.xpath("//*[@content-desc=\"active option\"]");
+ By productsScreenLocator = By.id("com.saucelabs.mydemoapp.android:id/productTV");
+ By sortButtonLocator = AppiumBy.accessibilityId("Shows current sorting order and displays available sorting options");
+ By sortModalLocator = By.id("com.saucelabs.mydemoapp.android:id/sortTV");
@Rule
@@ -59,34 +61,38 @@ public void setup() throws MalformedURLException {
}
// For all capabilities please check
- // http://appium.io/docs/en/writing-running-appium/caps/#general-capabilities
+ // https://appium.io/docs/en/2.0/guides/caps/
// Use the platform configuration https://saucelabs.com/platform/platform-configurator#/
// to find the emulators/real devices names, OS versions and appium versions you can use for your testings
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("appium:automationName", "UiAutomator2");
if (rdc.equals("true")) {
- //Allocate any avilable samsung device with Android version 12
+ //Allocate any available samsung device with Android version 12
capabilities.setCapability("appium:deviceName", "Samsung.*");
sauceOptions.setCapability("resigningEnabled", true);
sauceOptions.setCapability("sauceLabsNetworkCaptureEnabled", true);
+ sauceOptions.setCapability("appiumVersion", "latest");
}
else {
capabilities.setCapability("appium:deviceName", "Android GoogleAPI Emulator");
+ capabilities.setCapability("appium:appWaitActivity", ".view.activities.MainActivity");
+ sauceOptions.setCapability("appiumVersion", "latest");
}
capabilities.setCapability("appium:platformVersion", "12");
- String appName = "Android.MyDemoAppRN.apk";
+ String appName = "mda-2.1.0-24.apk";
capabilities.setCapability("appium:app", "storage:filename=" +appName);
- capabilities.setCapability("appium:appWaitActivity","com.saucelabs.mydemoapp.rn.MainActivity");
// Sauce capabilities
sauceOptions.setCapability("name", name.getMethodName());
+
sauceOptions.setCapability("build", "myApp-job-1");
List tags = Arrays.asList("sauceDemo", "Android", "Demo");
sauceOptions.setCapability("tags", tags);
sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
+
capabilities.setCapability("sauce:options", sauceOptions);
try {
@@ -95,6 +101,8 @@ public void setup() throws MalformedURLException {
System.out.println("Error to create Android Driver: " + e.getMessage());
return;
}
+
+ System.out.println("Job ID is: " + driver.getCapabilities().getCapability("appium:jobUuid"));
//Setting the driver so that we can report results
resultReportingTestWatcher.setDriver(driver);
}
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/IOSNativeAppTest.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/IOSNativeAppTest.java
index 4346585f..7d92c489 100644
--- a/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/IOSNativeAppTest.java
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/IOSNativeAppTest.java
@@ -1,7 +1,19 @@
package com.examples.simple_example;
+import static com.helpers.Constants.SAUCE_EU_URL;
+import static com.helpers.Constants.SAUCE_US_URL;
+import static com.helpers.Constants.rdc;
+import static com.helpers.Constants.region;
+import static org.assertj.core.api.Assertions.assertThat;
+
import com.helpers.SauceAppiumTestWatcher;
+import io.appium.java_client.AppiumBy;
import io.appium.java_client.ios.IOSDriver;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -11,109 +23,91 @@
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.time.Duration;
-import java.util.Arrays;
-import java.util.List;
-
-import static com.helpers.Constants.*;
-import static org.assertj.core.api.Assertions.assertThat;
-
public class IOSNativeAppTest {
- By productsScreenLocator = By.id("products screen");
- By sortButtonLocator = By.id("sort button");
- By sortModalLocator = By.id("active option");
-
- @Rule
- public TestName name = new TestName();
-
- //This rule allows us to set test status with Junit
- @Rule
- public SauceAppiumTestWatcher resultReportingTestWatcher = new SauceAppiumTestWatcher();
-
- private IOSDriver driver;
-
- @Before
- public void setUp() throws MalformedURLException {
- System.out.println("Sauce iOS Native App - Before hook");
-
- MutableCapabilities capabilities = new MutableCapabilities();
- MutableCapabilities sauceOptions = new MutableCapabilities();
- URL url;
- String appName;
-
- switch (region) {
- case "us":
- url = new URL(SAUCE_US_URL);
- break;
- case "eu":
- default:
- url = new URL(SAUCE_EU_URL);
- break;
- }
-
- // For all capabilities please check
- // http://appium.io/docs/en/writing-running-appium/caps/#general-capabilities
- // Use the platform configuration https://saucelabs.com/platform/platform-configurator#/
- // to find the simulators/real device names, OS versions and appium versions you can use for your testings
-
- capabilities.setCapability("platformName", "iOS");
- capabilities.setCapability("appium:automationName", "XCuiTest");
- if (rdc.equals("true")) {
- //Allocate any avilable iPhone device with version 14
- capabilities.setCapability("appium:deviceName", "iPhone.*");
- appName = "iOS.MyDemoAppRN.ipa";
-
- sauceOptions.setCapability("resigningEnabled", true);
- sauceOptions.setCapability("sauceLabsNetworkCaptureEnabled", true);
- }
- else {
- capabilities.setCapability("appium:deviceName", "iPhone 11 Simulator");
- appName = "iOS.MyDemoAppRN.zip";
- }
- capabilities.setCapability("appium:platformVersion", "14");
- capabilities.setCapability("app", "storage:filename=" + appName);
- sauceOptions.setCapability("name", name.getMethodName());
- sauceOptions.setCapability("build", "myApp-job-1");
- List tags = Arrays.asList("sauceDemo_ios", "iOS", "Demo");
- sauceOptions.setCapability("tags", tags);
- sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
- sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
- capabilities.setCapability("sauce:options", sauceOptions);
-
- try {
- driver = new IOSDriver(url, capabilities);
- } catch (Exception e){
- System.out.println("Error to create iOS Driver: " + e.getMessage());
- }
+ @Rule public TestName name = new TestName();
+ // This rule allows us to set test status with Junit
+ @Rule public SauceAppiumTestWatcher resultReportingTestWatcher = new SauceAppiumTestWatcher();
+ By productsScreenLocator = AppiumBy.accessibilityId("Products");
+ By sortButtonLocator = AppiumBy.iOSClassChain("**/XCUIElementTypeButton[`name == \"Button\"`]");
+ By sortModalLocator = AppiumBy.accessibilityId("Sort by:");
+ private IOSDriver driver;
+
+ @Before
+ public void setUp() throws MalformedURLException {
+ System.out.println("Sauce iOS Native App - Before hook");
+
+ MutableCapabilities capabilities = new MutableCapabilities();
+ MutableCapabilities sauceOptions = new MutableCapabilities();
+ URL url;
+ String appName;
+
+ switch (region) {
+ case "us":
+ url = new URL(SAUCE_US_URL);
+ break;
+ case "eu":
+ default:
+ url = new URL(SAUCE_EU_URL);
+ break;
+ }
- //Setting the driver so that we can report results
- resultReportingTestWatcher.setDriver(driver);
+ // For all capabilities please check
+ // https://appium.io/docs/en/2.0/guides/caps/
+ // Use the platform configuration https://saucelabs.com/platform/platform-configurator#/
+ // to find the simulators/real device names, OS versions and appium versions you can use for
+ // your testings
+ capabilities.setCapability("platformName", "iOS");
+ capabilities.setCapability("appium:automationName", "XCuiTest");
+ if (rdc.equals("true")) {
+ // Allocate any available iPhone device with version 14
+ capabilities.setCapability("appium:deviceName", "iPhone.*");
+ appName = "SauceLabs-Demo-App.ipa";
+ sauceOptions.setCapability("resigningEnabled", true);
+ sauceOptions.setCapability("sauceLabsNetworkCaptureEnabled", true);
+ } else {
+ capabilities.setCapability("appium:deviceName", "iPhone 11 Simulator");
+ appName = "SauceLabs-Demo-App.Simulator.zip";
+ }
+ capabilities.setCapability("appium:app", "storage:filename=" + appName);
+ capabilities.setCapability("appium:platformVersion", "14");
+ sauceOptions.setCapability("name", name.getMethodName());
+ sauceOptions.setCapability("build", "myApp-job-1");
+ List tags = Arrays.asList("sauceDemo_ios", "iOS", "Demo");
+ sauceOptions.setCapability("tags", tags);
+ sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
+ sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
+ capabilities.setCapability("sauce:options", sauceOptions);
+
+ try {
+ driver = new IOSDriver(url, capabilities);
+ } catch (Exception e) {
+ System.out.println("Error to create iOS Driver: " + e.getMessage());
}
- @Test
- public void verifyInProductsPage() throws MalformedURLException {
+ // Setting the driver so that we can report results
+ resultReportingTestWatcher.setDriver(driver);
+ }
- WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
- wait.until(ExpectedConditions.visibilityOfElementLocated(productsScreenLocator));
+ @Test
+ public void verifyPromptSortModal() {
- driver.findElement(sortButtonLocator).click();
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(productsScreenLocator));
- //Verify the sort modal is displayed on screen
- assertThat(isDisplayed(sortModalLocator, 5)).as("Verify sort modal is displayed").isTrue();
+ driver.findElement(sortButtonLocator).click();
- }
+ // Verify the sort modal is displayed on screen
+ assertThat(isDisplayed(sortModalLocator, 5)).as("Verify sort modal is displayed").isTrue();
+ }
- public Boolean isDisplayed(By locator, long timeoutInSeconds) {
- try {
- WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeoutInSeconds));
- wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
- } catch (org.openqa.selenium.TimeoutException exception) {
- return false;
- }
- return true;
+ public Boolean isDisplayed(By locator, long timeoutInSeconds) {
+ try {
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeoutInSeconds));
+ wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
+ } catch (org.openqa.selenium.TimeoutException exception) {
+ return false;
}
-
+ return true;
+ }
}
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/README.md b/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/README.md
index dde62025..7b3b379a 100644
--- a/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/README.md
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/simple_example/README.md
@@ -16,7 +16,8 @@ The examples in this repository use environment variables, make sure you've adde
export SAUCE_ACCESS_KEY=*******
### Demo app(s)
-The demo app that has been used for all these tests can be found [here](https://github.com/saucelabs/my-demo-app-rn/releases).
+The Android demo app that has been used for all these tests can be found [here](https://github.com/saucelabs/my-demo-app-android/releases).
+The iOS demo app that has been used for all these tests can be found [here](https://github.com/saucelabs/my-demo-app-ios/releases).
Be aware of the fact that and iOS simulator uses a different build then a iOS real device. So please check the file you
download.
@@ -24,9 +25,7 @@ download.
Make sure that when you downloaded the files from the releases page, that you rename the apps to the following:
-- `Android-MyDemoAppRN.{#.#.#}.build-{####}.apk` => `Android.MyDemoAppRN.apk`
-- `iOS-Real-Device-MyRNDemoApp.{#.#.#}-{####}.ipa` => `iOS.MyDemoAppRN.ipa`
-- `iOS-Simulator-MyRNDemoApp.{#.#.#}-{####}.zip` => `iOS.MyDemoAppRN.zip`
+- `mda-{#.#.#}.apk` => `SauceLabs-Demo-App.apk`
**If you don't do that then the scripts can't find the apps!**
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/up_download_file/DownloadImageFromAndroidRealDevice.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/up_download_file/DownloadImageFromAndroidRealDevice.java
index b3213373..424b1c6d 100644
--- a/appium/appium-app/appium-app-examples/src/test/java/com/examples/up_download_file/DownloadImageFromAndroidRealDevice.java
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/up_download_file/DownloadImageFromAndroidRealDevice.java
@@ -32,7 +32,7 @@ public class DownloadImageFromAndroidRealDevice {
int currentPhotos = 0;
String deviceFilePath = "/storage/self/primary/sauce-bot-coding.png";
- String downloadFolder = "src/test/java/com/appium_app/up_download_file/samsung_real_device";
+ String downloadFolder = "src/test/java/com/examples/up_download_file/samsung_real_device";
//This rule allows us to set test status with Junit
@Rule
@@ -58,8 +58,8 @@ public void setup() throws IOException {
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("appium:automationName", "UiAutomator2");
- capabilities.setCapability("appium:deviceName", "Samsung Galaxy S9");
- capabilities.setCapability("appium:platformVersion", "10");
+ capabilities.setCapability("appium:deviceName", "Samsung Galaxy S23");
+ capabilities.setCapability("appium:platformVersion", "13");
capabilities.setCapability("appium:newCommandTimeout", 240);
capabilities.setCapability("appium:browserName", "chrome");
capabilities.setCapability("appium:autoGrantPermissions", true);
@@ -71,6 +71,7 @@ public void setup() throws IOException {
sauceOptions.setCapability("tags", tags);
sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME"));
sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
+ sauceOptions.setCapability("appiumVersion", "stable");
capabilities.setCapability("sauce:options", sauceOptions);
@@ -98,12 +99,17 @@ public void downloadFileFromRealDevice() throws InterruptedException, IOExceptio
System.out.println("Sauce - number of photos before upload: " + currentPhotos );
// The file we want to upload
- String codingBot = "src/test/java/com/appium_app/up_download_file/sauce-bot-coding.png";
+ String codingBot = "src/test/java/com/examples/up_download_file/sauce-bot-coding.png";
File codingBotFile = new File(codingBot);
// Push the file to the device
// This is the `tricky` part, you need to know the file structure of the device and where you can download the file from.
// We checked this structure with the VUSB offering of Sauce Labs for private devices.
- driver.pushFile(deviceFilePath, codingBotFile);
+ try {
+ driver.pushFile(deviceFilePath, codingBotFile);
+ } catch(Exception ex)
+ {
+ System.out.println("Error: " + ex.getMessage());
+ }
// wait till it is uploaded
boolean bPhotoUpload = samsungGallery.waitUploadPhoto(currentPhotos, 5);
@@ -125,7 +131,7 @@ public void downloadFileFromRealDevice() throws InterruptedException, IOExceptio
ImageIO.write(image, "png", f);
// Now verify that the file does exist locally
- assertThat(f.exists()).as("The file we downloaded from the device, doesm't exist locally").isTrue();
+ assertThat(f.exists()).as("The file we downloaded from the device, doesn't exist locally").isTrue();
// This is not need only for the video
waiting(2);
}
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/examples/up_download_file/SamsungGallery.java b/appium/appium-app/appium-app-examples/src/test/java/com/examples/up_download_file/SamsungGallery.java
index fa126745..0d6b7bf0 100644
--- a/appium/appium-app/appium-app-examples/src/test/java/com/examples/up_download_file/SamsungGallery.java
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/examples/up_download_file/SamsungGallery.java
@@ -1,5 +1,7 @@
package com.examples.up_download_file;
+import com.google.common.collect.ImmutableMap;
+import io.appium.java_client.AppiumBy;
import io.appium.java_client.android.Activity;
import io.appium.java_client.android.AndroidDriver;
import org.openqa.selenium.By;
@@ -15,16 +17,19 @@ public class SamsungGallery {
private AndroidDriver driver;
- private String photos = "com.sec.android.gallery3d:id/recycler_view_item";
- private String deleteButton ="com.sec.android.gallery3d:id/btn_delete";
- private String confirmDeleteButton = "com.sec.android.gallery3d:id/button1";
+ private String photos = "//android.widget.FrameLayout[@content-desc='Button']";
+
+ private String deleteButton ="Delete";
+ private String confirmDeleteButton = "android:id/button1";
public SamsungGallery(AndroidDriver driver) {
this.driver = driver;
}
public void open() {
- driver.startActivity(new Activity("com.sec.android.gallery3d", "com.samsung.android.gallery.app.activity.GalleryActivity"));
+ driver.executeScript("mobile: activateApp", ImmutableMap.of(
+ "appId", "com.sec.android.gallery3d"
+ ));
}
@@ -32,7 +37,7 @@ public void openPhoto(String which){
int whichPhoto = (which == "first" ? 0 : this.amountOfPhotos()-1);
// open the photo
- List photosList = driver.findElements(By.id(photos));
+ List photosList = driver.findElements(By.xpath(photos));
photosList.get(whichPhoto).click();
}
@@ -46,14 +51,15 @@ public void deletePhoto(String which){
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
- final WebElement deleteImgBtn = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(deleteButton)));
+ final WebElement deleteImgBtn = wait.until(ExpectedConditions.visibilityOfElementLocated(new AppiumBy.ByAccessibilityId(deleteButton)));
deleteImgBtn.click();
driver.findElement(By.id(confirmDeleteButton)).click();
}
public int amountOfPhotos(){
- return (driver.findElements(By.id(photos)).size());
+ return (driver.findElements(By.xpath(photos)).size());
+
}
/**
diff --git a/appium/appium-app/appium-app-examples/src/test/java/com/helpers/Constants.java b/appium/appium-app/appium-app-examples/src/test/java/com/helpers/Constants.java
index ea538e48..9b876ed3 100644
--- a/appium/appium-app/appium-app-examples/src/test/java/com/helpers/Constants.java
+++ b/appium/appium-app/appium-app-examples/src/test/java/com/helpers/Constants.java
@@ -1,11 +1,9 @@
package com.helpers;
public class Constants {
- public static final String region = System.getProperty("region", "eu");
- public static final String host = System.getProperty("host", "saucelabs");
- public static final String rdc = System.getProperty("rdc", "true");
-
- public static final String SAUCE_EU_URL = "https://ondemand.eu-central-1.saucelabs.com/wd/hub";
- public static final String SAUCE_US_URL = "https://ondemand.us-west-1.saucelabs.com:443/wd/hub";
+ public static final String region = System.getProperty("region", "eu");
+ public static final String rdc = System.getProperty("rdc", "true");
+ public static final String SAUCE_EU_URL = "https://ondemand.eu-central-1.saucelabs.com/wd/hub";
+ public static final String SAUCE_US_URL = "https://ondemand.us-west-1.saucelabs.com:443/wd/hub";
}
diff --git a/appium/appium-web/appium-web-examples/pom.xml b/appium/appium-web/appium-web-examples/pom.xml
index 65f6a9df..527dcae5 100644
--- a/appium/appium-web/appium-web-examples/pom.xml
+++ b/appium/appium-web/appium-web-examples/pom.xml
@@ -2,19 +2,19 @@
-
- demo-java
- com.saucelabs
- 1.0-SNAPSHOT
- ../../../pom.xml
-
+
4.0.0
+ com.saucelabsappium-web-examples
+ 1.0-SNAPSHOT
+
+ Sauce Labs Appium Web
- 3.0.0-M5
- 8.3.0
+ 3.5.1
+ 9.3.0
+ 4.25.0
@@ -24,13 +24,13 @@
commons-loggingcommons-logging
- 1.2
+ 1.3.4org.assertjassertj-core
- 3.10.0
+ 3.26.3
@@ -38,6 +38,35 @@
java-client${appium.version}test
+
+
+ org.seleniumhq.selenium
+ selenium-api
+
+
+ org.seleniumhq.selenium
+ selenium-remote-driver
+
+
+ org.seleniumhq.selenium
+ selenium-support
+
+
+
+
+ org.seleniumhq.selenium
+ selenium-api
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-remote-driver
+ ${selenium.version}
+
+
+ org.seleniumhq.selenium
+ selenium-support
+ ${selenium.version}
diff --git a/appium/appium-web/appium-web-examples/src/test/java/com/examples/simple_example/AndroidWebAppTest.java b/appium/appium-web/appium-web-examples/src/test/java/com/examples/simple_example/AndroidWebAppTest.java
index c6483c09..e9cbe0ea 100644
--- a/appium/appium-web/appium-web-examples/src/test/java/com/examples/simple_example/AndroidWebAppTest.java
+++ b/appium/appium-web/appium-web-examples/src/test/java/com/examples/simple_example/AndroidWebAppTest.java
@@ -67,11 +67,11 @@ public void setup() throws MalformedURLException {
capabilities.setCapability("appium:automationName", "UiAutomator2");
if (rdc.equals("true")) {
capabilities.setCapability("appium:deviceName", "samsung.*");
- sauceOptions.setCapability("appiumVersion", "2.0.0");
+ sauceOptions.setCapability("appiumVersion", "latest");
}
else {
capabilities.setCapability("appium:deviceName", "Android GoogleAPI Emulator");
- sauceOptions.setCapability("appiumVersion", "2.0.0-beta66");
+ sauceOptions.setCapability("appiumVersion", "latest");
}
capabilities.setCapability("appium:platformVersion", "13");
diff --git a/best-practice/pom.xml b/best-practice/pom.xml
index de5e46ad..37165906 100644
--- a/best-practice/pom.xml
+++ b/best-practice/pom.xml
@@ -1,55 +1,65 @@
-
-
- demo-java
- com.saucelabs
- 1.0-SNAPSHOT
-
- 4.0.0
-
- best-practice
-
-
- 4.10.0
-
-
-
-
- com.saucelabs
- saucebindings-junit4
- ${sauce_junit4.version}
- test
-
-
-
- org.seleniumhq.selenium
- selenium-api
- ${selenium.version}
-
-
-
- org.seleniumhq.selenium
- selenium-java
- ${selenium.version}
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- ${maven.surefire.version}
-
- all
- 100
- true
- false
-
-
-
-
+
+ 4.0.0
+
+ com.saucelabs
+ best-practice
+ 1.0-SNAPSHOT
+
+ Sauce Labs Best Practices
+
+
+ 4.25.0
+ 1.5.0
+ 3.5.1
+ 9.3.0
+
+
+
+
+ com.saucelabs
+ saucebindings-junit4
+ ${sauce_junit4.version}
+ test
+
+
+
+ org.seleniumhq.selenium
+ selenium-api
+ ${selenium.version}
+
+
+
+ org.seleniumhq.selenium
+ selenium-java
+ ${selenium.version}
+
+
+
+ io.appium
+ java-client
+ ${appium.version}
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven.surefire.version}
+
+ methods
+ 100
+ true
+ false
+
+
+
+
diff --git a/best-practice/src/test/java/com/saucedemo/AbstractTestBase.java b/best-practice/src/test/java/com/saucedemo/AbstractTestBase.java
index 5a39cea7..778941fb 100644
--- a/best-practice/src/test/java/com/saucedemo/AbstractTestBase.java
+++ b/best-practice/src/test/java/com/saucedemo/AbstractTestBase.java
@@ -1,52 +1,47 @@
package com.saucedemo;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import org.junit.Rule;
import org.junit.rules.TestName;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.openqa.selenium.remote.RemoteWebDriver;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-/**
- * All Tests need to extend this class to get the correct behavior.
- */
+/** All Tests need to extend this class to get the correct behavior. */
public abstract class AbstractTestBase {
- public static final String buildName = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
+ public static final String buildName =
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
+ protected static final String SAUCE_USERNAME = System.getenv("SAUCE_USERNAME");
+ protected static final String SAUCE_ACCESS_KEY = System.getenv("SAUCE_ACCESS_KEY");
- @Rule
- public TestName testName = new TestName() {
+ @Rule
+ public TestName testName =
+ new TestName() {
public String getMethodName() {
- return String.format("%s", super.getMethodName());
+ return String.format("%s", super.getMethodName());
}
- };
- @Rule
- public SauceTestWatcher resultReportingTestWatcher = new SauceTestWatcher();
+ };
- protected static final String SAUCE_USERNAME = System.getenv("SAUCE_USERNAME");
- protected static final String SAUCE_ACCESS_KEY = System.getenv("SAUCE_ACCESS_KEY");
- protected static final String SCREENER_API_KEY = System.getenv("SCREENER_API_KEY");
- protected RemoteWebDriver driver;
+ @Rule public SauceTestWatcher resultReportingTestWatcher = new SauceTestWatcher();
+ protected RemoteWebDriver driver;
- /**
- * Custom TestWatcher for Sauce Labs projects.
- */
- public class SauceTestWatcher extends TestWatcher {
- @Override
- protected void succeeded(Description description) {
- if (driver != null) {
- driver.executeScript("sauce:job-result=passed");
- driver.quit();
- }
- }
+ /** Custom TestWatcher for Sauce Labs projects. */
+ public class SauceTestWatcher extends TestWatcher {
+ @Override
+ protected void succeeded(Description description) {
+ if (driver != null) {
+ driver.executeScript("sauce:job-result=passed");
+ driver.quit();
+ }
+ }
- @Override
- protected void failed(Throwable e, Description description) {
- if (driver != null) {
- driver.executeScript("sauce:job-result=failed");
- driver.quit();
- }
- }
+ @Override
+ protected void failed(Throwable e, Description description) {
+ if (driver != null) {
+ driver.executeScript("sauce:job-result=failed");
+ driver.quit();
+ }
}
+ }
}
diff --git a/best-practice/src/test/java/com/saucedemo/Constants.java b/best-practice/src/test/java/com/saucedemo/Constants.java
index 7aa64b6e..2885c609 100644
--- a/best-practice/src/test/java/com/saucedemo/Constants.java
+++ b/best-practice/src/test/java/com/saucedemo/Constants.java
@@ -1,12 +1,9 @@
package com.saucedemo;
public class Constants {
- public static final String region = System.getProperty("region", "us");
- public static final String SAUCE_EU_URL = "https://ondemand.eu-central-1.saucelabs.com:443/wd/hub";
- public static final String SAUCE_US_URL = "https://ondemand.us-west-1.saucelabs.com:443/wd/hub";
-
- public static final String SAUCE_USERNAME = System.getenv("SAUCE_USERNAME");
- public static final String SAUCE_ACCESS_KEY = System.getenv("SAUCE_ACCESS_KEY");
-
+ public static final String region = System.getProperty("region", "us");
+ public static final String SAUCE_EU_URL =
+ "https://ondemand.eu-central-1.saucelabs.com:443/wd/hub";
+ public static final String SAUCE_US_URL = "https://ondemand.us-west-1.saucelabs.com:443/wd/hub";
+ public static final String WEB_URL = "https://www.saucedemo.com/";
}
-
diff --git a/best-practice/src/test/java/com/saucedemo/Endpoints.java b/best-practice/src/test/java/com/saucedemo/Endpoints.java
index 19741516..30e9ec5c 100644
--- a/best-practice/src/test/java/com/saucedemo/Endpoints.java
+++ b/best-practice/src/test/java/com/saucedemo/Endpoints.java
@@ -3,34 +3,31 @@
import java.net.MalformedURLException;
import java.net.URL;
-/**
- * URL to the desired Data Center.
- */
+/** URL to the desired Data Center. */
public class Endpoints {
- /**
- * Emulator/Simulator Hub.
- *
- * @return URL of Emulator/Simulator Hub
- */
- public static URL getEmuSimHub() throws MalformedURLException {
- String user = System.getenv("SAUCE_USERNAME");
- String key = System.getenv("SAUCE_ACCESS_KEY");
- return new URL("https://" + user + ":" + key
- + "@ondemand.saucelabs.com:443/wd/hub");
- }
+ /**
+ * Emulator/Simulator Hub.
+ *
+ * @return URL of Emulator/Simulator Hub
+ */
+ public static URL getEmuSimHub() throws MalformedURLException {
+ String user = System.getenv("SAUCE_USERNAME");
+ String key = System.getenv("SAUCE_ACCESS_KEY");
+ return new URL("https://" + user + ":" + key + "@ondemand.us-west-1.saucelabs.com/wd/hub");
+ }
- public static URL getScreenerHub() throws MalformedURLException {
- return new URL("https://hub.screener.io/wd/hub");
- }
+ public static URL getScreenerHub() throws MalformedURLException {
+ return new URL("https://hub.screener.io/wd/hub");
+ }
- /**
- * Real Device Hub.
- *
- * @return URL for Real Device Hub
- */
- public static URL getRealDevicesHub() throws MalformedURLException {
- return new URL("https://" + System.getenv("SAUCE_USERNAME") + ":"
- + System.getenv("SAUCE_ACCESS_KEY")
- + "@ondemand.us-west-1.saucelabs.com/wd/hub");
- }
+ /**
+ * Real Device Hub.
+ *
+ * @return URL for Real Device Hub
+ */
+ public static URL getRealDevicesHub() throws MalformedURLException {
+ String user = System.getenv("SAUCE_USERNAME");
+ String key = System.getenv("SAUCE_ACCESS_KEY");
+ return new URL("https://" + user + ":" + key + "@ondemand.us-west-1.saucelabs.com/wd/hub");
+ }
}
diff --git a/best-practice/src/test/java/com/saucedemo/MobileTestsBase.java b/best-practice/src/test/java/com/saucedemo/MobileTestsBase.java
index 4aa45d7d..8525dfd9 100644
--- a/best-practice/src/test/java/com/saucedemo/MobileTestsBase.java
+++ b/best-practice/src/test/java/com/saucedemo/MobileTestsBase.java
@@ -1,19 +1,15 @@
package com.saucedemo;
import io.appium.java_client.AppiumDriver;
-import org.openqa.selenium.WebElement;
-/**
- * Mobile Tests extend this class to ensure the correct driver.
- */
+/** Mobile Tests extend this class to ensure the correct driver. */
public abstract class MobileTestsBase extends AbstractTestBase {
- /**
- * This casts RemoteWebDriver to AppiumDriver for mobile tests.
- *
- * @return instance of Appium Driver
- */
- @SuppressWarnings("unchecked")
- public AppiumDriver getDriver() {
- return (AppiumDriver) driver;
- }
+ /**
+ * This casts RemoteWebDriver to AppiumDriver for mobile tests.
+ *
+ * @return instance of Appium Driver
+ */
+ public AppiumDriver getDriver() {
+ return (AppiumDriver) driver;
+ }
}
diff --git a/best-practice/src/test/java/com/saucedemo/pages/AbstractBasePage.java b/best-practice/src/test/java/com/saucedemo/pages/AbstractBasePage.java
index f5f2e8a2..28cce158 100644
--- a/best-practice/src/test/java/com/saucedemo/pages/AbstractBasePage.java
+++ b/best-practice/src/test/java/com/saucedemo/pages/AbstractBasePage.java
@@ -1,43 +1,41 @@
package com.saucedemo.pages;
-import org.openqa.selenium.remote.RemoteWebDriver;
+
+import static com.saucedemo.Constants.WEB_URL;
import java.util.Map;
+import org.openqa.selenium.remote.RemoteWebDriver;
-/**
- * All page objects inherit from the base page.
- */
+/** All page objects inherit from the base page. */
public abstract class AbstractBasePage {
- protected final RemoteWebDriver driver;
-
- public RemoteWebDriver getDriver() {
- return this.driver;
- }
-
- public AbstractBasePage(RemoteWebDriver driver) {
- this.driver = driver;
- }
-
- /**
- * Executes a visual test.
- */
- public final void takeSnapshot() {
- driver.executeScript("/*@visual.snapshot*/", this.getClass().getSimpleName());
- }
-
- public void visit() {
- driver.get("https://www.saucedemo.com/" + getPagePart());
- }
-
- public abstract String getPagePart();
-
- /**
- * Screener uses this JavaScript to provide results of visual snapshot.
- *
- * @return Map of visual results
- */
- @SuppressWarnings("unchecked")
- public Map getVisualResults() {
- return (Map) driver.executeScript("/*@visual.end*/");
- }
+ protected final RemoteWebDriver driver;
+
+ public AbstractBasePage(RemoteWebDriver driver) {
+ this.driver = driver;
+ }
+
+ public RemoteWebDriver getDriver() {
+ return this.driver;
+ }
+
+ /** Executes a visual test. */
+ public final void takeSnapshot() {
+ driver.executeScript("/*@visual.snapshot*/", this.getClass().getSimpleName());
+ }
+
+ public void visit() {
+ driver.get(WEB_URL + getPagePart());
+ }
+
+ public abstract String getPagePart();
+
+ /**
+ * Screener uses this JavaScript to provide results of visual snapshot.
+ *
+ * @return Map of visual results
+ */
+ @SuppressWarnings("unchecked")
+ public Map getVisualResults() {
+ return (Map) driver.executeScript("/*@visual.end*/");
+ }
}
diff --git a/best-practice/src/test/java/com/saucedemo/pages/CheckoutStepOnePage.java b/best-practice/src/test/java/com/saucedemo/pages/CheckoutStepOnePage.java
index cdfa8c0d..6c91249d 100644
--- a/best-practice/src/test/java/com/saucedemo/pages/CheckoutStepOnePage.java
+++ b/best-practice/src/test/java/com/saucedemo/pages/CheckoutStepOnePage.java
@@ -2,16 +2,14 @@
import org.openqa.selenium.remote.RemoteWebDriver;
-/**
- * Page Object for Checkout Step One.
- */
+/** Page Object for Checkout Step One. */
public class CheckoutStepOnePage extends AbstractBasePage {
- public CheckoutStepOnePage(RemoteWebDriver driver) {
- super(driver);
- }
+ public CheckoutStepOnePage(RemoteWebDriver driver) {
+ super(driver);
+ }
- @Override
- public String getPagePart() {
- return "checkout-step-one.html";
- }
+ @Override
+ public String getPagePart() {
+ return "checkout-step-one.html";
+ }
}
diff --git a/best-practice/src/test/java/com/saucedemo/pages/LoginPage.java b/best-practice/src/test/java/com/saucedemo/pages/LoginPage.java
index 7d0a2266..d5165516 100644
--- a/best-practice/src/test/java/com/saucedemo/pages/LoginPage.java
+++ b/best-practice/src/test/java/com/saucedemo/pages/LoginPage.java
@@ -1,62 +1,59 @@
package com.saucedemo.pages;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
-import java.time.Duration;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Page Object for Login page.
- */
+/** Page Object for Login page. */
public class LoginPage extends AbstractBasePage {
- private final By usernameFieldLocator = By.id("user-name");
- private final By passwordFieldLocator = By.id("password");
- private final By submitButtonLocator = By.id("login-button");
-
- public LoginPage(RemoteWebDriver driver) {
- super(driver);
- }
-
- @Override
- public String getPagePart() {
- return "";
- }
-
- /**
- * Log in on page.
- *
- * @param userName the name of the user to log in
- */
- public void login(String userName) {
- //Create an instance of a Selenium explicit wait to dynamically wait for an element
- WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
- //wait for the user name field to be visible and store that element into a variable
- wait.until((driver) -> driver.findElement(usernameFieldLocator).isDisplayed());
-
- WebElement userNameField = driver.findElement(usernameFieldLocator);
- WebElement passwordField = driver.findElement(passwordFieldLocator);
- WebElement submitButton = driver.findElement(submitButtonLocator);
-
- userNameField.sendKeys(userName);
- passwordField.sendKeys("secret_sauce");
- submitButton.click();
- }
-
- /**
- * How long it takes to load the page.
- *
- * @return duration of time to load the page
- */
- @SuppressWarnings("unchecked")
- public Integer getPageLoadTime() {
- HashMap metrics = new HashMap<>();
- metrics.put("type", "sauce:performance");
- Map perfMetrics = (Map) driver.executeScript("sauce:log", metrics);
- return Integer.parseInt(perfMetrics.get("load").toString());
- }
-
+ private final By usernameFieldLocator = By.id("user-name");
+ private final By passwordFieldLocator = By.id("password");
+ private final By submitButtonLocator = By.id("login-button");
+
+ public LoginPage(RemoteWebDriver driver) {
+ super(driver);
+ }
+
+ @Override
+ public String getPagePart() {
+ return "";
+ }
+
+ /**
+ * Log in on page.
+ *
+ * @param userName the name of the user to log in
+ */
+ public void login(String userName) {
+ // Create an instance of a Selenium explicit wait to dynamically wait for an element
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
+ // wait for the user name field to be visible and store that element into a variable
+ wait.until((driver) -> driver.findElement(usernameFieldLocator).isDisplayed());
+
+ WebElement userNameField = driver.findElement(usernameFieldLocator);
+ WebElement passwordField = driver.findElement(passwordFieldLocator);
+ WebElement submitButton = driver.findElement(submitButtonLocator);
+
+ userNameField.sendKeys(userName);
+ passwordField.sendKeys("secret_sauce");
+ submitButton.click();
+ }
+
+ /**
+ * How long it takes to load the page.
+ *
+ * @return duration of time to load the page
+ */
+ @SuppressWarnings("unchecked")
+ public Integer getPageLoadTime() {
+ HashMap metrics = new HashMap<>();
+ metrics.put("type", "sauce:performance");
+ Map perfMetrics =
+ (Map) driver.executeScript("sauce:log", metrics);
+ return Integer.parseInt(perfMetrics.get("load").toString());
+ }
}
diff --git a/best-practice/src/test/java/com/saucedemo/pages/ProductsPage.java b/best-practice/src/test/java/com/saucedemo/pages/ProductsPage.java
index ab101664..bb9d54b6 100644
--- a/best-practice/src/test/java/com/saucedemo/pages/ProductsPage.java
+++ b/best-practice/src/test/java/com/saucedemo/pages/ProductsPage.java
@@ -1,37 +1,33 @@
package com.saucedemo.pages;
+import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
-import java.time.Duration;
-
-/**
- * Page Object representing Products page.
- */
+/** Page Object representing Products page. */
public class ProductsPage extends AbstractBasePage {
- public ProductsPage(RemoteWebDriver driver) {
- super(driver);
- }
+ public ProductsPage(RemoteWebDriver driver) {
+ super(driver);
+ }
- @Override
- public String getPagePart() {
- return "inventory.html";
- }
+ @Override
+ public String getPagePart() {
+ return "inventory.html";
+ }
- /**
- * Whether the browser is on the correct page.
- *
- * @return true if browser is on expected page
- */
- public boolean isDisplayed() {
- WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
- //wait for the user name field to be visible and store that element into a variable
- By userNameFieldLocator = By.id("inventory_container");
- return
- wait.until(
- ExpectedConditions.visibilityOfElementLocated(userNameFieldLocator)).isDisplayed();
- }
+ /**
+ * Whether the browser is on the correct page.
+ *
+ * @return true if browser is on expected page
+ */
+ public boolean isDisplayed() {
+ WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
+ // wait for the user name field to be visible and store that element into a variable
+ By userNameFieldLocator = By.id("inventory_container");
+ return wait.until(ExpectedConditions.visibilityOfElementLocated(userNameFieldLocator))
+ .isDisplayed();
+ }
}
diff --git a/best-practice/src/test/java/com/saucedemo/pages/ShoppingCartPage.java b/best-practice/src/test/java/com/saucedemo/pages/ShoppingCartPage.java
index 098a45e3..1c23f85f 100644
--- a/best-practice/src/test/java/com/saucedemo/pages/ShoppingCartPage.java
+++ b/best-practice/src/test/java/com/saucedemo/pages/ShoppingCartPage.java
@@ -2,16 +2,14 @@
import org.openqa.selenium.remote.RemoteWebDriver;
-/**
- * Page Object representing shopping cart page.
- */
+/** Page Object representing shopping cart page. */
public class ShoppingCartPage extends AbstractBasePage {
- public ShoppingCartPage(RemoteWebDriver driver) {
- super(driver);
- }
+ public ShoppingCartPage(RemoteWebDriver driver) {
+ super(driver);
+ }
- @Override
- public String getPagePart() {
- return "cart.html";
- }
+ @Override
+ public String getPagePart() {
+ return "cart.html";
+ }
}
diff --git a/best-practice/src/test/java/com/saucedemo/tests/BaseTest.java b/best-practice/src/test/java/com/saucedemo/tests/BaseTest.java
index 4ae05f4d..c0832939 100644
--- a/best-practice/src/test/java/com/saucedemo/tests/BaseTest.java
+++ b/best-practice/src/test/java/com/saucedemo/tests/BaseTest.java
@@ -1,5 +1,15 @@
package com.saucedemo.tests;
+import static com.saucedemo.Constants.SAUCE_EU_URL;
+import static com.saucedemo.Constants.SAUCE_US_URL;
+import static com.saucedemo.Constants.region;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.Collection;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestName;
@@ -10,133 +20,120 @@
import org.openqa.selenium.MutableCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.Arrays;
-import java.util.Collection;
-
-import static com.saucedemo.Constants.*;
-
public class BaseTest {
- protected RemoteWebDriver driver;
-
- protected String WEB_URL = "https://www.saucedemo.com/";
-
- @Parameterized.Parameter
- public String platform;
- @Parameterized.Parameter(1)
- public String browserDeviceName;
- @Parameterized.Parameter(2)
- public String browserPlatformVersion;
- @Parameterized.Parameter(3)
- public String platformName;
-
- @Parameterized.Parameters()
- public static Collection
\ No newline at end of file
diff --git a/selenium-cucumber-examples/src/test/java/com/saucedemo/selenium/cucumber/RunTestsAT.java b/selenium-cucumber-examples/src/test/java/com/saucedemo/selenium/cucumber/RunTestsAT.java
index b0bcb140..a40b5c9c 100644
--- a/selenium-cucumber-examples/src/test/java/com/saucedemo/selenium/cucumber/RunTestsAT.java
+++ b/selenium-cucumber-examples/src/test/java/com/saucedemo/selenium/cucumber/RunTestsAT.java
@@ -1,8 +1,9 @@
package com.saucedemo.selenium.cucumber;
-import cucumber.api.CucumberOptions;
-import cucumber.api.testng.AbstractTestNGCucumberTests;
+import io.cucumber.testng.CucumberOptions;
+import io.cucumber.testng.AbstractTestNGCucumberTests;
-@CucumberOptions(plugin = {"pretty"})
+
+@CucumberOptions(features = "src/test/resources")
public class RunTestsAT extends AbstractTestNGCucumberTests{
}
diff --git a/selenium-cucumber-examples/src/test/java/com/saucedemo/selenium/cucumber/StepDefinitions.java b/selenium-cucumber-examples/src/test/java/com/saucedemo/selenium/cucumber/StepDefinitions.java
index b59c5f75..e341e63d 100644
--- a/selenium-cucumber-examples/src/test/java/com/saucedemo/selenium/cucumber/StepDefinitions.java
+++ b/selenium-cucumber-examples/src/test/java/com/saucedemo/selenium/cucumber/StepDefinitions.java
@@ -4,161 +4,164 @@
import com.saucelabs.saucebindings.SaucePlatform;
import com.saucelabs.saucebindings.SauceSession;
import com.saucelabs.saucebindings.options.SauceOptions;
-import cucumber.api.Scenario;
-import cucumber.api.java.After;
-import cucumber.api.java.Before;
-import cucumber.api.java.en.And;
-import cucumber.api.java.en.Given;
-import cucumber.api.java.en.Then;
-import cucumber.api.java.en.When;
-import org.junit.Assert;
+import io.cucumber.java.After;
+import io.cucumber.java.Before;
+import io.cucumber.java.Scenario;
+import io.cucumber.java.en.And;
+import io.cucumber.java.en.Given;
+import io.cucumber.java.en.Then;
+import io.cucumber.java.en.When;
+import java.time.Duration;
+import java.util.stream.IntStream;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
-
-import java.time.Duration;
-import java.util.stream.IntStream;
+import org.testng.Assert;
public class StepDefinitions {
- private WebDriverWait wait;
-
- protected static ThreadLocal session = new ThreadLocal<>();
- protected static ThreadLocal options = new ThreadLocal<>();
-
- public SauceSession getSession() {
- return session.get();
- }
+ protected static ThreadLocal session = new ThreadLocal<>();
+ protected static ThreadLocal options = new ThreadLocal<>();
+ private WebDriverWait wait;
- public RemoteWebDriver getDriver() {
- return getSession().getDriver();
- }
-
-
- @Before
- public void setUp(Scenario scenario) {
- options.set(new SauceOptions());
- options.get().sauce().setName(scenario.getName());
-
- if (System.getenv("START_TIME") != null) {
- options.get().sauce().setBuild("Build Time: " + System.getenv("START_TIME"));
- }
-
- String platform;
- if (System.getProperty("platform") != null) {
- platform = System.getProperty("platform");
- } else {
- platform = "default";
- }
-
- switch(platform) {
- case "windows_10_edge":
- options.get().setPlatformName(SaucePlatform.WINDOWS_10);
- options.get().setBrowserName(Browser.EDGE);
- break;
- case "mac_sierra_chrome":
- options.get().setPlatformName(SaucePlatform.MAC_SIERRA);
- options.get().setBrowserName(Browser.CHROME);
- break;
- case "windows_8_ff":
- options.get().setPlatformName(SaucePlatform.WINDOWS_8);
- options.get().setBrowserName(Browser.FIREFOX);
- break;
- case "windows_8_1_ie":
- options.get().setPlatformName(SaucePlatform.WINDOWS_8_1);
- options.get().setBrowserName(Browser.INTERNET_EXPLORER);
- break;
- case "mac_mojave_safari":
- options.get().setPlatformName(SaucePlatform.MAC_MOJAVE);
- options.get().setBrowserName(Browser.SAFARI);
- break;
- default:
- // accept Sauce defaults
- break;
- }
-
- session.set(new SauceSession(options.get()));
-
- getSession().start();
- wait = new WebDriverWait(getDriver(), Duration.ofSeconds(10));
- }
+ public SauceSession getSession() {
+ return session.get();
+ }
- @After
- public void tearDown(Scenario scenario){
- getSession().stop(!scenario.isFailed());
- }
+ public RemoteWebDriver getDriver() {
+ return getSession().getDriver();
+ }
- @Given("^I go to the login page$")
- public void go_to_login_page() {
- getDriver().get("https://www.saucedemo.com");
- }
+ @Before
+ public void setUp(Scenario scenario) {
+ options.set(new SauceOptions());
+ options.get().sauce().setName(scenario.getName());
- @Given("I am on the inventory page")
- public void go_to_the_inventory_page(){
- getDriver().get("https://www.saucedemo.com/inventory.html");
+ if (System.getenv("START_TIME") != null) {
+ options.get().sauce().setBuild("Build Time: " + System.getenv("START_TIME"));
}
- @When("I login as a valid user")
- public void login_as_valid_user() {
- login("standard_user", "secret_sauce");
+ String platform;
+ if (System.getProperty("platform") != null) {
+ platform = System.getProperty("platform");
+ } else {
+ platform = "default";
}
- @When("I login as an invalid user")
- public void login_as_invalid_user() {
- login("doesnt_exist", "secret_sauce");
+ switch (platform) {
+ case "windows_10_edge":
+ options.get().setPlatformName(SaucePlatform.WINDOWS_10);
+ options.get().setBrowserName(Browser.EDGE);
+ break;
+ case "mac_sierra_chrome":
+ options.get().setPlatformName(SaucePlatform.MAC_SIERRA);
+ options.get().setBrowserName(Browser.CHROME);
+ break;
+ case "windows_8_ff":
+ options.get().setPlatformName(SaucePlatform.WINDOWS_8);
+ options.get().setBrowserName(Browser.FIREFOX);
+ break;
+ case "windows_8_1_ie":
+ options.get().setPlatformName(SaucePlatform.WINDOWS_8_1);
+ options.get().setBrowserName(Browser.INTERNET_EXPLORER);
+ break;
+ case "mac_mojave_safari":
+ options.get().setPlatformName(SaucePlatform.MAC_MOJAVE);
+ options.get().setBrowserName(Browser.SAFARI);
+ break;
+ default:
+ // accept Sauce defaults
+ break;
}
- /**
- * Use this method to send any number of login/password parameters, to test different edge cases or roles within
- * the software. This method exists to show an example of how steps can call other parameterized methods.
- * @param username The user name to login with
- * @param password The password to use (for testing the password field
- */
- private void login(String username, String password) {
- wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("user-name")));
- getDriver().findElement(By.id("user-name")).sendKeys(username);
-
- wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("password")));
- getDriver().findElement(By.id("password")).sendKeys(password);
-
- getDriver().findElement(By.className("btn_action")).click();
- }
-
- @When("^I add (\\d+) items? to the cart$")
- public void add_items_to_cart(int items){
- By itemButton = By.className("btn_primary");
-
- IntStream.range(0, items).forEach(i -> {
- wait.until(ExpectedConditions.elementToBeClickable(getDriver().findElement(itemButton)));
- getDriver().findElement(itemButton).click();
- });
- }
-
- @And("I remove an item")
- public void remove_an_item(){
- By itemButton = By.className("btn_secondary");
-
- wait.until(ExpectedConditions.elementToBeClickable(getDriver().findElement(itemButton)));
- getDriver().findElement(itemButton).click();
- }
-
- @Then("I have (\\d) items? in my cart")
- public void one_item_in_cart(Integer items) {
- String expected_items = items.toString();
-
- By itemsInCart = By.className("shopping_cart_badge");
-
- wait.until(ExpectedConditions.elementToBeClickable(getDriver().findElement(itemsInCart)));
- Assert.assertEquals(getDriver().findElement(itemsInCart).getText(), expected_items);
- }
-
- @Then("The item list is not displayed")
- public void item_list_is_not_diplayed() {
- Assert.assertEquals(getDriver().findElements(By.id("inventory_container")).size(), 0);
- }
-
- @Then("The item list is displayed")
- public void item_list_is_diplayed() {
- Assert.assertTrue(getDriver().findElement(By.id("inventory_container")).isDisplayed());
- }
+ session.set(new SauceSession(options.get()));
+
+ getSession().start();
+ wait = new WebDriverWait(getDriver(), Duration.ofSeconds(10));
+ }
+
+ @After
+ public void tearDown(Scenario scenario) {
+ getSession().stop(!scenario.isFailed());
+ }
+
+ @Given("I go to the login page")
+ public void go_to_login_page() {
+ getDriver().get("https://www.saucedemo.com");
+ }
+
+ @Given("I am on the inventory page")
+ public void go_to_the_inventory_page() {
+ getDriver().get("https://www.saucedemo.com/inventory.html");
+ login("standard_user", "secret_sauce");
+ }
+
+ @When("I login as a valid user")
+ public void login_as_valid_user() {
+ login("standard_user", "secret_sauce");
+ }
+
+ @When("I login as an invalid user")
+ public void login_as_invalid_user() {
+ login("doesnt_exist", "secret_sauce");
+ }
+
+ /**
+ * Use this method to send any number of login/password parameters, to test different edge cases
+ * or roles within the software. This method exists to show an example of how steps can call other
+ * parameterized methods.
+ *
+ * @param username The user name to login with
+ * @param password The password to use (for testing the password field
+ */
+ private void login(String username, String password) {
+ wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("user-name")));
+ getDriver().findElement(By.id("user-name")).sendKeys(username);
+
+ wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("password")));
+ getDriver().findElement(By.id("password")).sendKeys(password);
+
+ getDriver().findElement(By.className("btn_action")).click();
+ }
+
+ @When("^I add (\\d+) items? to the cart$")
+ public void add_items_to_cart(int items) {
+ By itemButton = By.className("btn_primary");
+
+ IntStream.range(0, items)
+ .forEach(
+ i -> {
+ wait.until(
+ ExpectedConditions.elementToBeClickable(getDriver().findElement(itemButton)));
+ getDriver().findElement(itemButton).click();
+ });
+ }
+
+ @And("I remove an item")
+ public void remove_an_item() {
+ By itemButton = By.className("btn_secondary");
+
+ wait.until(ExpectedConditions.elementToBeClickable(getDriver().findElement(itemButton)));
+ getDriver().findElement(itemButton).click();
+ }
+
+ @Then("^I have (\\d) items? in my cart$")
+ public void one_item_in_cart(Integer items) {
+ String expected_items = items.toString();
+
+ By itemsInCart = By.className("shopping_cart_badge");
+
+ wait.until(ExpectedConditions.elementToBeClickable(getDriver().findElement(itemsInCart)));
+ Assert.assertEquals(getDriver().findElement(itemsInCart).getText(), expected_items);
+ }
+
+ @Then("The item list is not displayed")
+ public void item_list_is_not_diplayed() {
+ Assert.assertEquals(getDriver().findElements(By.id("inventory_container")).size(), 0);
+ }
+
+ @Then("The item list is displayed")
+ public void item_list_is_diplayed() {
+ Assert.assertTrue(getDriver().findElement(By.id("inventory_container")).isDisplayed());
+ }
}
diff --git a/selenium-examples/README.md b/selenium-examples/README.md
index ad91c117..a66295dd 100644
--- a/selenium-examples/README.md
+++ b/selenium-examples/README.md
@@ -1,66 +1,32 @@
# Selenium examples
-This folder contains Selenium examples
-## Examples
+The primary function of this project is to demonstrate using Sauce Labs with JUnit 5 (The [demo](/src/test/java/com/saucedemo/selenium/demo)), including:
+* Setting valid options
+* Sending test results to Sauce Labs
+* Running in Parallel with Maven surefire. See [pom.xml](pom.xml)
-- [Accessibility Test with Sauce Bindings](../selenium-examples/src/test/java/com/saucedemo/accessibility/SauceBindingsExampleTest.java)
-- [Accessibility Test with Deque Axe](../selenium-examples/src/test/java/com/saucedemo/accessibility/DequeAxeExampleTest.java)
-- [Simple web test, Junit 5](../selenium-examples/src/test/java/com/saucedemo/JUnit5W3CChromeTest.java)
-- [Simple Headless test, TestNG](../selenium-examples/src/test/java/com/saucedemo/SampleHeadlessSauceTest.java)
-- [Sauce Status Updates w/ JUnit 3](../selenium-examples/src/test/java/com/saucedemo/JUnit3UpdateSauceStatusTest.java)
+In addition, this project contains two additional packages:
-## How to run tests
+* Sauce Labs Features package for demos of functionality exclusive to Sauce Labs
+* Selenium Features package for demos of Selenium features on Sauce Labs
-### JUnit 5 test
-```bash
-cd selenium-examples
-mvn test -Dtest=JUnit5W3CChromeTest
-```
+## Execution options:
-Your output will look like this if done correctly
-
-```java
-[INFO] Scanning for projects...
-[INFO]
-[INFO] ------------------< com.saucelabs:selenium-examples >-------------------
-[INFO] Building selenium-examples 1.0-SNAPSHOT
-[INFO] --------------------------------[ jar ]---------------------------------
-[INFO]
-[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ selenium-examples ---
-[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
-[INFO] Copying 0 resource
-[INFO]
-[INFO] --- maven-compiler-plugin:3.0:compile (default-compile) @ selenium-examples ---
-[INFO] Nothing to compile - all classes are up to date
-[INFO]
-[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ selenium-examples ---
-[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
-[INFO] skip non existing resourceDirectory /Users/nikolayadvolodkin/Documents/source/java/demo-java/selenium-examples/src/test/resources
-[INFO]
-[INFO] --- maven-compiler-plugin:3.0:testCompile (default-testCompile) @ selenium-examples ---
-[INFO] Nothing to compile - all classes are up to date
-[INFO]
-[INFO] --- maven-surefire-plugin:3.0.0-M4:test (default-test) @ selenium-examples ---
-[INFO]
-[INFO] -------------------------------------------------------
-[INFO] T E S T S
-[INFO] -------------------------------------------------------
-[INFO] Running com.saucedemo.JUnit5W3CChromeTest
-Apr 05, 2021 1:48:11 PM org.openqa.selenium.remote.ProtocolHandshake createSession
-INFO: Detected dialect: W3C
-SauceOnDemandSessionID=c36e76bd99964b29824e3c9597558659 job-name=Junit5W3CChromeTest
-Test Job Link: https://app.saucelabs.com/tests/c36e76bd99964b29824e3c9597558659
-[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 7.44 s - in com.saucedemo.JUnit5W3CChromeTest
-[INFO]
-[INFO] Results:
-[INFO]
-[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
-[INFO]
-[INFO] ------------------------------------------------------------------------
-[INFO] BUILD SUCCESS
-[INFO] ------------------------------------------------------------------------
-[INFO] Total time: 9.728 s
-[INFO] Finished at: 2021-04-05T13:48:14-04:00
+First, ensure you are in `selenium-examples` directory
+```bash
+cd selenium-examples
```
+1. Run everything with default parallelization:
+ ```bash
+ mvn clean test
+ ```
+2. Run only demo tests:
+ ```bash
+ mvn clean test -Dtest='com.saucedemo.selenium.demo.*Test'
+ ```
+3. Change parallelization
+ ```bash
+ mvn test -Dsurefire.parallel=20
+ ```
diff --git a/selenium-examples/pom.xml b/selenium-examples/pom.xml
index 4d5a9fbd..0b675fe9 100644
--- a/selenium-examples/pom.xml
+++ b/selenium-examples/pom.xml
@@ -1,66 +1,83 @@
-
-
- demo-java
- com.saucelabs
- 1.0-SNAPSHOT
-
- 4.0.0
+ 4.0.0
- selenium-examples
+ com.saucelabs
+ selenium-examples
+ 1.0-SNAPSHOT
-
-
- com.saucelabs
- saucebindings-junit5
- 1.0.0
- test
-
-
- org.seleniumhq.selenium
- selenium-java
- 4.0.0
-
-
- com.deque.html.axe-core
- selenium
- 4.4.0
-
-
- org.slf4j
- slf4j-simple
- 2.0.4
- test
-
-
+ Sauce Labs JUnit5 Examples
+ Example code for using Selenium on Sauce labs
+ https://github.com/saucelabs-training/demo-java
+
+
+ MIT License
+ https://www.opensource.org/licenses/mit-license.php
+ repo
+
+
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- ${maven.surefire.version}
-
-
- 20
- 20
- 20
- 20
-
-
-
- junit.jupiter.execution.parallel.enabled = true
- junit.jupiter.execution.parallel.mode.default = concurrent
- junit.jupiter.execution.parallel.mode.classes.default = concurrent
- junit.jupiter.execution.parallel.config.strategy = fixed
- junit.jupiter.execution.parallel.config.strategy = custom
- junit.jupiter.execution.parallel.config.custom.class = com.saucelabs.saucebindings.junit5.CustomStrategy
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+ jitpack.io
+ https://jitpack.io
+
+
+
+
+ 10
+ 11
+ 11
+ UTF-8
+
+
+
+
+ org.seleniumhq.selenium
+ selenium-java
+ 4.25.0
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.11.3
+ test
+
+
+ com.deque.html.axe-core
+ selenium
+ 4.10.0
+ test
+
+
+ com.titusfortner
+ selenium-logger
+ 2.4.0
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.5.1
+
+
+
+ junit.jupiter.execution.parallel.enabled = true
+ junit.jupiter.execution.parallel.mode.default = concurrent
+ junit.jupiter.execution.parallel.config.strategy = fixed
+ junit.jupiter.execution.parallel.config.fixed.parallelism = ${surefire.parallel}
+ junit.jupiter.execution.parallel.config.fixed.max-pool-size = ${surefire.parallel}
+
+
+
+
+
+
+
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/PerformanceTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/PerformanceTest.java
deleted file mode 100644
index e54baf8a..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/PerformanceTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.saucedemo.selenium;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInfo;
-import org.openqa.selenium.chrome.ChromeOptions;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Performance Test.
- */
-public class PerformanceTest extends SeleniumTestBase {
-
- @BeforeEach
- public void setup(TestInfo testInfo) {
- ChromeOptions options = new ChromeOptions();
- options.setPlatformName("Windows 10");
- options.setBrowserVersion("latest");
-
- Map sauceOptions = new HashMap<>();
- sauceOptions.put("capturePerformance", true);
- sauceOptions.put("extendedDebugging", true);
- options.setCapability("sauce:options", sauceOptions);
-
- basicSetup(testInfo, options);
- }
-
- @DisplayName("Ensure all metrics within historical limits")
- @Test
- public void performanceAllMetrics() {
- driver.get("https://www.saucedemo.com");
-
- HashMap args = new HashMap<>();
- args.put("name", watcher.getName());
- Map performance = (Map) driver.executeScript("sauce:performance", args);
-
- Assertions.assertEquals("pass", performance.get("result"));
- }
-
- @DisplayName("Ensure provided metrics within historical limits")
- @Test
- public void performanceSpecificMetrics() {
- driver.get("https://www.saucedemo.com");
-
- HashMap args = new HashMap<>();
- args.put("name", watcher.getName());
- args.put("metrics", Arrays.asList("load", "firstContentfulPaint"));
-
- Map performance = (Map) driver.executeScript("sauce:performance", args);
- Assertions.assertEquals("pass", performance.get("result"));
- }
-
- @DisplayName("Get log of performance metrics from previous navigation")
- @Test
- public void performanceLog() {
- driver.get("https://www.saucedemo.com");
-
- HashMap metricsLog = new HashMap<>();
- metricsLog.put("type", "sauce:performance");
- Map metrics = (Map) driver.executeScript("sauce:log", metricsLog);
-
- Assertions.assertTrue((int) metrics.get("firstInteractive") < 5000 );
- }
-
- @DisplayName("Get jankiness metrics from previous navigation")
- @Test
- public void jankiness() {
- driver.get("https://www.saucedemo.com");
-
- Map metrics = (Map) driver.executeScript("sauce:jankinessCheck");
-
- Assertions.assertTrue((double) metrics.get("score") > 0.5 );
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/SeleniumTestBase.java b/selenium-examples/src/test/java/com/saucedemo/selenium/SeleniumTestBase.java
deleted file mode 100644
index f4adfb59..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/SeleniumTestBase.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.saucedemo.selenium;
-
-import org.junit.jupiter.api.TestInfo;
-import org.junit.jupiter.api.extension.ExtensionContext;
-import org.junit.jupiter.api.extension.RegisterExtension;
-import org.junit.jupiter.api.extension.TestWatcher;
-import org.openqa.selenium.MutableCapabilities;
-import org.openqa.selenium.chrome.ChromeOptions;
-import org.openqa.selenium.remote.RemoteWebDriver;
-import org.openqa.selenium.remote.SessionId;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-public class SeleniumTestBase {
-
- public RemoteWebDriver driver;
-
- @RegisterExtension
- public SeleniumTestBase.SauceTestWatcher watcher = new SeleniumTestBase.SauceTestWatcher();
-
- public void basicSetup(TestInfo testInfo, MutableCapabilities options) {
- Map sauceOptions = (Map) options.getCapability("sauce:options");
-
- if (sauceOptions == null) {
- sauceOptions = new HashMap<>();
- }
-
- sauceOptions.put("username", System.getenv("SAUCE_USERNAME"));
- sauceOptions.put("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
- sauceOptions.put("name", testInfo.getDisplayName());
- options.setCapability("sauce:options", sauceOptions);
-
- watcher.setName(testInfo.getDisplayName());
-
- URL url;
- try {
- url = new URL("https://ondemand.us-west-1.saucelabs.com/wd/hub");
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
- }
-
- driver = new RemoteWebDriver(url, options);
- watcher.setId(driver.getSessionId());
- }
-
- public void basicSetup(TestInfo testInfo) {
- ChromeOptions options = new ChromeOptions();
- options.setPlatformName("Windows 10");
- options.setBrowserVersion("latest");
-
- basicSetup(testInfo, options);
- }
-
- public class SauceTestWatcher implements TestWatcher {
- private String name;
- private String id;
-
- @Override
- public void testSuccessful(ExtensionContext context) {
- printResults();
- driver.executeScript("sauce:job-result=passed");
- driver.quit();
- }
-
- @Override
- public void testFailed(ExtensionContext context, Throwable cause) {
- printResults();
- driver.executeScript("sauce:job-result=failed");
- driver.quit();
- }
-
- public void printResults() {
- String sauceReporter = String.format("SauceOnDemandSessionID=%s job-name=%s", id, name);
- String sauceTestLink = String.format("Test Job Link: https://app.saucelabs.com/tests/%s", id);
- System.out.print(sauceReporter + "\n" + sauceTestLink + "\n");
- }
-
- public void setName(String displayName) {
- this.name = displayName;
- }
-
- public String getName() {
- return name;
- }
-
- public void setId(SessionId sessionId) {
- this.id = String.valueOf(sessionId);
- }
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/TestBase.java b/selenium-examples/src/test/java/com/saucedemo/selenium/TestBase.java
new file mode 100644
index 00000000..d667c6d0
--- /dev/null
+++ b/selenium-examples/src/test/java/com/saucedemo/selenium/TestBase.java
@@ -0,0 +1,113 @@
+package com.saucedemo.selenium;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.api.extension.TestWatcher;
+import org.openqa.selenium.Capabilities;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.MutableCapabilities;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.chrome.ChromeOptions;
+import org.openqa.selenium.firefox.FirefoxOptions;
+import org.openqa.selenium.remote.AbstractDriverOptions;
+import org.openqa.selenium.remote.RemoteWebDriver;
+import org.openqa.selenium.remote.SessionId;
+
+public class TestBase {
+
+ static {
+ String buildName = "Default Build Name";
+ String buildNumber = String.valueOf(System.currentTimeMillis());
+ System.setProperty("build.name", buildName + ": " + buildNumber);
+ }
+
+ public WebDriver driver;
+ @RegisterExtension public TestBase.SauceTestWatcher watcher = new TestBase.SauceTestWatcher();
+ protected TestInfo testInfo;
+ protected SessionId id;
+
+ public void startChromeSession(TestInfo testInfo, List args) {
+ ChromeOptions options = new ChromeOptions().addArguments(args);
+ startSession(testInfo, options);
+ }
+
+ public void startChromeSession(TestInfo testInfo) {
+ startChromeSession(testInfo, new ArrayList<>());
+ }
+
+ public void startFirefoxSession(TestInfo testInfo) {
+ startSession(testInfo, new FirefoxOptions());
+ }
+
+ public void startSession(TestInfo testInfo, Capabilities options) {
+ startSession(options, defaultSauceOptions(testInfo));
+ }
+
+ protected void startSession(Capabilities options, Map sauceOptions) {
+ ((MutableCapabilities) options).setCapability("sauce:options", sauceOptions);
+ if (options.getPlatformName() == null) {
+ ((AbstractDriverOptions>) options).setPlatformName("Windows 11");
+ }
+
+ URL url;
+ try {
+ url = new URL("https://ondemand.us-west-1.saucelabs.com/wd/hub");
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+
+ driver = new RemoteWebDriver(url, options);
+ this.id = ((RemoteWebDriver) driver).getSessionId();
+ }
+
+ protected Map defaultSauceOptions(TestInfo testInfo) {
+ this.testInfo = testInfo;
+
+ Map options = new HashMap<>();
+ options.put("username", System.getenv("SAUCE_USERNAME"));
+ options.put("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
+ options.put("name", testInfo.getDisplayName());
+ options.put("build", System.getProperty("build.name"));
+ options.put("seleniumVersion", "4.22.0");
+ return options;
+ }
+
+ public class SauceTestWatcher implements TestWatcher {
+ @Override
+ public void testSuccessful(ExtensionContext context) {
+ printResults();
+ try {
+ ((JavascriptExecutor) driver).executeScript("sauce:job-result=passed");
+ driver.quit();
+ } catch (Exception e) {
+ System.out.println("problem with using driver: " + e);
+ }
+ }
+
+ @Override
+ public void testFailed(ExtensionContext context, Throwable cause) {
+ printResults();
+
+ try {
+ ((JavascriptExecutor) driver).executeScript("sauce:job-result=failed");
+ driver.quit();
+ } catch (Exception e) {
+ System.out.println("problem with using driver: " + e);
+ }
+ }
+
+ public void printResults() {
+ String sauceReporter =
+ String.format("SauceOnDemandSessionID=%s job-name=%s", id, testInfo.getDisplayName());
+ String sauceTestLink = String.format("Test Job Link: https://app.saucelabs.com/tests/%s", id);
+ System.out.print(sauceReporter + "\n" + sauceTestLink + "\n");
+ }
+ }
+}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/accessibility/DequeAxeTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/accessibility/DequeAxeTest.java
deleted file mode 100644
index 5f99ae72..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/accessibility/DequeAxeTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.saucedemo.selenium.accessibility;
-
-import com.deque.html.axecore.results.Results;
-import com.deque.html.axecore.selenium.AxeBuilder;
-import com.saucedemo.selenium.SeleniumTestBase;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInfo;
-
-/**
- * Accessibility Tests with Deque Library.
- */
-public class DequeAxeTest extends SeleniumTestBase {
-
- @BeforeEach
- public void setup(TestInfo testInfo) {
- basicSetup(testInfo);
- }
-
- @DisplayName("Deque Axe Test With Selenium Not html")
- @Test
- public void accessibilityTest() {
- driver.navigate().to("https://www.saucedemo.com");
-
- AxeBuilder axeBuilder = new AxeBuilder();
- Results accessibilityResults = axeBuilder.analyze(driver);
-
- Assertions.assertEquals(3, accessibilityResults.getViolations().size());
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/accessibility/SauceBindingsTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/accessibility/SauceBindingsTest.java
deleted file mode 100644
index 505f98fa..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/accessibility/SauceBindingsTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.saucedemo.selenium.accessibility;
-
-import com.deque.html.axecore.results.Results;
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-/**
- * Accessibility Tests with Sauce Bindings.
- */
-public class SauceBindingsTest extends SauceBaseTest {
-
- @DisplayName("Accessibility of Swag Labs")
- @Test
- public void sauceDemoAccessibility() {
- driver.navigate().to("https://www.saucedemo.com");
- Results results = session.getAccessibilityResults();
- Assertions.assertEquals(3, results.getViolations().size());
- }
-
- @DisplayName("Accessibility of abcdcomputech")
- @Test
- public void abcdcomputechTest() {
- driver.navigate().to("http://abcdcomputech.dequecloud.com");
- Results results = session.getAccessibilityResults();
- Assertions.assertEquals(7, results.getViolations().size());
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/demo/AuthenticationTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/demo/AuthenticationTest.java
new file mode 100644
index 00000000..03273aa0
--- /dev/null
+++ b/selenium-examples/src/test/java/com/saucedemo/selenium/demo/AuthenticationTest.java
@@ -0,0 +1,54 @@
+package com.saucedemo.selenium.demo;
+
+import com.saucedemo.selenium.TestBase;
+import org.junit.jupiter.api.*;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+public class AuthenticationTest extends TestBase {
+
+ @BeforeEach
+ public void setup(TestInfo testInfo) {
+ startFirefoxSession(testInfo);
+ }
+
+ @Test
+ public void signInUnsuccessful() {
+ driver.get("https://www.saucedemo.com/");
+
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("locked_out_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+
+ WebElement errorElement = driver.findElement(By.cssSelector("[data-test='error']"));
+ Assertions.assertTrue(
+ errorElement.getText().contains("Sorry, this user has been locked out"), "Error Not Found");
+ }
+
+ @Test
+ public void signInSuccessful() {
+ driver.get("https://www.saucedemo.com/");
+
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+
+ Assertions.assertEquals(
+ "https://www.saucedemo.com/inventory.html", driver.getCurrentUrl(), "Login Not Successful");
+ }
+
+ @Test
+ public void logout() throws InterruptedException {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+ driver.findElement(By.id("react-burger-menu-btn")).click();
+ Thread.sleep(1000);
+
+ driver.findElement(By.id("logout_sidebar_link")).click();
+
+ Assertions.assertEquals(
+ "https://www.saucedemo.com/", driver.getCurrentUrl(), "Logout Not Successful");
+ }
+}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/demo/CartTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/demo/CartTest.java
new file mode 100644
index 00000000..41ed1f8c
--- /dev/null
+++ b/selenium-examples/src/test/java/com/saucedemo/selenium/demo/CartTest.java
@@ -0,0 +1,96 @@
+package com.saucedemo.selenium.demo;
+
+import com.saucedemo.selenium.TestBase;
+import org.junit.jupiter.api.*;
+import org.openqa.selenium.By;
+
+public class CartTest extends TestBase {
+
+ @BeforeEach
+ public void setup(TestInfo testInfo) {
+ startChromeSession(testInfo);
+ }
+
+ @Test
+ public void addFromProductPage() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+
+ driver
+ .findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-bolt-t-shirt']"))
+ .click();
+
+ Assertions.assertEquals(
+ "1",
+ driver.findElement(By.className("shopping_cart_badge")).getText(),
+ "Item not correctly added to cart");
+ }
+
+ @Test
+ public void removeFromProductPage() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+ driver
+ .findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-bolt-t-shirt']"))
+ .click();
+
+ driver
+ .findElement(By.cssSelector("button[data-test='remove-sauce-labs-bolt-t-shirt']"))
+ .click();
+
+ Assertions.assertTrue(
+ driver.findElements(By.className("shopping_cart_badge")).isEmpty(),
+ "Item not correctly removed from cart");
+ }
+
+ @Test
+ public void addFromInventoryPage() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+
+ driver.findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-onesie']")).click();
+
+ Assertions.assertEquals("1", driver.findElement(By.className("shopping_cart_badge")).getText());
+ }
+
+ @Test
+ public void removeFromInventoryPage() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+ driver
+ .findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-bike-light']"))
+ .click();
+
+ driver.findElement(By.cssSelector("button[data-test='remove-sauce-labs-bike-light']")).click();
+
+ Assertions.assertTrue(
+ driver.findElements(By.className("shopping_cart_badge")).isEmpty(),
+ "Shopping Cart is not empty");
+ }
+
+ @Test
+ public void removeFromCartPage() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+ driver
+ .findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-backpack']"))
+ .click();
+ driver.findElement(By.className("shopping_cart_link")).click();
+
+ driver.findElement(By.cssSelector("button[data-test='remove-sauce-labs-backpack']")).click();
+
+ Assertions.assertTrue(
+ driver.findElements(By.className("shopping_cart_badge")).isEmpty(),
+ "Shopping Cart is not empty");
+ }
+}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/demo/CheckoutTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/demo/CheckoutTest.java
new file mode 100644
index 00000000..a4f64258
--- /dev/null
+++ b/selenium-examples/src/test/java/com/saucedemo/selenium/demo/CheckoutTest.java
@@ -0,0 +1,77 @@
+package com.saucedemo.selenium.demo;
+
+import com.saucedemo.selenium.TestBase;
+import org.junit.jupiter.api.*;
+import org.openqa.selenium.By;
+
+public class CheckoutTest extends TestBase {
+
+ @BeforeEach
+ public void setup(TestInfo testInfo) {
+ startFirefoxSession(testInfo);
+ }
+
+ @Test
+ public void badInfo() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+ driver.findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-onesie']")).click();
+ driver.findElement(By.className("shopping_cart_link")).click();
+ driver.findElement(By.cssSelector("button[data-test='checkout']")).click();
+
+ driver.findElement(By.cssSelector("input[data-test='continue']")).click();
+
+ Assertions.assertTrue(
+ driver
+ .findElement(By.cssSelector("input[data-test='firstName']"))
+ .getAttribute("class")
+ .contains("error"),
+ "Expected error not found on page");
+ }
+
+ @Test
+ public void goodInfo() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+ driver.findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-onesie']")).click();
+ driver.findElement(By.className("shopping_cart_link")).click();
+ driver.findElement(By.cssSelector("button[data-test='checkout']")).click();
+
+ driver.findElement(By.cssSelector("input[data-test='firstName']")).sendKeys("Luke");
+ driver.findElement(By.cssSelector("input[data-test='lastName']")).sendKeys("Perry");
+ driver.findElement(By.cssSelector("input[data-test='postalCode']")).sendKeys("90210");
+
+ driver.findElement(By.cssSelector("input[data-test='continue']")).click();
+
+ Assertions.assertEquals(
+ "https://www.saucedemo.com/checkout-step-two.html",
+ driver.getCurrentUrl(),
+ "Information Submission Unsuccessful");
+ }
+
+ @Test
+ public void completeCheckout() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+ driver.findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-onesie']")).click();
+ driver.findElement(By.className("shopping_cart_link")).click();
+ driver.findElement(By.cssSelector("button[data-test='checkout']")).click();
+ driver.findElement(By.cssSelector("input[data-test='firstName']")).sendKeys("Luke");
+ driver.findElement(By.cssSelector("input[data-test='lastName']")).sendKeys("Perry");
+ driver.findElement(By.cssSelector("input[data-test='postalCode']")).sendKeys("90210");
+ driver.findElement(By.cssSelector("input[data-test='continue']")).click();
+
+ driver.findElement(By.cssSelector("button[data-test='finish']")).click();
+
+ Assertions.assertEquals(
+ "https://www.saucedemo.com/checkout-complete.html", driver.getCurrentUrl());
+
+ Assertions.assertTrue(driver.findElement(By.className("complete-text")).isDisplayed());
+ }
+}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/demo/NavigationTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/demo/NavigationTest.java
new file mode 100644
index 00000000..6b538d14
--- /dev/null
+++ b/selenium-examples/src/test/java/com/saucedemo/selenium/demo/NavigationTest.java
@@ -0,0 +1,75 @@
+package com.saucedemo.selenium.demo;
+
+import com.saucedemo.selenium.TestBase;
+import org.junit.jupiter.api.*;
+import org.openqa.selenium.By;
+
+public class NavigationTest extends TestBase {
+
+ @BeforeEach
+ public void setup(TestInfo testInfo) {
+ startFirefoxSession(testInfo);
+ }
+
+ @Test
+ public void cancelFromCart() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+ driver.findElement(By.className("shopping_cart_link")).click();
+
+ driver.findElement(By.cssSelector("button[data-test='continue-shopping']")).click();
+
+ Assertions.assertEquals("https://www.saucedemo.com/inventory.html", driver.getCurrentUrl());
+ }
+
+ @Test
+ public void cancelFromInfoPage() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+ driver.findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-onesie']")).click();
+ driver.findElement(By.className("shopping_cart_link")).click();
+ driver.findElement(By.cssSelector("button[data-test='checkout']")).click();
+
+ driver.findElement(By.cssSelector("button[data-test='cancel']")).click();
+
+ Assertions.assertEquals("https://www.saucedemo.com/cart.html", driver.getCurrentUrl());
+ }
+
+ @Test
+ public void cancelFromCheckoutPage() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+ driver.findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-onesie']")).click();
+ driver.findElement(By.className("shopping_cart_link")).click();
+ driver.findElement(By.cssSelector("button[data-test='checkout']")).click();
+ driver.findElement(By.cssSelector("input[data-test='firstName']")).sendKeys("Luke");
+ driver.findElement(By.cssSelector("input[data-test='lastName']")).sendKeys("Perry");
+ driver.findElement(By.cssSelector("input[data-test='postalCode']")).sendKeys("90210");
+ driver.findElement(By.cssSelector("input[data-test='continue']")).click();
+
+ driver.findElement(By.cssSelector("button[data-test='cancel']")).click();
+
+ Assertions.assertEquals("https://www.saucedemo.com/inventory.html", driver.getCurrentUrl());
+ }
+
+ @Test
+ public void startCheckout() {
+ driver.get("https://www.saucedemo.com/");
+ driver.findElement(By.cssSelector("input[data-test='username']")).sendKeys("standard_user");
+ driver.findElement(By.cssSelector("input[data-test='password']")).sendKeys("secret_sauce");
+ driver.findElement(By.cssSelector("input[data-test='login-button']")).click();
+ driver.findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-onesie']")).click();
+ driver.findElement(By.className("shopping_cart_link")).click();
+
+ driver.findElement(By.cssSelector("button[data-test='checkout']")).click();
+
+ Assertions.assertEquals(
+ "https://www.saucedemo.com/checkout-step-one.html", driver.getCurrentUrl());
+ }
+}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/demo/SauceBindingsTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/demo/SauceBindingsTest.java
deleted file mode 100644
index 507bf2b0..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/demo/SauceBindingsTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.saucedemo.selenium.demo;
-
-import com.saucelabs.saucebindings.SauceSession;
-import com.saucelabs.saucebindings.options.SauceOptions;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInfo;
-import org.junit.jupiter.api.extension.ExtensionContext;
-import org.junit.jupiter.api.extension.RegisterExtension;
-import org.junit.jupiter.api.extension.TestWatcher;
-import org.openqa.selenium.remote.RemoteWebDriver;
-
-/**
- * Demo tests using Sauce bindings.
- */
-public class SauceBindingsTest {
- private SauceSession session;
- protected RemoteWebDriver driver;
-
- /**
- * A Test Watcher is needed to be able to get the results of a Test so that it can be sent to Sauce Labs.
- * Note that the name is never actually used
- */
- @RegisterExtension
- public SauceTestWatcher watcher = new SauceTestWatcher();
-
- @BeforeEach
- public void setup(TestInfo testInfo) {
- SauceOptions sauceOptions = SauceOptions.chrome()
- .setName(testInfo.getDisplayName())
- .build();
- session = new SauceSession(sauceOptions);
- driver = session.start();
- }
-
- @DisplayName("Sauce Bindings Navigation Test")
- @Test
- public void sauceBindingsNavigationTest() {
- driver.navigate().to("https://www.saucedemo.com");
- Assertions.assertEquals("Swag Labs", driver.getTitle());
- }
-
- /**
- * Custom TestWatcher for Sauce Labs projects.
- */
- public class SauceTestWatcher implements TestWatcher {
- @Override
- public void testSuccessful(ExtensionContext context) {
- session.stop(true);
- }
-
- @Override
- public void testFailed(ExtensionContext context, Throwable cause) {
- session.stop(false);
- }
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/demo/SaucebindingsJunitTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/demo/SaucebindingsJunitTest.java
deleted file mode 100644
index 90d16ffc..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/demo/SaucebindingsJunitTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.saucedemo.selenium.demo;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-/**
- * saucebindings.junit5 package provides a default superclass to handle set up and tear down
- *
- * @see Sauce Binding Test Runners
- * for more information
- */
-public class SaucebindingsJunitTest extends SauceBaseTest {
-
- @DisplayName("Sauce Bindings Test Runner Navigation Example")
- @Test
- public void sauceBindingsTestRunnerTest() {
- driver.navigate().to("https://www.saucedemo.com");
- Assertions.assertEquals("Swag Labs", driver.getTitle());
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/demo/SeleniumTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/demo/SeleniumTest.java
deleted file mode 100644
index 09dfdc98..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/demo/SeleniumTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.saucedemo.selenium.demo;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInfo;
-import org.junit.jupiter.api.extension.ExtensionContext;
-import org.junit.jupiter.api.extension.RegisterExtension;
-import org.junit.jupiter.api.extension.TestWatcher;
-import org.openqa.selenium.chrome.ChromeOptions;
-import org.openqa.selenium.remote.RemoteWebDriver;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Demo tests with Selenium.
- */
-public class SeleniumTest {
- public RemoteWebDriver driver;
-
- /**
- * A Test Watcher is needed to be able to get the results of a Test so that it can be sent to Sauce Labs.
- * Note that the name is never actually used
- */
- @RegisterExtension
- public SauceTestWatcher watcher = new SauceTestWatcher();
-
- @BeforeEach
- public void setup(TestInfo testInfo) throws MalformedURLException {
- ChromeOptions options = new ChromeOptions();
- options.setPlatformName("Windows 10");
- options.setBrowserVersion("latest");
-
- Map sauceOptions = new HashMap<>();
- sauceOptions.put("username", System.getenv("SAUCE_USERNAME"));
- sauceOptions.put("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
- sauceOptions.put("name", testInfo.getDisplayName());
-
- options.setCapability("sauce:options", sauceOptions);
- URL url = new URL("https://ondemand.us-west-1.saucelabs.com/wd/hub");
-
- driver = new RemoteWebDriver(url, options);
- }
-
- @DisplayName("Selenium Navigation Test")
- @Test
- public void navigateAndClose() {
- driver.navigate().to("https://www.saucedemo.com");
- Assertions.assertEquals("Swag Labs", driver.getTitle());
- }
-
- /**
- * Custom TestWatcher for Sauce Labs projects.
- */
- public class SauceTestWatcher implements TestWatcher {
- @Override
- public void testSuccessful(ExtensionContext context) {
- driver.executeScript("sauce:job-result=passed");
- driver.quit();
- }
-
- @Override
- public void testFailed(ExtensionContext context, Throwable cause) {
- driver.executeScript("sauce:job-result=failed");
- driver.quit();
- }
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/login/SauceBindingsLoginTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/login/SauceBindingsLoginTest.java
deleted file mode 100644
index 1331bb67..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/login/SauceBindingsLoginTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.saucedemo.selenium.login;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.ui.WebDriverWait;
-
-import java.time.Duration;
-
-/**
- * Login Test Using Sauce Bindings.
- */
-public class SauceBindingsLoginTest extends SauceBaseTest {
-
- @DisplayName("Swag Labs Login with Sauce Bindings")
- @Test
- public void swagLabsLoginTest() {
- driver.get("https://www.saucedemo.com");
-
- By usernameFieldLocator = By.id("user-name");
- By passwordFieldLocator = By.id("password");
- By submitButtonLocator = By.id("login-button");
-
- WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
- wait.until((driver) -> driver.findElement(usernameFieldLocator).isDisplayed());
-
- WebElement userNameField = driver.findElement(usernameFieldLocator);
- WebElement passwordField = driver.findElement(passwordFieldLocator);
- WebElement submitButton = driver.findElement(submitButtonLocator);
-
- userNameField.sendKeys("standard_user");
- passwordField.sendKeys("secret_sauce");
- submitButton.click();
-
- Assertions.assertEquals("https://www.saucedemo.com/inventory.html", driver.getCurrentUrl());
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/login/SeleniumLoginTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/login/SeleniumLoginTest.java
deleted file mode 100644
index 352e94b4..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/login/SeleniumLoginTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.saucedemo.selenium.login;
-
-import com.saucedemo.selenium.SeleniumTestBase;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInfo;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebElement;
-import org.openqa.selenium.support.ui.WebDriverWait;
-
-import java.time.Duration;
-
-/**
- * Login tests with Selenium.
- */
-public class SeleniumLoginTest extends SeleniumTestBase {
- @BeforeEach
- public void setup(TestInfo testInfo) {
- basicSetup(testInfo);
- }
-
- @DisplayName("Swag Labs Login with Selenium")
- @Test
- public void swagLabsLoginTest() {
- driver.get("https://www.saucedemo.com");
-
- By usernameFieldLocator = By.cssSelector("#user-name");
- By passwordFieldLocator = By.cssSelector("#password");
- By submitButtonLocator = By.cssSelector(".btn_action");
-
- WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(20));
- wait.until((driver) -> driver.findElement(usernameFieldLocator).isDisplayed());
-
- WebElement userNameField = driver.findElement(usernameFieldLocator);
- WebElement passwordField = driver.findElement(passwordFieldLocator);
- WebElement submitButton = driver.findElement(submitButtonLocator);
-
- userNameField.sendKeys("standard_user");
- passwordField.sendKeys("secret_sauce");
- submitButton.click();
-
- Assertions.assertEquals("https://www.saucedemo.com/inventory.html", driver.getCurrentUrl());
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/sauce_features/AccessibilityTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/sauce_features/AccessibilityTest.java
new file mode 100644
index 00000000..74eb69f2
--- /dev/null
+++ b/selenium-examples/src/test/java/com/saucedemo/selenium/sauce_features/AccessibilityTest.java
@@ -0,0 +1,29 @@
+package com.saucedemo.selenium.sauce_features;
+
+import com.deque.html.axecore.results.Results;
+import com.deque.html.axecore.selenium.AxeBuilder;
+import com.saucedemo.selenium.TestBase;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+
+public class AccessibilityTest extends TestBase {
+
+ @BeforeEach
+ public void setup(TestInfo testInfo) {
+ startChromeSession(testInfo);
+ }
+
+ @DisplayName("Deque Axe Test With Selenium Not html")
+ @Test
+ public void accessibilityTest() {
+ driver.navigate().to("https://www.saucedemo.com");
+
+ AxeBuilder axeBuilder = new AxeBuilder();
+ Results accessibilityResults = axeBuilder.analyze(driver);
+
+ Assertions.assertEquals(3, accessibilityResults.getViolations().size());
+ }
+}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/sauce_features/PerformanceTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/sauce_features/PerformanceTest.java
new file mode 100644
index 00000000..ccda3fb2
--- /dev/null
+++ b/selenium-examples/src/test/java/com/saucedemo/selenium/sauce_features/PerformanceTest.java
@@ -0,0 +1,94 @@
+package com.saucedemo.selenium.sauce_features;
+
+import com.saucedemo.selenium.TestBase;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.chrome.ChromeOptions;
+
+/** Performance Test. */
+public class PerformanceTest extends TestBase {
+
+ @BeforeEach
+ public void setup(TestInfo testInfo) {
+ ChromeOptions options = new ChromeOptions();
+ options.setPlatformName("Windows 10");
+ options.setBrowserVersion("117");
+
+ Map sauceOptions = defaultSauceOptions(testInfo);
+ sauceOptions.put("capturePerformance", true);
+ sauceOptions.put("extendedDebugging", true);
+
+ startSession(options, sauceOptions);
+ }
+
+ @DisplayName("Ensure all metrics within historical limits")
+ @Test
+ public void performanceAllMetrics() {
+ driver.get("https://www.saucedemo.com");
+
+ HashMap args = new HashMap<>();
+ args.put("name", testInfo.getDisplayName());
+ Map performance =
+ (Map)
+ ((JavascriptExecutor) driver).executeScript("sauce:performance", args);
+
+ try {
+ Assertions.assertEquals("pass", performance.get("result"));
+ } catch (AssertionError ignored) {
+ System.out.println(
+ "Metrics are out of historical limits, but this is just a demo, so do not fail in CI");
+ }
+ }
+
+ @DisplayName("Ensure provided metrics within historical limits")
+ @Test
+ public void performanceSpecificMetrics() {
+ driver.get("https://www.saucedemo.com");
+
+ HashMap args = new HashMap<>();
+ args.put("name", testInfo.getDisplayName());
+ args.put("metrics", Arrays.asList("load", "firstContentfulPaint"));
+
+ Map performance =
+ (Map)
+ ((JavascriptExecutor) driver).executeScript("sauce:performance", args);
+
+ try {
+ Assertions.assertEquals("pass", performance.get("result"));
+ } catch (AssertionError ignored) {
+ System.out.println(
+ "Metrics are out of historical limits, but this is just a demo, so do not fail in CI");
+ }
+ }
+
+ @DisplayName("Get log of performance metrics from previous navigation")
+ @Test
+ public void performanceLog() {
+ driver.get("https://www.saucedemo.com");
+
+ HashMap metricsLog = new HashMap<>();
+ metricsLog.put("type", "sauce:performance");
+ Map metrics =
+ (Map) ((JavascriptExecutor) driver).executeScript("sauce:log", metricsLog);
+
+ Assertions.assertTrue((long) metrics.get("firstInteractive") < 5000);
+ }
+
+ @DisplayName("Get jankiness metrics from previous navigation")
+ @Test
+ public void jankiness() {
+ driver.get("https://www.saucedemo.com");
+
+ Map metrics =
+ (Map) ((JavascriptExecutor) driver).executeScript("sauce:jankinessCheck");
+
+ Assertions.assertTrue((Double) metrics.get("score") > 0.5);
+ }
+}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/AttributePropertyTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/AttributePropertyTest.java
deleted file mode 100644
index 8bec2a24..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/AttributePropertyTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.saucedemo.selenium.se4newfeatures;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebElement;
-public class AttributePropertyTest extends SauceBaseTest {
-
- /**
- * Property and Attribute often return the same value (especially in Java, since values are converted to Strings,
- * but they are different
- * attribute is defined in html spec: https://dom.spec.whatwg.org/#concept-element-attribute
- * property is defined in ecma spec: https://262.ecma-international.org/5.1/#sec-4.3.26
- *
- * WebElement#getAttribute guesses which value you want from an element's attribute or property value and returns that
- *
- * Since this doesn't make sense in a specification, w3c defines 2 new endpoints, made available in Selenium as:
- * WebElement#getDomProperty and WebElement#getDomAttribute
- *
- * The old behavior with the existing method is still available, but executes a large javascript blob
- * New behavior should be preferred for performance and preciseness
- */
-
- @DisplayName("getDomProperty returns false, getDomAttribute returns null")
- @Test
- public void domPropertyReturnsFalseInsteadOfNullForBoolean() {
- driver.navigate().to("http://watir.com/examples/forms_with_input_elements.html");
- WebElement element = driver.findElement(By.id("new_user_interests_books"));
-
- Assertions.assertEquals("true", element.getAttribute("checked"));
- Assertions.assertEquals("true", element.getDomProperty("checked"));
-
- element.click();
-
- Assertions.assertNull(element.getAttribute("checked"));
- Assertions.assertEquals("false", element.getDomProperty("checked"));
- }
-
- @DisplayName("getDomProperty Boolean result updates, getDomAttribute does not")
- @Test
- public void attributePropertyDoesNotUpdateBoolean() {
- driver.navigate().to("http://watir.com/examples/forms_with_input_elements.html");
- WebElement element = driver.findElement(By.id("new_user_interests_books"));
-
- Assertions.assertEquals("true", element.getAttribute("checked"));
- Assertions.assertEquals("true", element.getDomAttribute("checked"));
- Assertions.assertEquals("true", element.getDomProperty("checked"));
-
- element.click();
-
- Assertions.assertNull(element.getAttribute("checked"));
- Assertions.assertEquals("false", element.getDomProperty("checked"));
- Assertions.assertEquals("true", element.getDomAttribute("checked"));
- }
-
- @DisplayName("getDomProperty String result updates, getDomAttribute does not")
- @Test
- public void attributePropertyDoesNotUpdateString() {
- driver.navigate().to("http://watir.com/examples/forms_with_input_elements.html");
- WebElement element = driver.findElement(By.id("new_user_occupation"));
-
- Assertions.assertEquals("Developer", element.getAttribute("value"));
- Assertions.assertEquals("Developer", element.getDomAttribute("value"));
- Assertions.assertEquals("Developer", element.getDomProperty("value"));
-
- element.clear();
- element.sendKeys("Engineer");
-
- Assertions.assertEquals("Engineer", element.getAttribute("value"));
- Assertions.assertEquals("Developer", element.getDomAttribute("value"));
- Assertions.assertEquals("Engineer", element.getDomProperty("value"));
- }
-
- @DisplayName("getDomAttribute is what is in the DOM, getDomProperty may includes parsing")
- @Test
- public void urlValues() {
- driver.navigate().to("http://watir.com/examples/non_control_elements.html");
- WebElement element = driver.findElement(By.id("link_3"));
-
- Assertions.assertEquals("http://watir.com/examples/forms_with_input_elements.html", element.getDomProperty("href"));
- Assertions.assertEquals("forms_with_input_elements.html", element.getDomAttribute("href"));
- }
-
- @DisplayName("getDomProperty is case sensitive, getDomAttribute is not")
- @Test
- public void caseSensitivity() {
- driver.navigate().to("http://watir.com/examples/forms_with_input_elements.html");
- WebElement element = driver.findElement(By.name("new_user_email"));
-
- Assertions.assertEquals("new_user_email", element.getDomAttribute("nAme"));
- Assertions.assertNull(element.getDomProperty("nAme"));
- }
-
- @DisplayName("property className is equivalent to attribute class")
- @Test
- public void className() {
- driver.navigate().to("http://watir.com/examples/forms_with_input_elements.html");
- WebElement element = driver.findElement(By.id("new_user_first_name"));
-
- Assertions.assertEquals("name", element.getDomProperty("className"));
- Assertions.assertEquals("name", element.getDomAttribute("class"));
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/ChromeNetworkTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/ChromeNetworkTest.java
deleted file mode 100644
index 3be4fb42..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/ChromeNetworkTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.saucedemo.selenium.se4newfeatures;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.WebDriverException;
-import org.openqa.selenium.chromium.ChromiumNetworkConditions;
-import org.openqa.selenium.chromium.HasNetworkConditions;
-import org.openqa.selenium.remote.Augmenter;
-
-public class ChromeNetworkTest extends SauceBaseTest {
-
- @Test
- public void toggleOffline() {
- WebDriver augmentedDriver = new Augmenter().augment(driver);
- ChromiumNetworkConditions networkConditions = new ChromiumNetworkConditions();
- networkConditions.setOffline(true);
- ((HasNetworkConditions) augmentedDriver).setNetworkConditions(networkConditions);
-
- try {
- driver.get("https://www.saucedemo.com");
- Assertions.fail("If Network is set to be offline, the previous line should throw an exception");
- } catch (WebDriverException ex) {
- ((HasNetworkConditions) augmentedDriver).setNetworkConditions(new ChromiumNetworkConditions());
- }
- driver.get("https://www.saucedemo.com");
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/FirefoxAddonTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/FirefoxAddonTest.java
deleted file mode 100644
index 65e9c91e..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/FirefoxAddonTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.saucedemo.selenium.se4newfeatures;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import com.saucelabs.saucebindings.options.SauceOptions;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.firefox.HasExtensions;
-import org.openqa.selenium.remote.Augmenter;
-import org.openqa.selenium.remote.LocalFileDetector;
-
-import java.nio.file.Paths;
-
-public class FirefoxAddonTest extends SauceBaseTest {
-
- public SauceOptions createSauceOptions() {
- return SauceOptions.firefox().build();
- }
-
- @Test
- public void addons() {
- driver.setFileDetector(new LocalFileDetector());
- WebDriver augmentedDriver = new Augmenter().augment(driver);
- String id = ((HasExtensions) augmentedDriver).installExtension(Paths.get("src/test/resources/ninja_saucebot-1.0-an+fx.xpi"));
-
- driver.get("https://www.saucedemo.com");
- Assertions.assertTrue(driver.findElements(By.className("bot_column2")).size() > 0);
- ((HasExtensions) augmentedDriver).uninstallExtension(id);
-
- driver.navigate().refresh();
- Assertions.assertEquals(0, driver.findElements(By.className("bot_column2")).size());
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/FirefoxContextTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/FirefoxContextTest.java
deleted file mode 100644
index 8a5078c5..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/FirefoxContextTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.saucedemo.selenium.se4newfeatures;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import com.saucelabs.saucebindings.options.SauceOptions;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.By;
-import org.openqa.selenium.JavascriptExecutor;
-import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.firefox.FirefoxCommandContext;
-import org.openqa.selenium.firefox.FirefoxOptions;
-import org.openqa.selenium.firefox.HasContext;
-import org.openqa.selenium.remote.Augmenter;
-
-public class FirefoxContextTest extends SauceBaseTest {
-
- public SauceOptions createSauceOptions() {
- FirefoxOptions firefoxOptions = new FirefoxOptions();
- firefoxOptions.addPreference("intl.accept_languages", "de-DE");
- return SauceOptions.firefox(firefoxOptions).setGeckodriverVersion("0.30.0").build();
- }
-
- @Test
- public void changePrefs() {
- driver.get("https://www.google.com");
-
- String lang1 = driver.findElement(By.id("gws-output-pages-elements-homepage_additional_languages__als")).getText();
- Assertions.assertTrue(lang1.contains("angeboten auf"));
-
- WebDriver augmentedDriver = new Augmenter().augment(driver);
- ((HasContext) augmentedDriver).setContext(FirefoxCommandContext.CHROME);
-
- ((JavascriptExecutor) driver).executeScript("Services.prefs.setStringPref('intl.accept_languages', 'es-ES')");
-
- ((HasContext) augmentedDriver).setContext(FirefoxCommandContext.CONTENT);
- driver.navigate().refresh();
-
- String lang2 = driver.findElement(By.id("gws-output-pages-elements-homepage_additional_languages__als")).getText();
- Assertions.assertTrue(lang2.contains("Ofrecido por"));
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/MSEdgeTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/MSEdgeTest.java
deleted file mode 100644
index 09b0fae4..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/MSEdgeTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.saucedemo.selenium.se4newfeatures;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import com.saucelabs.saucebindings.options.SauceOptions;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.By;
-import org.openqa.selenium.edge.EdgeOptions;
-
-import java.util.Collections;
-
-public class MSEdgeTest extends SauceBaseTest {
-
- public SauceOptions createSauceOptions() {
- EdgeOptions options = new EdgeOptions();
-
- // Selenium 3 did not support any direct options for Chromium Edge
- // Selenium 4 allows setting all compliant values on EdgeOptions
-
- options.setExperimentalOption("excludeSwitches",
- Collections.singletonList("disable-popup-blocking"));
-
- return SauceOptions.edge(options).build();
- }
-
- @Test
- public void edgeExecution() {
- driver.get("https://deliver.courseavenue.com/PopupTest.aspx");
- driver.findElement(By.cssSelector("input[type=submit]")).click();
-
- Assertions.assertEquals(1, driver.getWindowHandles().size());
- driver.quit();
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/NewWindowTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/NewWindowTest.java
deleted file mode 100644
index 35e5c6e0..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/NewWindowTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.saucedemo.selenium.se4newfeatures;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.Point;
-import org.openqa.selenium.WindowType;
-
-public class NewWindowTest extends SauceBaseTest {
-
- @Test
- public void secondWindow() {
- driver.switchTo().newWindow(WindowType.WINDOW);
- driver.manage().window().setPosition(new Point(100, 400));
-
- Assertions.assertEquals(2, driver.getWindowHandles().toArray().length);
- }
-
- @Test
- public void secondTab() {
- driver.switchTo().newWindow(WindowType.TAB);
-
- Assertions.assertEquals(2, driver.getWindowHandles().toArray().length);
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/RelativeLocatorsTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/RelativeLocatorsTest.java
deleted file mode 100644
index 6913c783..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/RelativeLocatorsTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.saucedemo.selenium.se4newfeatures;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.By;
-import org.openqa.selenium.WebElement;
-
-import static org.openqa.selenium.support.locators.RelativeLocator.with;
-
-public class RelativeLocatorsTest extends SauceBaseTest {
-
- @Test
- public void relativeLocators() {
- driver.get("https://www.diemol.com/selenium-4-demo/relative-locators-demo.html");
-
- WebElement element = driver.findElement(with(By.tagName("li"))
- .toLeftOf(By.id("berlin"))
- .below(By.id("warsaw")));
-
- Assertions.assertEquals("london", element.getAttribute("id"));
-
- driver.executeScript("arguments[0].style.filter='blur(8px)'", element);
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/RemoteWebDriverBuilderTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/RemoteWebDriverBuilderTest.java
deleted file mode 100644
index 9194b094..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/RemoteWebDriverBuilderTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.saucedemo.selenium.se4newfeatures;
-
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInfo;
-import org.openqa.selenium.OutputType;
-import org.openqa.selenium.UnexpectedAlertBehaviour;
-import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.firefox.FirefoxOptions;
-import org.openqa.selenium.firefox.HasFullPageScreenshot;
-import org.openqa.selenium.remote.RemoteWebDriver;
-import org.openqa.selenium.remote.http.ClientConfig;
-
-import java.time.Duration;
-import java.util.HashMap;
-import java.util.Map;
-public class RemoteWebDriverBuilderTest {
-
- /**
- * RemoteWebDriver builder gives you a few great things off the bat:
- * 1. Allows you to easily set Connection and Read Timeouts
- * 2. Automatically applies augmentation for casting to valid interfaces
- * 3. Keeps Browser Options and Sauce Options separate
- * 4. Address values are Strings not URL, which is just easier
- */
- @DisplayName("Use RemoteWebDriverBuilder class")
- @Test
- public void webDriverBuilder(TestInfo testInfo) {
- FirefoxOptions browserOptions = new FirefoxOptions();
-
- browserOptions.setPlatformName("Windows 10");
- browserOptions.setBrowserVersion("latest");
- browserOptions.setAcceptInsecureCerts(true);
- browserOptions.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.IGNORE);
-
- Map sauceOptions = new HashMap<>();
- sauceOptions.put("name", testInfo.getDisplayName());
- sauceOptions.put("build", System.getenv("BUILD_NAME") + ": " + System.getenv("BUILD_NUMBER"));
- sauceOptions.put("username", System.getenv("SAUCE_USERNAME"));
- sauceOptions.put("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
-
- ClientConfig config = ClientConfig.defaultConfig()
- .readTimeout(Duration.ofMinutes(3));
-
- WebDriver driver = RemoteWebDriver.builder()
- .oneOf(browserOptions)
- .setCapability("sauce:options", sauceOptions)
- .address("https://ondemand.us-west-1.saucelabs.com/wd/hub")
- .config(config)
- .build();
-
- ((HasFullPageScreenshot) driver).getFullPageScreenshotAs(OutputType.FILE);
-
- driver.quit();
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/TimeoutsTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/TimeoutsTest.java
deleted file mode 100644
index 959d07f5..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/TimeoutsTest.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.saucedemo.selenium.se4newfeatures;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.WebDriver;
-
-import java.time.Duration;
-public class TimeoutsTest extends SauceBaseTest {
-
- @Test
- public void getTimoutValues() {
- WebDriver.Timeouts timeouts = driver.manage().timeouts();
-
- timeouts.pageLoadTimeout(Duration.ofSeconds(33));
- timeouts.implicitlyWait(Duration.ofMillis(333));
- timeouts.scriptTimeout(Duration.ofSeconds(33));
- timeouts.getPageLoadTimeout();
- // These getters do not exist in Selenium 3
- Assertions.assertEquals(Duration.ofSeconds(33), timeouts.getPageLoadTimeout());
- Assertions.assertEquals(Duration.ofMillis(333), timeouts.getImplicitWaitTimeout());
- Assertions.assertEquals(Duration.ofSeconds(33), timeouts.getScriptTimeout());
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/ViewPageChromeTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/ViewPageChromeTest.java
deleted file mode 100644
index 1a5557c5..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/ViewPageChromeTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.saucedemo.selenium.se4newfeatures;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import com.saucelabs.saucebindings.options.SauceOptions;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.OutputType;
-import org.openqa.selenium.Pdf;
-import org.openqa.selenium.chrome.ChromeOptions;
-import org.openqa.selenium.print.PrintOptions;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-public class ViewPageChromeTest extends SauceBaseTest {
- public final static String directory = "src/test/screenshots/";
-
- public SauceOptions createSauceOptions() {
- ChromeOptions options = new ChromeOptions();
- // note: headless only actually required for print page
- options.setHeadless(true);
-
- return SauceOptions.chrome(options).build();
- }
-
- @Test
- public void printPage() throws IOException {
- driver.navigate().to("https://www.saucedemo.com/v1/inventory.html");
-
- Path printPage = Paths.get(directory + "PrintPageChrome.pdf");
- Pdf print = driver.print(new PrintOptions());
-
- Files.write(printPage, OutputType.BYTES.convertFromBase64Png(print.getContent()));
- }
-
- @Test
- public void takeScreenshot() throws IOException {
- driver.navigate().to("https://www.saucedemo.com/v1/inventory.html");
- byte[] screenshotAs = driver.getScreenshotAs(OutputType.BYTES);
-
- Path screenshot = Paths.get(directory + "TakeScreenshotChrome.png");
- Files.write(screenshot, screenshotAs);
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/ViewPageFirefoxTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/ViewPageFirefoxTest.java
deleted file mode 100644
index 0172501a..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4newfeatures/ViewPageFirefoxTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.saucedemo.selenium.se4newfeatures;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import com.saucelabs.saucebindings.options.SauceOptions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.OutputType;
-import org.openqa.selenium.Pdf;
-import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.firefox.HasFullPageScreenshot;
-import org.openqa.selenium.print.PrintOptions;
-import org.openqa.selenium.remote.Augmenter;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-public class ViewPageFirefoxTest extends SauceBaseTest {
- public final static String directory = "src/test/screenshots/";
-
- public SauceOptions createSauceOptions() {
- return SauceOptions.firefox()
- .setGeckodriverVersion("0.30.0")
- .setBrowserVersion("beta")
- .build();
- }
-
- @BeforeEach
- public void navigate() {
- driver.navigate().to("https://www.saucedemo.com/v1/inventory.html");
- }
-
- @Test
- public void printPage() throws IOException {
-
- Path printPage = Paths.get(directory + "PrintPageFirefox.pdf");
- Pdf print = driver.print(new PrintOptions());
-
- Files.write(printPage, OutputType.BYTES.convertFromBase64Png(print.getContent()));
- }
-
- @Test
- public void takeScreenshot() throws IOException {
-
- Path screenshot = Paths.get(directory + "TakeScreenshotFirefox.png");
- byte[] screenshotAs = driver.getScreenshotAs(OutputType.BYTES);
-
- Files.write(screenshot, screenshotAs);
- }
-
- @Test
- public void takeFullPageScreenshot() throws IOException {
- WebDriver augmentedDriver = new Augmenter().augment(driver);
- File file = ((HasFullPageScreenshot) augmentedDriver).getFullPageScreenshotAs(OutputType.FILE);
-
- Path fullPageScreenshot = Paths.get(directory + "TakeFullPageScreenshotFirefox.png");
- Files.move(file.toPath(), fullPageScreenshot);
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4updates/CapabilitiesMergeTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4updates/CapabilitiesMergeTest.java
deleted file mode 100644
index 31513ce3..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4updates/CapabilitiesMergeTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.saucedemo.selenium.se4updates;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.PageLoadStrategy;
-import org.openqa.selenium.UnexpectedAlertBehaviour;
-import org.openqa.selenium.chrome.ChromeOptions;
-public class CapabilitiesMergeTest {
-
- @DisplayName("Selenium 4 Can not merge in place!")
- @Test
- public void doesNotMergeInPlace() {
- ChromeOptions options1 = new ChromeOptions();
- ChromeOptions options2 = new ChromeOptions();
-
- options1.setPageLoadStrategy(PageLoadStrategy.EAGER);
- options2.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.IGNORE);
-
- options1.merge(options2);
-
- Assertions.assertNotEquals(UnexpectedAlertBehaviour.IGNORE, options1.getCapability("unhandledPromptBehavior"));
- }
-
- @DisplayName("Selenium 4 Has to merge as a new object")
- @Test
- public void mergeNewObject() {
- ChromeOptions options1 = new ChromeOptions();
- ChromeOptions options2 = new ChromeOptions();
-
- options1.setPageLoadStrategy(PageLoadStrategy.EAGER);
- options2.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.IGNORE);
-
- ChromeOptions options3 = options1.merge(options2);
-
- Assertions.assertEquals(UnexpectedAlertBehaviour.IGNORE, options3.getCapability("unhandledPromptBehavior"));
- }
-
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4updates/DurationParameterTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4updates/DurationParameterTest.java
deleted file mode 100644
index c85ab608..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4updates/DurationParameterTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.saucedemo.selenium.se4updates;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.support.ui.WebDriverWait;
-
-import java.time.Duration;
-import java.util.concurrent.TimeUnit;
-public class DurationParameterTest extends SauceBaseTest {
-
- @DisplayName("Timeout integers still work but are deprecated")
- @Test
- public void timeoutIntegersDeprecated() {
-
- // Uses Seconds
- WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(5));
-
- // Uses Long / TimeUnit
- driver.manage().timeouts().implicitlyWait(Duration.ofMillis(555));
- }
-
- @DisplayName("Timeouts now use Duration instances")
- @Test
- public void timeoutUnitsDeprecated() {
-
- // Uses Seconds
- WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
-
- // Uses Long / TimeoutUnit
- driver.manage().timeouts().implicitlyWait(Duration.ofMillis(555));
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/se4updates/FindByTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/se4updates/FindByTest.java
deleted file mode 100644
index 1a419d38..00000000
--- a/selenium-examples/src/test/java/com/saucedemo/selenium/se4updates/FindByTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.saucedemo.selenium.se4updates;
-
-import com.saucelabs.saucebindings.junit5.SauceBaseTest;
-import org.junit.jupiter.api.Test;
-import org.openqa.selenium.By;
-public class FindByTest extends SauceBaseTest {
-
- @Test
- public void findElement() {
- driver.navigate().to("https://www.saucedemo.com");
-
- // These are no longer available at all in Selenium 4:
- // driver.findElementById("user-name");
- // driver.findElementByCssSelector("#password");
- // driver.findElementByClassName("btn_action");
-
- driver.findElement(By.cssSelector("#user-name"));
- driver.findElement(By.cssSelector("#password"));
- driver.findElement(By.cssSelector(".btn_action"));
- }
-}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/AttributePropertyTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/AttributePropertyTest.java
new file mode 100644
index 00000000..891687c3
--- /dev/null
+++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/AttributePropertyTest.java
@@ -0,0 +1,110 @@
+package com.saucedemo.selenium.selenium_features;
+
+import com.saucedemo.selenium.TestBase;
+import org.junit.jupiter.api.*;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+public class AttributePropertyTest extends TestBase {
+
+ @BeforeEach
+ public void setup(TestInfo testInfo) {
+ startChromeSession(testInfo);
+ }
+
+ /**
+ * Property and Attribute often return the same value (especially in Java, since values are
+ * converted to Strings, but they are different attribute is defined in html spec:
+ * https://dom.spec.whatwg.org/#concept-element-attribute property is defined in ecma spec:
+ * https://262.ecma-international.org/5.1/#sec-4.3.26
+ *
+ *
WebElement#getAttribute guesses which value you want from an element's attribute or property
+ * value and returns that
+ *
+ *
Since this doesn't make sense in a specification, w3c defines 2 new endpoints, made
+ * available in Selenium as: WebElement#getDomProperty and WebElement#getDomAttribute
+ *
+ *
The old behavior with the existing method is still available, but executes a large
+ * javascript blob New behavior should be preferred for performance and preciseness
+ */
+ @DisplayName("getDomProperty returns false, getDomAttribute returns null")
+ @Test
+ public void domPropertyReturnsFalseInsteadOfNullForBoolean() {
+ driver.navigate().to("http://watir.com/examples/forms_with_input_elements.html");
+ WebElement element = driver.findElement(By.id("new_user_interests_books"));
+
+ Assertions.assertEquals("true", element.getAttribute("checked"));
+ Assertions.assertEquals("true", element.getDomProperty("checked"));
+
+ element.click();
+
+ Assertions.assertNull(element.getAttribute("checked"));
+ Assertions.assertEquals("false", element.getDomProperty("checked"));
+ }
+
+ @DisplayName("getDomProperty Boolean result updates, getDomAttribute does not")
+ @Test
+ public void attributePropertyDoesNotUpdateBoolean() {
+ driver.navigate().to("http://watir.com/examples/forms_with_input_elements.html");
+ WebElement element = driver.findElement(By.id("new_user_interests_books"));
+
+ Assertions.assertEquals("true", element.getAttribute("checked"));
+ Assertions.assertEquals("true", element.getDomAttribute("checked"));
+ Assertions.assertEquals("true", element.getDomProperty("checked"));
+
+ element.click();
+
+ Assertions.assertNull(element.getAttribute("checked"));
+ Assertions.assertEquals("false", element.getDomProperty("checked"));
+ Assertions.assertEquals("true", element.getDomAttribute("checked"));
+ }
+
+ @DisplayName("getDomProperty String result updates, getDomAttribute does not")
+ @Test
+ public void attributePropertyDoesNotUpdateString() {
+ driver.navigate().to("http://watir.com/examples/forms_with_input_elements.html");
+ WebElement element = driver.findElement(By.id("new_user_occupation"));
+
+ Assertions.assertEquals("Developer", element.getAttribute("value"));
+ Assertions.assertEquals("Developer", element.getDomAttribute("value"));
+ Assertions.assertEquals("Developer", element.getDomProperty("value"));
+
+ element.clear();
+ element.sendKeys("Engineer");
+
+ Assertions.assertEquals("Engineer", element.getAttribute("value"));
+ Assertions.assertEquals("Developer", element.getDomAttribute("value"));
+ Assertions.assertEquals("Engineer", element.getDomProperty("value"));
+ }
+
+ @DisplayName("getDomAttribute is what is in the DOM, getDomProperty may includes parsing")
+ @Test
+ public void urlValues() {
+ driver.navigate().to("http://watir.com/examples/non_control_elements.html");
+ WebElement element = driver.findElement(By.id("link_3"));
+
+ Assertions.assertEquals(
+ "http://watir.com/examples/forms_with_input_elements.html", element.getDomProperty("href"));
+ Assertions.assertEquals("forms_with_input_elements.html", element.getDomAttribute("href"));
+ }
+
+ @DisplayName("getDomProperty is case sensitive, getDomAttribute is not")
+ @Test
+ public void caseSensitivity() {
+ driver.navigate().to("http://watir.com/examples/forms_with_input_elements.html");
+ WebElement element = driver.findElement(By.name("new_user_email"));
+
+ Assertions.assertEquals("new_user_email", element.getDomAttribute("nAme"));
+ Assertions.assertNull(element.getDomProperty("nAme"));
+ }
+
+ @DisplayName("property className is equivalent to attribute class")
+ @Test
+ public void className() {
+ driver.navigate().to("http://watir.com/examples/forms_with_input_elements.html");
+ WebElement element = driver.findElement(By.id("new_user_first_name"));
+
+ Assertions.assertEquals("name", element.getDomProperty("className"));
+ Assertions.assertEquals("name", element.getDomAttribute("class"));
+ }
+}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/CapabilitiesMergeTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/CapabilitiesMergeTest.java
new file mode 100644
index 00000000..f4a435de
--- /dev/null
+++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/CapabilitiesMergeTest.java
@@ -0,0 +1,45 @@
+package com.saucedemo.selenium.selenium_features;
+
+import com.saucedemo.selenium.TestBase;
+import org.junit.jupiter.api.*;
+import org.openqa.selenium.PageLoadStrategy;
+import org.openqa.selenium.UnexpectedAlertBehaviour;
+import org.openqa.selenium.chrome.ChromeOptions;
+
+public class CapabilitiesMergeTest extends TestBase {
+
+ @BeforeEach
+ public void setup(TestInfo testInfo) {
+ startChromeSession(testInfo);
+ }
+
+ @DisplayName("Selenium 4 Can not merge in place!")
+ @Test
+ public void doesNotMergeInPlace() {
+ ChromeOptions options1 = new ChromeOptions();
+ ChromeOptions options2 = new ChromeOptions();
+
+ options1.setPageLoadStrategy(PageLoadStrategy.EAGER);
+ options2.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.IGNORE);
+
+ options1.merge(options2);
+
+ Assertions.assertNotEquals(
+ UnexpectedAlertBehaviour.IGNORE, options1.getCapability("unhandledPromptBehavior"));
+ }
+
+ @DisplayName("Selenium 4 Has to merge as a new object")
+ @Test
+ public void mergeNewObject() {
+ ChromeOptions options1 = new ChromeOptions();
+ ChromeOptions options2 = new ChromeOptions();
+
+ options1.setPageLoadStrategy(PageLoadStrategy.EAGER);
+ options2.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.IGNORE);
+
+ ChromeOptions options3 = options1.merge(options2);
+
+ Assertions.assertEquals(
+ UnexpectedAlertBehaviour.IGNORE, options3.getCapability("unhandledPromptBehavior"));
+ }
+}
diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/CdpEndpointTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/CdpEndpointTest.java
new file mode 100644
index 00000000..bbdc9800
--- /dev/null
+++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/CdpEndpointTest.java
@@ -0,0 +1,76 @@
+package com.saucedemo.selenium.selenium_features;
+
+import com.google.common.collect.ImmutableMap;
+import com.saucedemo.selenium.TestBase;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Cookie;
+import org.openqa.selenium.chromium.HasCdp;
+import org.openqa.selenium.remote.Augmenter;
+
+public class CdpEndpointTest extends TestBase {
+
+ @BeforeEach
+ public void setup(TestInfo testInfo) {
+ startChromeSession(testInfo);
+ driver = new Augmenter().augment(driver);
+ }
+
+ @Test
+ public void setCookieCdpEndpoint() {
+ Map cookie = new HashMap<>();
+ cookie.put("name", "cheese");
+ cookie.put("value", "gouda");
+ cookie.put("domain", "www.selenium.dev");
+ cookie.put("secure", true);
+
+ ((HasCdp) driver).executeCdpCommand("Network.setCookie", cookie);
+
+ driver.get("https://www.selenium.dev");
+ Cookie cheese = driver.manage().getCookieNamed("cheese");
+ Assertions.assertEquals("gouda", cheese.getValue());
+ }
+
+ @Test
+ public void performanceMetricsCdpEndpoint() {
+ driver.get("https://www.selenium.dev/selenium/web/frameset.html");
+
+ ((HasCdp) driver).executeCdpCommand("Performance.enable", new HashMap<>());
+
+ Map response =
+ ((HasCdp) driver).executeCdpCommand("Performance.getMetrics", new HashMap<>());
+ List