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.saucelabs appium-junit4-cucumber-examples + 1.0-SNAPSHOT + - - io.cucumber cucumber-java - 7.3.3 + 7.20.1 test io.cucumber cucumber-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.saucelabs appium-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-logging commons-logging - 1.2 + 1.3.4 org.assertj assertj-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 crossPlatformData() { - return Arrays.asList(new Object[][] { - { "desktop", "safari", "latest", "macOS 11.00" }, - { "desktop", "chrome", "latest-1", "macOS 13" }, - { "desktop", "firefox", "latest", "Windows 11" }, - { "desktop", "chrome", "latest", "Windows 10" } - }); - } - @Rule - public TestName name = new TestName(); - - @Before - public void setup() throws MalformedURLException { - - System.out.println("BeforeMethod hook"); - URL url; - - switch (region) { - case "us": - url = new URL(SAUCE_US_URL); - break; - case "eu": - default: - url = new URL(SAUCE_EU_URL); - break; - } + @Parameterized.Parameter public String platform; - boolean isBuildCap = false; - MutableCapabilities caps = new MutableCapabilities(); - MutableCapabilities sauceOptions = new MutableCapabilities(); - - switch (platform) { - case "desktop": - caps.setCapability("browserName", browserDeviceName); - caps.setCapability("browserVersion", browserPlatformVersion); - caps.setCapability("platformName", platformName); - break; - case "android": - caps.setCapability("platformName", "android"); - caps.setCapability("appium:automationName", "UiAutomator2"); - caps.setCapability("browserName", "chrome"); - caps.setCapability("appium:deviceName", browserDeviceName); - caps.setCapability("appium:platformVersion", browserPlatformVersion); - break; - case "ios": - caps.setCapability("platformName", "iOS"); - caps.setCapability("appium:automationName", "XCuiTest"); - caps.setCapability("browserName", "safari"); - caps.setCapability("appium:deviceName", browserDeviceName); - caps.setCapability("appium:platformVersion", browserPlatformVersion); - break; - default: - throw new IllegalStateException("Unexpected value: " + platform); - } + @Parameterized.Parameter(1) + public String browserDeviceName; - sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME")); - sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY")); - sauceOptions.setCapability("name", name.getMethodName()); + @Parameterized.Parameter(2) + public String browserPlatformVersion; - if (!isBuildCap) { //handle build cap - LocalDateTime dateTime = LocalDateTime.now(); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy-HH"); - String buildLocal = "sauceDemo-" +dateTime.format(formatter); - String buildVal = System.getenv("BUILD_TAG"); - sauceOptions.setCapability("build", buildVal == null ? buildLocal : buildVal); - } + @Parameterized.Parameter(3) + public String platformName; - caps.setCapability("sauce:options", sauceOptions); + @Rule public TestName name = new TestName(); + protected RemoteWebDriver driver; - try { - driver = new RemoteWebDriver(url, caps); - - } catch (Exception e) { - System.out.println("*** Problem to create the driver " + e.getMessage()); - throw new RuntimeException(e); - } - } - - - @Rule - public TestRule watcher = new TestWatcher() { + @Rule + public TestRule watcher = + new TestWatcher() { @Override protected void succeeded(Description description) { - if(driver != null) - { - System.out.println("Test Passed!"); - driver.executeScript("sauce:job-result=passed"); - driver.quit(); - } + if (driver != null) { + System.out.println("Test Passed!"); + driver.executeScript("sauce:job-result=passed"); + driver.quit(); + } } @Override public void failed(Throwable e, Description description) { - if(driver != null) - { - System.out.println("Test Failed!"); - driver.executeScript("sauce:job-result=failed"); - driver.executeScript("sauce:context=" +e.getMessage()); - driver.quit(); - } + if (driver != null) { + System.out.println("Test Failed!"); + driver.executeScript("sauce:job-result=failed"); + driver.executeScript("sauce:context=" + e.getMessage()); + driver.quit(); + } } + }; + + @Parameterized.Parameters() + public static Collection crossPlatformData() { + return Arrays.asList( + new Object[][] { + {"desktop", "safari", "latest", "macOS 11.00"}, + {"desktop", "chrome", "latest-1", "macOS 13"}, + {"desktop", "firefox", "latest", "Windows 11"}, + {"desktop", "chrome", "latest", "Windows 10"} + }); + } + + @Before + public void setup() throws MalformedURLException { + + System.out.println("BeforeMethod hook"); + URL url; + + switch (region) { + case "us": + url = new URL(SAUCE_US_URL); + break; + case "eu": + default: + url = new URL(SAUCE_EU_URL); + break; + } + + boolean isBuildCap = false; + MutableCapabilities caps = new MutableCapabilities(); + MutableCapabilities sauceOptions = new MutableCapabilities(); + + switch (platform) { + case "desktop": + caps.setCapability("browserName", browserDeviceName); + caps.setCapability("browserVersion", browserPlatformVersion); + caps.setCapability("platformName", platformName); + break; + case "android": + caps.setCapability("platformName", "android"); + caps.setCapability("appium:automationName", "UiAutomator2"); + caps.setCapability("browserName", "chrome"); + caps.setCapability("appium:deviceName", browserDeviceName); + caps.setCapability("appium:platformVersion", browserPlatformVersion); + break; + case "ios": + caps.setCapability("platformName", "iOS"); + caps.setCapability("appium:automationName", "XCuiTest"); + caps.setCapability("browserName", "safari"); + caps.setCapability("appium:deviceName", browserDeviceName); + caps.setCapability("appium:platformVersion", browserPlatformVersion); + break; + default: + throw new IllegalStateException("Unexpected value: " + platform); + } + + sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME")); + sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY")); + sauceOptions.setCapability("name", name.getMethodName()); - }; + if (!isBuildCap) { // handle build cap + LocalDateTime dateTime = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy-HH"); + String buildLocal = "sauceDemo-" + dateTime.format(formatter); + String buildVal = System.getenv("BUILD_TAG"); + sauceOptions.setCapability("build", buildVal == null ? buildLocal : buildVal); + } + + caps.setCapability("sauce:options", sauceOptions); + try { + driver = new RemoteWebDriver(url, caps); + + } catch (Exception e) { + System.out.println("*** Problem to create the driver " + e.getMessage()); + throw new RuntimeException(e); + } + } } diff --git a/best-practice/src/test/java/com/saucedemo/tests/DesktopTests.java b/best-practice/src/test/java/com/saucedemo/tests/DesktopTests.java index caa80e02..935c6bf3 100644 --- a/best-practice/src/test/java/com/saucedemo/tests/DesktopTests.java +++ b/best-practice/src/test/java/com/saucedemo/tests/DesktopTests.java @@ -1,5 +1,8 @@ package com.saucedemo.tests; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import com.saucedemo.pages.LoginPage; import com.saucedemo.pages.ProductsPage; import org.junit.Test; @@ -7,34 +10,31 @@ import org.junit.runners.Parameterized; import org.openqa.selenium.TimeoutException; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - /** Desktop Tests. */ @RunWith(Parameterized.class) public class DesktopTests extends BaseTest { - @Test() - public void loginWorks() { - LoginPage loginPage = new LoginPage(driver); - loginPage.visit(); - loginPage.login("standard_user"); - assertTrue(new ProductsPage(driver).isDisplayed()); - } + @Test() + public void loginWorks() { + LoginPage loginPage = new LoginPage(driver); + loginPage.visit(); + loginPage.login("standard_user"); + assertTrue(new ProductsPage(driver).isDisplayed()); + } - @Test(expected = TimeoutException.class) - public void lockedOutUser() { - LoginPage loginPage = new LoginPage(driver); - loginPage.visit(); - loginPage.login("locked_out_user"); - assertFalse(new ProductsPage(driver).isDisplayed()); - } + @Test(expected = TimeoutException.class) + public void lockedOutUser() { + LoginPage loginPage = new LoginPage(driver); + loginPage.visit(); + loginPage.login("locked_out_user"); + assertFalse(new ProductsPage(driver).isDisplayed()); + } - @Test(expected = TimeoutException.class) - public void invalidCredentials() { - LoginPage loginPage = new LoginPage(driver); - loginPage.visit(); - loginPage.login("foo_bar_user"); - assertFalse(new ProductsPage(driver).isDisplayed()); - } + @Test(expected = TimeoutException.class) + public void invalidCredentials() { + LoginPage loginPage = new LoginPage(driver); + loginPage.visit(); + loginPage.login("foo_bar_user"); + assertFalse(new ProductsPage(driver).isDisplayed()); + } } diff --git a/best-practice/src/test/java/com/saucedemo/tests/EmuSimWebAppTests.java b/best-practice/src/test/java/com/saucedemo/tests/EmuSimWebAppTests.java index 7d3b7267..e4403d2d 100644 --- a/best-practice/src/test/java/com/saucedemo/tests/EmuSimWebAppTests.java +++ b/best-practice/src/test/java/com/saucedemo/tests/EmuSimWebAppTests.java @@ -1,9 +1,15 @@ package com.saucedemo.tests; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import com.saucedemo.Endpoints; import com.saucedemo.MobileTestsBase; import com.saucedemo.pages.LoginPage; import com.saucedemo.pages.ProductsPage; +import java.net.MalformedURLException; +import java.util.Arrays; +import java.util.Collection; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -12,91 +18,87 @@ import org.openqa.selenium.TimeoutException; import org.openqa.selenium.remote.RemoteWebDriver; -import java.net.MalformedURLException; -import java.util.Arrays; -import java.util.Collection; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Emulator / Simulator Web Tests. - */ +/** Emulator / Simulator Web Tests. */ @RunWith(Parameterized.class) public class EmuSimWebAppTests extends MobileTestsBase { - /* - * Configure our data driven parameters - * */ - @Parameterized.Parameter - public String browserName; - @Parameterized.Parameter(1) - public String platform; - @Parameterized.Parameter(2) - public String platformVersion; - @Parameterized.Parameter(3) - public String deviceName; + /* + * Configure our data driven parameters + * */ + @Parameterized.Parameter public String browserName; + + @Parameterized.Parameter(1) + public String platform; + + @Parameterized.Parameter(2) + public String platformVersion; + + @Parameterized.Parameter(3) + public String deviceName; - @Parameterized.Parameters() - public static Collection crossBrowserData() { - return Arrays.asList(new Object[][]{ - {"Safari", "iOS", "14.3", "iPhone XS Max Simulator"}, - {"Safari", "iOS", "14.3", "iPhone XS Simulator"}, - {"Safari", "iOS", "14.3", "iPhone SE (2nd generation) Simulator"} - // Duplication below for demo purposes of massive parallelization -// {"Safari", "iOS", "14.3", "iPhone XS Max Simulator"}, -// {"Safari", "iOS", "14.3", "iPhone XS Simulator"}, -// {"Safari", "iOS", "14.3", "iPhone SE (2nd generation) Simulator"}, -// {"Safari", "iOS", "14.3", "iPhone XS Max Simulator"}, -// {"Safari", "iOS", "14.3", "iPhone XS Simulator"}, -// {"Safari", "iOS", "14.3", "iPhone SE (2nd generation) Simulator"}, -// {"Safari", "iOS", "14.3", "iPhone XS Max Simulator"}, -// {"Safari", "iOS", "14.3", "iPhone XS Simulator"}, -// {"Safari", "iOS", "14.3", "iPhone SE (2nd generation) Simulator"}, + @Parameterized.Parameters() + public static Collection crossBrowserData() { + return Arrays.asList( + new Object[][] { + {"Safari", "iOS", "16.2", "iPhone XS Max Simulator"}, + {"Safari", "iOS", "16.2", "iPhone XS Simulator"}, + {"Safari", "iOS", "16.2", "iPhone SE (2nd generation) Simulator"} + // Duplication below for demo purposes of massive parallelization + // https://saucelabs.com/products/platform-configurator#/ + // {"Safari", "iOS", "16.2", "iPhone XS Max Simulator"}, + // {"Safari", "iOS", "16.2", "iPhone XS Simulator"}, + // {"Safari", "iOS", "16.2", "iPhone SE (2nd generation) Simulator"}, + // {"Safari", "iOS", "16.2", "iPhone XS Max Simulator"}, + // {"Safari", "iOS", "16.2", "iPhone XS Simulator"}, + // {"Safari", "iOS", "16.2", "iPhone SE (2nd generation) Simulator"}, + // {"Safari", "iOS", "16.2", "iPhone XS Max Simulator"}, + // {"Safari", "iOS", "16.2", "iPhone XS Simulator"}, + // {"Safari", "iOS", "16.2", "iPhone SE (2nd generation) Simulator"}, }); - } + } - @Before - public void setUp() throws MalformedURLException { - //Configure these using Platform Configurator: - // https://wiki.saucelabs.com/display/DOCS/Platform+Configurator#/ - MutableCapabilities capabilities = new MutableCapabilities(); - capabilities.setCapability("browserName", browserName); - capabilities.setCapability("platformName", platform); - capabilities.setCapability("platformVersion", platformVersion); - capabilities.setCapability("deviceName", deviceName); + @Before + public void setUp() throws MalformedURLException { + // Configure these using Platform Configurator: + // https://saucelabs.com/products/platform-configurator#/ + MutableCapabilities capabilities = new MutableCapabilities(); + capabilities.setCapability("browserName", browserName); + capabilities.setCapability("platformName", platform); + capabilities.setCapability("appium:platformVersion", platformVersion); + capabilities.setCapability("appium:deviceName", deviceName); + capabilities.setCapability("appium:automationName", "XCUITest"); - capabilities.setCapability("name", testName.getMethodName()); - capabilities.setCapability("build", buildName); + MutableCapabilities sauceOptions = new MutableCapabilities(); + sauceOptions.setCapability("name", testName.getMethodName()); + sauceOptions.setCapability("build", buildName); - capabilities.setCapability("idleTimeout", "90"); - capabilities.setCapability("newCommandTimeout", "90"); - //EmuSim devices have Simulator/Emulator in the name + capabilities.setCapability("sauce:options", sauceOptions); + // EmuSim devices have Simulator/Emulator in the name - driver = new RemoteWebDriver(Endpoints.getEmuSimHub(), capabilities); - } + driver = new RemoteWebDriver(Endpoints.getEmuSimHub(), capabilities); + } - @Test - public void loginWorks() { - LoginPage loginPage = new LoginPage(driver); - loginPage.visit(); - loginPage.login("standard_user"); - assertTrue(new ProductsPage(driver).isDisplayed()); - } + @Test + public void loginWorks() { + LoginPage loginPage = new LoginPage(driver); + loginPage.visit(); + loginPage.login("standard_user"); + assertTrue(new ProductsPage(driver).isDisplayed()); + } - @Test(expected = TimeoutException.class) - public void lockedOutUser() { - LoginPage loginPage = new LoginPage(driver); - loginPage.visit(); - loginPage.login("locked_out_user"); - assertFalse(new ProductsPage(driver).isDisplayed()); - } + @Test(expected = TimeoutException.class) + public void lockedOutUser() { + LoginPage loginPage = new LoginPage(driver); + loginPage.visit(); + loginPage.login("locked_out_user"); + assertFalse(new ProductsPage(driver).isDisplayed()); + } - @Test(expected = TimeoutException.class) - public void invalidCredentials() { - LoginPage loginPage = new LoginPage(driver); - loginPage.visit(); - loginPage.login("foo_bar_user"); - assertFalse(new ProductsPage(driver).isDisplayed()); - } + @Test(expected = TimeoutException.class) + public void invalidCredentials() { + LoginPage loginPage = new LoginPage(driver); + loginPage.visit(); + loginPage.login("foo_bar_user"); + assertFalse(new ProductsPage(driver).isDisplayed()); + } } diff --git a/best-practice/src/test/java/com/saucedemo/tests/PerformanceTests.java b/best-practice/src/test/java/com/saucedemo/tests/PerformanceTests.java index a6167204..865e4ec3 100644 --- a/best-practice/src/test/java/com/saucedemo/tests/PerformanceTests.java +++ b/best-practice/src/test/java/com/saucedemo/tests/PerformanceTests.java @@ -6,24 +6,22 @@ import org.junit.Assert; import org.junit.Test; -/** - * Performance Tests. - */ +/** Performance Tests. */ public class PerformanceTests extends SauceBaseTest { - @Override - public SauceOptions createSauceOptions() { - return SauceOptions.chrome() - .setExtendedDebugging() - .setName(testName.getMethodName()) - .setCapturePerformance() - .build(); - } + @Override + public SauceOptions createSauceOptions() { + return SauceOptions.chrome() + .setExtendedDebugging() + .setName(testName.getMethodName()) + .setCapturePerformance() + .build(); + } - @Test - public void performanceDidntDegrade() { - LoginPage loginPage = new LoginPage(driver); - loginPage.visit(); + @Test + public void performanceDidntDegrade() { + LoginPage loginPage = new LoginPage(driver); + loginPage.visit(); - Assert.assertTrue(loginPage.getPageLoadTime() < 2000); - } + Assert.assertTrue(loginPage.getPageLoadTime() < 2000); + } } diff --git a/best-practice/src/test/java/com/saucedemo/tests/RealDeviceWebTests.java b/best-practice/src/test/java/com/saucedemo/tests/RealDeviceWebTests.java index f3c7259e..fbe0ba10 100644 --- a/best-practice/src/test/java/com/saucedemo/tests/RealDeviceWebTests.java +++ b/best-practice/src/test/java/com/saucedemo/tests/RealDeviceWebTests.java @@ -1,10 +1,16 @@ package com.saucedemo.tests; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + import com.saucedemo.Endpoints; import com.saucedemo.MobileTestsBase; import com.saucedemo.pages.LoginPage; import com.saucedemo.pages.ProductsPage; import io.appium.java_client.ios.IOSDriver; +import java.net.MalformedURLException; +import java.util.Arrays; +import java.util.Collection; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -12,73 +18,65 @@ import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.TimeoutException; -import java.net.MalformedURLException; -import java.util.Arrays; -import java.util.Collection; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Real Device Web Tests. - */ +/** Real Device Web Tests. */ @RunWith(Parameterized.class) public class RealDeviceWebTests extends MobileTestsBase { - @Parameterized.Parameter - public String deviceName; + @Parameterized.Parameter public String deviceName; - @Parameterized.Parameters() - public static Collection iosConfigurations() { - return Arrays.asList(new Object[][]{ - {"iPhone 11.*"}, - {"iPhone 12.*"}, - {"iPad 10.*"}, - {"iPad Air.*"}, - {"iPad.*"}, - // Duplication below for demo purposes of massive parallelization + @Parameterized.Parameters() + public static Collection iosConfigurations() { + return Arrays.asList( + new Object[][] { + {"iPhone 11.*"}, {"iPhone 12.*"}, {"iPad 10.*"}, {"iPad Air.*"}, {"iPad.*"}, + // Duplication below for demo purposes of massive parallelization + // https://saucelabs.com/products/platform-configurator#/ }); - } + } + + @Before + public void setUp() throws MalformedURLException { + /* + * if you set the browserName => always starts with webcontext + if you set the app => always starts with native context + if you set the package/bundleId => always starts with native context + if you have a hybrid app and set autoWebview => always starts with webview + * */ + MutableCapabilities capabilities = new MutableCapabilities(); + capabilities.setCapability("platformName", "iOS"); + capabilities.setCapability("browserName", "Safari"); + capabilities.setCapability("appium:language", "en"); + capabilities.setCapability("appium:deviceName", deviceName); + + MutableCapabilities sauceOptions = new MutableCapabilities(); + sauceOptions.setCapability("name", testName.getMethodName()); + sauceOptions.setCapability("build", buildName); - @Before - public void setUp() throws MalformedURLException { - MutableCapabilities capabilities = new MutableCapabilities(); - capabilities.setCapability("language", "en"); - capabilities.setCapability("platformName", "iOS"); - capabilities.setCapability("deviceName", deviceName); - /* - * if you set the browserName => always starts with webcontext - if you set the app => always starts with native context - if you set the package/bundleId => always starts with native context - if you have a hybrid app and set autoWebview => always starts with webview - * */ - capabilities.setCapability("browserName", "Safari"); - capabilities.setCapability("name", testName.getMethodName()); - capabilities.setCapability("build", buildName); + capabilities.setCapability("sauce:options", sauceOptions); - driver = new IOSDriver(Endpoints.getRealDevicesHub(), capabilities); - } + driver = new IOSDriver(Endpoints.getRealDevicesHub(), capabilities); + } - @Test - public void loginWorks() { - LoginPage loginPage = new LoginPage(getDriver()); - loginPage.visit(); - loginPage.login("standard_user"); - assertTrue(new ProductsPage(driver).isDisplayed()); - } + @Test + public void loginWorks() { + LoginPage loginPage = new LoginPage(getDriver()); + loginPage.visit(); + loginPage.login("standard_user"); + assertTrue(new ProductsPage(driver).isDisplayed()); + } - @Test(expected = TimeoutException.class) - public void lockedOutUser() { - LoginPage loginPage = new LoginPage(driver); - loginPage.visit(); - loginPage.login("locked_out_user"); - assertFalse(new ProductsPage(driver).isDisplayed()); - } + @Test(expected = TimeoutException.class) + public void lockedOutUser() { + LoginPage loginPage = new LoginPage(driver); + loginPage.visit(); + loginPage.login("locked_out_user"); + assertFalse(new ProductsPage(driver).isDisplayed()); + } - @Test(expected = TimeoutException.class) - public void invalidCredentials() { - LoginPage loginPage = new LoginPage(driver); - loginPage.visit(); - loginPage.login("foo_bar_user"); - assertFalse(new ProductsPage(driver).isDisplayed()); - } + @Test(expected = TimeoutException.class) + public void invalidCredentials() { + LoginPage loginPage = new LoginPage(driver); + loginPage.visit(); + loginPage.login("foo_bar_user"); + assertFalse(new ProductsPage(driver).isDisplayed()); + } } diff --git a/best-practice/src/test/java/com/saucedemo/tests/VisualCrossPlatformTests.java b/best-practice/src/test/java/com/saucedemo/tests/VisualCrossPlatformTests.java deleted file mode 100644 index 6812e5df..00000000 --- a/best-practice/src/test/java/com/saucedemo/tests/VisualCrossPlatformTests.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.saucedemo.tests; - -import com.saucedemo.Endpoints; -import com.saucedemo.MobileTestsBase; -import com.saucedemo.pages.CheckoutStepOnePage; -import com.saucedemo.pages.LoginPage; -import com.saucedemo.pages.ProductsPage; -import com.saucedemo.pages.ShoppingCartPage; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.remote.CapabilityType; -import org.openqa.selenium.remote.RemoteWebDriver; - -import java.net.URL; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; - -import static org.junit.Assert.assertNull; - -/** - * Cross Platform Tests for Visual. - * - * Note: Visual Tests do not run in Github By Default - */ -@RunWith(Parameterized.class) -public class VisualCrossPlatformTests extends MobileTestsBase { - /* - * Configure our data driven parameters - * */ - @Parameterized.Parameter - public String browserName; - @Parameterized.Parameter(2) - public String browserVersion; - @Parameterized.Parameter(1) - public String platform; - @Parameterized.Parameter(3) - public String viewportSize; - // Device name is a property added to know which device resolution is configured - @Parameterized.Parameter(4) - public String deviceName; - - @Parameterized.Parameters() - public static Collection crossBrowserData() { - return Arrays.asList(new Object[][]{ - {"Chrome", "Windows 10", "latest", "412x732", "Pixel XL"}, - {"Chrome", "Windows 10", "latest", "412x869", "Galaxy Note 10+"}, - {"Safari", "macOS 10.15", "latest", "375x812", "iPhone X"}, - {"Chrome", "Windows 10", "latest", "1080x720", "1080p"}, - {"Safari", "macOS 10.15", "latest", "1080x720", "1080p"} - }); - } - - @Before - public void setUp() throws Exception { - MutableCapabilities browserOptions = new MutableCapabilities(); - browserOptions.setCapability(CapabilityType.BROWSER_NAME, browserName); - browserOptions.setCapability(CapabilityType.BROWSER_VERSION, browserVersion); - browserOptions.setCapability(CapabilityType.PLATFORM_NAME, platform); - - MutableCapabilities sauceOptions = new MutableCapabilities(); - sauceOptions.setCapability("username", SAUCE_USERNAME); - sauceOptions.setCapability("accessKey", SAUCE_ACCESS_KEY); - sauceOptions.setCapability("name", testName.getMethodName()); - sauceOptions.setCapability("build", buildName); - browserOptions.setCapability("sauce:options", sauceOptions); - - MutableCapabilities visualOptions = new MutableCapabilities(); - visualOptions.setCapability("apiKey", SCREENER_API_KEY); - visualOptions.setCapability("projectName", "Sauce Demo Java"); - visualOptions.setCapability("viewportSize", viewportSize); - visualOptions.setCapability("failOnNewStates", false); - - browserOptions.setCapability("sauce:visual", visualOptions); - - URL url = Endpoints.getScreenerHub(); - driver = new RemoteWebDriver(url, browserOptions); - } - - @Test() - public void visualFlow() { - LoginPage loginPage = new LoginPage(driver); - loginPage.visit(); - driver.executeScript("/*@visual.init*/", deviceName); - loginPage.takeSnapshot(); - - loginPage.login("standard_user"); - new ProductsPage(driver).takeSnapshot(); - - ShoppingCartPage shoppingCartPage = new ShoppingCartPage(driver); - shoppingCartPage.visit(); - shoppingCartPage.takeSnapshot(); - - CheckoutStepOnePage stepOneCheckoutPage = new CheckoutStepOnePage(driver); - stepOneCheckoutPage.visit(); - stepOneCheckoutPage.takeSnapshot(); - - Map response = stepOneCheckoutPage.getVisualResults(); - assertNull(response.get("message")); - } -} diff --git a/gitpod/pom.xml b/gitpod/pom.xml index 850d5007..091bfa8b 100644 --- a/gitpod/pom.xml +++ b/gitpod/pom.xml @@ -1,55 +1,65 @@ - - - demo-java - com.saucelabs - 1.0-SNAPSHOT - - 4.0.0 - gitpod + 4.0.0 - - - com.saucelabs - saucebindings-junit5 - 1.0.0 - test - - - org.seleniumhq.selenium - selenium-java - 4.11.0 - - + com.saucelabs + gitpod + 1.0-SNAPSHOT - - - - 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 - - - - - - + Sauce Labs Gitpod Examples + + + 3.5.1 + 9.3.0 + 4.25.0 + + + + + com.saucelabs + saucebindings-junit5 + 1.5.0 + test + + + org.seleniumhq.selenium + selenium-java + ${selenium.version} + + + io.appium + java-client + ${appium.version} + test + + + + + + + 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 = dynamic + + + + + + diff --git a/gitpod/src/test/java/com/saucedemo/selenium/AppiumTest.java b/gitpod/src/test/java/com/saucedemo/selenium/AppiumTest.java index ac7d9769..ad3e3c5d 100644 --- a/gitpod/src/test/java/com/saucedemo/selenium/AppiumTest.java +++ b/gitpod/src/test/java/com/saucedemo/selenium/AppiumTest.java @@ -1,6 +1,13 @@ -package com.saucedemo.selenium.demo; +package com.saucedemo.selenium; -import org.junit.jupiter.api.Assertions; +import io.appium.java_client.AppiumDriver; +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.ios.IOSDriver; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -9,97 +16,85 @@ import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.TestWatcher; import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.remote.RemoteWebDriver; -import io.appium.java_client.android.AndroidDriver; -import io.appium.java_client.ios.IOSDriver; -import io.appium.java_client.AppiumDriver; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.ArrayList; - -/** - * Demo tests with Appium. - */ +/** Demo tests with Appium. */ public class AppiumTest { - public AppiumDriver driver; - public MutableCapabilities options; + public AppiumDriver driver; + public MutableCapabilities options; - /** - * 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(); + /** + * 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, InterruptedException { - String platformName = System.getenv().getOrDefault("PLATFORM_NAME", "Android"); - options = new MutableCapabilities(); - String appName = System.getenv().getOrDefault("APP_NAME", null); - String defaultBrowser = appName != null ? null : "Chrome"; - options.setCapability("browserName", System.getenv().getOrDefault("BROWSER_NAME", defaultBrowser)); - options.setCapability("platformName", platformName); - options.setCapability("appium:app", "storage:filename=" + appName); - options.setCapability("appium:platformVersion", System.getenv("PLATFORM_VERSION")); - options.setCapability("appium:deviceName", System.getenv().getOrDefault("DEVICE_NAME", "Google.*")); - options.setCapability("appium:automationName", System.getenv().getOrDefault("AUTOMATION_NAME", "UiAutomator2")); + @BeforeEach + public void setup(TestInfo testInfo) throws MalformedURLException { + String platformName = System.getenv().getOrDefault("PLATFORM_NAME", "Android"); + options = new MutableCapabilities(); + String appName = System.getenv().getOrDefault("APP_NAME", null); + String defaultBrowser = appName != null ? null : "Chrome"; + options.setCapability( + "browserName", System.getenv().getOrDefault("BROWSER_NAME", defaultBrowser)); + options.setCapability("platformName", platformName); + if (appName != null) { + options.setCapability("appium:app", "storage:filename=" + appName); + } + options.setCapability("appium:platformVersion", System.getenv("PLATFORM_VERSION")); + options.setCapability( + "appium:deviceName", System.getenv().getOrDefault("DEVICE_NAME", "Google.*")); + options.setCapability( + "appium:automationName", System.getenv().getOrDefault("AUTOMATION_NAME", "UiAutomator2")); - ArrayList tags = new ArrayList(); - if (System.getenv("GITPOD_WORKSPACE_ID") != null) { - tags.add("gitpod"); - } + ArrayList tags = new ArrayList<>(); + if (System.getenv("GITPOD_WORKSPACE_ID") != null) { + tags.add("gitpod"); + } - Map sauceOptions = new HashMap<>(); - sauceOptions.put("appiumVersion", "2.0.0"); - sauceOptions.put("username", System.getenv("SAUCE_USERNAME")); - sauceOptions.put("accessKey", System.getenv("SAUCE_ACCESS_KEY")); - sauceOptions.put("build", System.getenv("BUILD")); - sauceOptions.put("name", testInfo.getDisplayName()); - sauceOptions.put("tags", tags); - options.setCapability("sauce:options", sauceOptions); + Map sauceOptions = new HashMap<>(); + sauceOptions.put("appiumVersion", "2.0.0"); + sauceOptions.put("username", System.getenv("SAUCE_USERNAME")); + sauceOptions.put("accessKey", System.getenv("SAUCE_ACCESS_KEY")); + sauceOptions.put("build", System.getenv("BUILD")); + sauceOptions.put("name", testInfo.getDisplayName()); + sauceOptions.put("tags", tags); + options.setCapability("sauce:options", sauceOptions); - String region = System.getenv().getOrDefault("REGION", "us-west-1"); - String ondemandUrl = "https://ondemand." + region + ".saucelabs.com:443/wd/hub"; - URL url = new URL(ondemandUrl); + String region = System.getenv().getOrDefault("REGION", "us-west-1"); + String ondemandUrl = "https://ondemand." + region + ".saucelabs.com:443/wd/hub"; + URL url = new URL(ondemandUrl); - boolean isIos = platformName.toLowerCase() == "ios"; - if (isIos) { - driver = new IOSDriver(url, options); - } else { - driver = new AndroidDriver(url, options); - } + if ("iOS".equalsIgnoreCase(platformName)) { + driver = new IOSDriver(url, options); + } else { + driver = new AndroidDriver(url, options); + } + } + @DisplayName("Appium Test from Gitpod") + @Test + public void navigateAndClose() throws InterruptedException { + // Add tests and assertions here + if (options.getCapability("browserName") != null) { + driver.get("https://saucedemo.com"); } - @DisplayName("Appium Test from Gitpod") - @Test - public void navigateAndClose() throws InterruptedException { - // Add tests and assertions here - if (options.getCapability("browserName") != null) { - driver.get("https://saucedemo.com"); - } + // Replace this with commands and assertions + Thread.sleep(5000); + } - // Replace this with commands and assertions - Thread.sleep(5000); + /** 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(); } - /** - * 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(); - } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + driver.executeScript("sauce:job-result=failed"); + driver.quit(); } + } } diff --git a/gitpod/src/test/java/com/saucedemo/selenium/SeleniumTest.java b/gitpod/src/test/java/com/saucedemo/selenium/SeleniumTest.java index 412ce3e3..40f769d3 100644 --- a/gitpod/src/test/java/com/saucedemo/selenium/SeleniumTest.java +++ b/gitpod/src/test/java/com/saucedemo/selenium/SeleniumTest.java @@ -1,5 +1,10 @@ -package com.saucedemo.selenium.demo; +package com.saucedemo.selenium; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +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; @@ -11,73 +16,63 @@ import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.remote.RemoteWebDriver; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.ArrayList; - -/** - * Demo tests with Selenium. - */ +/** Demo tests with Selenium. */ public class SeleniumTest { - public RemoteWebDriver driver; + 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(); + /** + * 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 { - MutableCapabilities options = new MutableCapabilities(); - options.setCapability("platformName", System.getenv("PLATFORM_NAME")); - options.setCapability("browserName", System.getenv().getOrDefault("BROWSER_NAME", "chrome")); - options.setCapability("browserVersion", System.getenv().getOrDefault("BROWSER_VERSION", "latest")); + @BeforeEach + public void setup(TestInfo testInfo) throws MalformedURLException { + MutableCapabilities options = new MutableCapabilities(); + options.setCapability("platformName", System.getenv("PLATFORM_NAME")); + options.setCapability("browserName", System.getenv().getOrDefault("BROWSER_NAME", "chrome")); + options.setCapability( + "browserVersion", System.getenv().getOrDefault("BROWSER_VERSION", "latest")); - ArrayList tags = new ArrayList(); - if (System.getenv("GITPOD_WORKSPACE_ID") != null) { - tags.add("gitpod"); - } + ArrayList tags = new ArrayList<>(); + if (System.getenv("GITPOD_WORKSPACE_ID") != null) { + tags.add("gitpod"); + } - Map sauceOptions = new HashMap<>(); - sauceOptions.put("username", System.getenv("SAUCE_USERNAME")); - sauceOptions.put("accessKey", System.getenv("SAUCE_ACCESS_KEY")); - sauceOptions.put("build", System.getenv("BUILD")); - sauceOptions.put("name", testInfo.getDisplayName()); - sauceOptions.put("tags", tags); - options.setCapability("sauce:options", sauceOptions); + Map sauceOptions = new HashMap<>(); + sauceOptions.put("username", System.getenv("SAUCE_USERNAME")); + sauceOptions.put("accessKey", System.getenv("SAUCE_ACCESS_KEY")); + sauceOptions.put("build", System.getenv("BUILD")); + sauceOptions.put("name", testInfo.getDisplayName()); + sauceOptions.put("tags", tags); + options.setCapability("sauce:options", sauceOptions); - String region = System.getenv().getOrDefault("REGION", "us-west-1"); - String ondemandUrl = "https://ondemand." + region + ".saucelabs.com:443/wd/hub"; - URL url = new URL(ondemandUrl); + String region = System.getenv().getOrDefault("REGION", "us-west-1"); + String ondemandUrl = "https://ondemand." + region + ".saucelabs.com:443/wd/hub"; + URL url = new URL(ondemandUrl); - driver = new RemoteWebDriver(url, options); - } + driver = new RemoteWebDriver(url, options); + } - @DisplayName("Selenium Test from Gitpod") - @Test - public void navigateAndClose() { - driver.navigate().to("https://www.saucedemo.com"); - Assertions.assertEquals("Swag Labs", driver.getTitle()); - } + @DisplayName("Selenium Test from Gitpod") + @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(); - } + /** 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(); - } + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + driver.executeScript("sauce:job-result=failed"); + driver.quit(); } + } } diff --git a/playwright-examples/README.md b/playwright-examples/README.md new file mode 100644 index 00000000..30700d88 --- /dev/null +++ b/playwright-examples/README.md @@ -0,0 +1,13 @@ +# Playwright Examples + +## Changes to be made (reference Sauce Account) + +```bash + export SAUCE_USERNAME=your_username + export SAUCE_ACCESS_KEY=your_access_key +``` + +## Running the tests + +- `mvn test` + diff --git a/playwright-examples/pom.xml b/playwright-examples/pom.xml new file mode 100644 index 00000000..3055022d --- /dev/null +++ b/playwright-examples/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + com.saucelabs + playwright-examples + 1.0-SNAPSHOT + + Sauce Labs Playwright Examples + + + UTF-8 + 11 + 11 + 5.11.3 + + + + + com.microsoft.playwright + playwright + 1.48.0 + test + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + com.saucelabs + saucerest + 2.5.3 + test + + + diff --git a/playwright-examples/src/test/java/com/saucelabs/playwrightexamples/TestExample.java b/playwright-examples/src/test/java/com/saucelabs/playwrightexamples/TestExample.java new file mode 100644 index 00000000..7eddc390 --- /dev/null +++ b/playwright-examples/src/test/java/com/saucelabs/playwrightexamples/TestExample.java @@ -0,0 +1,194 @@ +package com.saucelabs.playwrightexamples; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.microsoft.playwright.APIRequest; +import com.microsoft.playwright.APIRequestContext; +import com.microsoft.playwright.APIResponse; +import com.microsoft.playwright.Browser; +import com.microsoft.playwright.BrowserContext; +import com.microsoft.playwright.Page; +import com.microsoft.playwright.Playwright; +import com.microsoft.playwright.options.RequestOptions; +import com.saucelabs.saucerest.DataCenter; +import com.saucelabs.saucerest.SauceREST; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.regex.Pattern; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +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; + +public class TestExample { + + static final String SAUCE_USERNAME = System.getenv("SAUCE_USERNAME"); + static final String SAUCE_ACCESS_KEY = System.getenv("SAUCE_ACCESS_KEY"); + static final String SAUCE_URL = "https://ondemand.us-west-1.saucelabs.com/wd/hub/"; + static SauceREST sauceREST = new SauceREST(SAUCE_USERNAME, SAUCE_ACCESS_KEY, DataCenter.US_WEST); + static APIRequestContext request; + static Playwright playwright; + @RegisterExtension public SauceTestWatcher watcher = new SauceTestWatcher(); + Browser browser; + BrowserContext context; + Page page; + String sessionId; + String cdpEndpoint; + TestInfo testInfo; + + @BeforeAll + static void beforeAll() { + createPlaywright(); + createAPIRequestContext(); + } + + static void closePlaywright() { + if (playwright != null) { + playwright.close(); + playwright = null; + } + } + + @AfterAll + static void afterAll() { + closePlaywright(); + } + + static void createAPIRequestContext() { + request = + playwright.request().newContext(new APIRequest.NewContextOptions().setBaseURL(SAUCE_URL)); + } + + static void createPlaywright() { + playwright = Playwright.create(); + } + + private static JsonObject getSessionPayload() { + JsonObject sauceOptions = new JsonObject(); + sauceOptions.addProperty("username", SAUCE_USERNAME); + sauceOptions.addProperty("accessKey", SAUCE_ACCESS_KEY); + sauceOptions.addProperty("devTools", Boolean.TRUE); + sauceOptions.addProperty("_tptCommanderVersion", "stable"); + + JsonObject sessionRequest = new JsonObject(); + sessionRequest.addProperty("platformName", "macOS 13"); + sessionRequest.addProperty("browserName", "Chrome"); + sessionRequest.add("sauce:options", sauceOptions); + + JsonObject capabilities = new JsonObject(); + capabilities.add("alwaysMatch", sessionRequest); + JsonObject payload = new JsonObject(); + payload.add("capabilities", capabilities); + return payload; + } + + void createSession() { + JsonObject payload = getSessionPayload(); + + APIResponse newSessionResponse = + request.post("session", RequestOptions.create().setData(payload.toString())); + JsonObject newSessionBlob = new Gson().fromJson(newSessionResponse.text(), JsonObject.class); + sessionId = newSessionBlob.get("value").getAsJsonObject().get("sessionId").getAsString(); + cdpEndpoint = + newSessionBlob + .get("value") + .getAsJsonObject() + .get("capabilities") + .getAsJsonObject() + .get("se:cdp") + .getAsString(); + } + + @BeforeEach + void launchBrowserAndCreatePage(TestInfo testInfo) throws IOException { + createSession(); + this.testInfo = testInfo; + sauceREST.getJobsEndpoint().changeName(sessionId, testInfo.getDisplayName()); + browser = playwright.chromium().connectOverCDP(cdpEndpoint); + + // Maximize browser + Browser.NewContextOptions newContextOptions = + new Browser.NewContextOptions().setViewportSize(null); + context = browser.newContext(newContextOptions); + page = context.newPage(); + } + + @AfterEach + void closeContextAndWindow() throws IOException { + context.close(); + browser.close(); + request.delete("session/" + sessionId); + } + + @Test + void shouldClickButton() { + page.navigate( + "data:text/html,"); + page.locator("button").click(); + assertEquals("Clicked", page.evaluate("result")); + } + + @Test + void shouldCheckTheBox() { + page.setContent(""); + page.locator("input").check(); + assertTrue((Boolean) page.evaluate("() => window['checkbox'].checked")); + } + + @Test + void shouldSearchWiki() { + page.navigate("https://www.wikipedia.org/"); + page.locator("input[name=\"search\"]").click(); + page.locator("input[name=\"search\"]").fill("playwright"); + page.locator("input[name=\"search\"]").press("Enter"); + assertEquals("https://en.wikipedia.org/wiki/Playwright", page.url()); + } + + @Test + void shouldTakeScreenshot() { + page.navigate("https://playwright.dev"); + page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("example.png"))); + assertThat(page).hasTitle(Pattern.compile("Playwright")); + } + + public class SauceTestWatcher implements TestWatcher { + @Override + public void testSuccessful(ExtensionContext context) { + printResults(); + try { + sauceREST.getJobsEndpoint().passed(sessionId); + } catch (Exception e) { + System.out.println("Problem setting job as passed: " + e); + } + } + + @Override + public void testFailed(ExtensionContext context, Throwable cause) { + printResults(); + + try { + sauceREST.getJobsEndpoint().failed(sessionId); + } catch (Exception e) { + System.out.println("Problem setting job as failed: " + e); + } + } + + public void printResults() { + String sauceReporter = + String.format( + "SauceOnDemandSessionID=%s job-name=%s", sessionId, testInfo.getDisplayName()); + String sauceLink = String.format("Job Link: https://app.saucelabs.com/tests/%s", sessionId); + System.out.print(sauceReporter + "\n" + sauceLink + "\n"); + } + } +} diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 3c2b1905..00000000 --- a/pom.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - 4.0.0 - - com.saucelabs - demo-java - pom - 1.0-SNAPSHOT - - - 4.10.0 - 8.3.0 - 1.2.0 - 1.0.0 - 1.0.1 - 1.0.0 - 3.0.0-M5 - - - - best-practice - appium-junit4-cucumber-examples - gitpod - selenium-cucumber-examples - selenium-examples - selenium-junit4-examples - selenium-testng-examples - appium/appium-app/appium-app-examples - appium/appium-app/appium-app-best-practice - appium/appium-web/appium-web-examples - - - - com.saucelabs - sauce_bindings - ${sauce.version} - - - org.seleniumhq.selenium - selenium-java - ${selenium.version} - test - - - - io.appium - java-client - ${appium.version} - test - - - - test - - - org.apache.maven.plugins - maven-compiler-plugin - 3.0 - - 1.8 - 1.8 - - - - - diff --git a/renovate.json b/renovate.json new file mode 100644 index 00000000..5db72dd6 --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ] +} diff --git a/selenium-cucumber-examples/pom.xml b/selenium-cucumber-examples/pom.xml index f22e9ea0..0195e204 100644 --- a/selenium-cucumber-examples/pom.xml +++ b/selenium-cucumber-examples/pom.xml @@ -1,46 +1,46 @@ - - demo-java - com.saucelabs - 1.0-SNAPSHOT - + 4.0.0 + com.saucelabs selenium-cucumber-examples + 1.0-SNAPSHOT + + Sauce Labs Test Cucumber Examples - info.cukes + io.cucumber cucumber-java - 1.2.4 + 7.20.1 - info.cukes + io.cucumber cucumber-picocontainer - 1.2.4 + 7.20.1 test - info.cukes + io.cucumber cucumber-testng - 1.2.4 + 7.20.1 org.testng testng - 6.9.10 + 7.10.2 test - org.apache.commons + commons-io commons-io - 1.3.2 + 2.17.0 org.apache.maven.plugins maven-resources-plugin - 2.7 + 3.3.1 @@ -49,7 +49,7 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven.surefire.version} + 3.5.1 6 false @@ -66,7 +66,7 @@ maven-resources-plugin - 2.7 + 3.3.1 copy-resources @@ -89,4 +89,4 @@ - + \ 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> metricList = (List>) response.get("metrics"); + + Map metrics = new HashMap<>(); + for (Map metric : metricList) { + metrics.put((String) metric.get("name"), (Number) metric.get("value")); + } + + Assertions.assertTrue(metrics.get("DevToolsCommandDuration").doubleValue() > 0); + Assertions.assertEquals(12, metrics.get("Frames").intValue()); + } + + @Test + public void basicAuthCdpEndpoint() { + ((HasCdp) driver).executeCdpCommand("Network.enable", new HashMap<>()); + + String encodedAuth = Base64.getEncoder().encodeToString("admin:admin".getBytes()); + Map headers = + ImmutableMap.of("headers", ImmutableMap.of("authorization", "Basic " + encodedAuth)); + + ((HasCdp) driver).executeCdpCommand("Network.setExtraHTTPHeaders", headers); + + driver.get("https://the-internet.herokuapp.com/basic_auth"); + + Assertions.assertEquals( + "Congratulations! You must have the proper credentials.", + driver.findElement(By.tagName("p")).getText()); + } +} diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/ChromeNetworkTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/ChromeNetworkTest.java new file mode 100644 index 00000000..7123ba10 --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/ChromeNetworkTest.java @@ -0,0 +1,38 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +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.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 TestBase { + + @BeforeEach + public void setup(TestInfo testInfo) { + startChromeSession(testInfo); + } + + @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/selenium_features/DevToolsTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/DevToolsTest.java new file mode 100644 index 00000000..6ff8056d --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/DevToolsTest.java @@ -0,0 +1,422 @@ +package com.saucedemo.selenium.selenium_features; + +import static com.google.common.net.MediaType.JPEG; +import static org.openqa.selenium.devtools.events.CdpEventTypes.consoleEvent; +import static org.openqa.selenium.devtools.events.CdpEventTypes.domMutation; +import static org.openqa.selenium.remote.http.HttpMethod.DELETE; +import static org.openqa.selenium.support.ui.ExpectedConditions.presenceOfAllElementsLocatedBy; +import static org.openqa.selenium.support.ui.ExpectedConditions.presenceOfElementLocated; + +import com.google.common.collect.ImmutableMap; +import com.google.common.net.MediaType; +import com.saucedemo.selenium.TestBase; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Duration; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; +import java.util.function.Supplier; +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.Credentials; +import org.openqa.selenium.HasAuthentication; +import org.openqa.selenium.JavascriptException; +import org.openqa.selenium.UsernameAndPassword; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeOptions; +import org.openqa.selenium.devtools.DevTools; +import org.openqa.selenium.devtools.HasDevTools; +import org.openqa.selenium.devtools.NetworkInterceptor; +import org.openqa.selenium.devtools.v129.browser.Browser; +import org.openqa.selenium.devtools.v129.emulation.Emulation; +import org.openqa.selenium.devtools.v129.network.Network; +import org.openqa.selenium.devtools.v129.network.model.Headers; +import org.openqa.selenium.devtools.v129.performance.Performance; +import org.openqa.selenium.devtools.v129.performance.model.Metric; +import org.openqa.selenium.devtools.v129.runtime.Runtime; +import org.openqa.selenium.logging.HasLogEvents; +import org.openqa.selenium.remote.Augmenter; +import org.openqa.selenium.remote.http.ClientConfig; +import org.openqa.selenium.remote.http.Contents; +import org.openqa.selenium.remote.http.Filter; +import org.openqa.selenium.remote.http.HttpClient; +import org.openqa.selenium.remote.http.HttpMethod; +import org.openqa.selenium.remote.http.HttpRequest; +import org.openqa.selenium.remote.http.HttpResponse; +import org.openqa.selenium.remote.http.Routable; +import org.openqa.selenium.remote.http.Route; +import org.openqa.selenium.support.ui.WebDriverWait; + +public class DevToolsTest extends TestBase { + private static URL APP_URL; + + static { + try { + APP_URL = new URL("https://visual-todo-app-84499c59b74b.herokuapp.com"); + } catch (MalformedURLException ignore) { + // fall off + } + } + + WebDriverWait wait; + + @BeforeEach + public void setup(TestInfo testInfo) { + Map sauceOptions = defaultSauceOptions(testInfo); + sauceOptions.put("devtools", true); + startSession(new ChromeOptions(), sauceOptions); + + wait = new WebDriverWait(driver, Duration.ofSeconds(10)); + driver = new Augmenter().augment(driver); + + ClientConfig clientConfig = ClientConfig.defaultConfig().baseUrl(APP_URL); + HttpResponse response; + try (HttpClient client = HttpClient.Factory.createDefault().createClient(clientConfig)) { + response = client.execute(new HttpRequest(DELETE, APP_URL.toString() + "/items")); + } + Assertions.assertEquals(200, response.getStatus()); + } + + @Test + public void setCookie() { + DevTools devTools = ((HasDevTools) driver).getDevTools(); + devTools.createSession(); + + devTools.send( + Network.setCookie( + "cheese", + "gouda", + Optional.empty(), + Optional.of("www.selenium.dev"), + Optional.empty(), + Optional.of(true), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty())); + + driver.get("https://www.selenium.dev"); + Cookie cheese = driver.manage().getCookieNamed("cheese"); + Assertions.assertEquals("gouda", cheese.getValue()); + } + + @Test + public void performanceMetrics() { + driver.get("https://www.selenium.dev/selenium/web/frameset.html"); + + DevTools devTools = ((HasDevTools) driver).getDevTools(); + devTools.createSession(); + devTools.send(Performance.enable(Optional.empty())); + + List metricList = devTools.send(Performance.getMetrics()); + + Map metrics = new HashMap<>(); + for (Metric metric : metricList) { + metrics.put(metric.getName(), metric.getValue()); + } + + Assertions.assertTrue(metrics.get("DevToolsCommandDuration").doubleValue() > 0); + Assertions.assertEquals(12, metrics.get("Frames").intValue()); + } + + @Test + public void performanceMetricsWithCPUThrottling() { + driver.get("https://googlechrome.github.io/devtools-samples/jank/"); + + DevTools devTools = ((HasDevTools) driver).getDevTools(); + devTools.createSession(); + devTools.send(Performance.enable(Optional.empty())); + + List metricList = devTools.send(Performance.getMetrics()); + Metric heapCheckOne = + metricList.stream() + .filter(metric -> "JSHeapUsedSize".equals(metric.getName())) + .findFirst() + .orElse(new Metric("JSHeapUsedSize", 0)); + + devTools.send(Emulation.setCPUThrottlingRate(4)); + for (int i = 0; i < 15; i++) { + driver.findElement(By.className("add")).click(); + } + + metricList = devTools.send(Performance.getMetrics()); + Metric heapCheckTwo = + metricList.stream() + .filter(metric -> "JSHeapUsedSize".equals(metric.getName())) + .findFirst() + .orElse(new Metric("JSHeapUsedSize", 0)); + + Assertions.assertTrue(heapCheckOne.getValue().intValue() < heapCheckTwo.getValue().intValue()); + } + + @Test + public void basicAuthenticationCdpApi() { + DevTools devTools = ((HasDevTools) driver).getDevTools(); + devTools.createSession(); + devTools.send(Network.enable(Optional.of(100000), Optional.of(100000), Optional.of(100000))); + + String encodedAuth = Base64.getEncoder().encodeToString("admin:admin".getBytes()); + Map headers = ImmutableMap.of("Authorization", "Basic " + encodedAuth); + + devTools.send(Network.setExtraHTTPHeaders(new Headers(headers))); + + driver.get("https://the-internet.herokuapp.com/basic_auth"); + + Assertions.assertEquals( + "Congratulations! You must have the proper credentials.", + driver.findElement(By.tagName("p")).getText()); + } + + @Test + public void basicAuthenticationBidiApi() { + Predicate uriPredicate = uri -> uri.toString().contains("herokuapp.com"); + Supplier authentication = UsernameAndPassword.of("admin", "admin"); + + ((HasAuthentication) driver).register(uriPredicate, authentication); + + driver.get("https://the-internet.herokuapp.com/basic_auth"); + + String successMessage = "Congratulations! You must have the proper credentials."; + WebElement elementMessage = driver.findElement(By.tagName("p")); + Assertions.assertEquals(successMessage, elementMessage.getText()); + } + + @Test + public void consoleLogs() { + driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html"); + + DevTools devTools = ((HasDevTools) driver).getDevTools(); + devTools.createSession(); + devTools.send(Runtime.enable()); + + CopyOnWriteArrayList logs = new CopyOnWriteArrayList<>(); + devTools.addListener( + Runtime.consoleAPICalled(), + event -> logs.add((String) event.getArgs().get(0).getValue().orElse(""))); + + driver.findElement(By.id("consoleLog")).click(); + + wait.until(_d -> !logs.isEmpty()); + Assertions.assertEquals("Hello, world!", logs.get(0)); + } + + @Test + public void jsErrors() { + driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html"); + + DevTools devTools = ((HasDevTools) driver).getDevTools(); + devTools.createSession(); + devTools.send(Runtime.enable()); + + CopyOnWriteArrayList errors = new CopyOnWriteArrayList<>(); + devTools.getDomains().events().addJavascriptExceptionListener(errors::add); + + driver.findElement(By.id("jsException")).click(); + + wait.until(_d -> !errors.isEmpty()); + Assertions.assertTrue(errors.get(0).getMessage().contains("Error: Not working")); + } + + @Test + public void waitForDownload() { + driver.get("https://www.selenium.dev/selenium/web/downloads/download.html"); + + DevTools devTools = ((HasDevTools) driver).getDevTools(); + devTools.createSession(); + devTools.send( + Browser.setDownloadBehavior( + Browser.SetDownloadBehaviorBehavior.ALLOWANDNAME, + Optional.empty(), + Optional.of(""), + Optional.of(true))); + + AtomicBoolean completed = new AtomicBoolean(false); + devTools.addListener( + Browser.downloadProgress(), + e -> completed.set(Objects.equals(e.getState().toString(), "completed"))); + + driver.findElement(By.id("file-2")).click(); + + Assertions.assertDoesNotThrow(() -> wait.until(_d -> completed)); + } + + @Test + public void mutatedElements() { + driver.get("https://www.selenium.dev/selenium/web/dynamic.html"); + + CopyOnWriteArrayList mutations = new CopyOnWriteArrayList<>(); + ((HasLogEvents) driver).onLogEvent(domMutation(e -> mutations.add(e.getElement()))); + + driver.findElement(By.id("reveal")).click(); + + wait.until(_d -> !mutations.isEmpty()); + Assertions.assertEquals(mutations.get(0), driver.findElement(By.id("revealed"))); + } + + @Test + public void elementsMutation() { + driver.get("https://the-internet.herokuapp.com/dynamic_controls"); + + CopyOnWriteArrayList mutations = new CopyOnWriteArrayList<>(); + ((HasLogEvents) driver).onLogEvent(domMutation(e -> mutations.add(e.getElement()))); + + driver.findElement(By.cssSelector("#checkbox-example > button")).click(); + wait.until(_d -> !mutations.isEmpty()); + + driver.findElement(By.cssSelector("#checkbox-example > button")).click(); + wait.until(_d -> mutations.size() > 1); + + Assertions.assertTrue(mutations.size() >= 2); + } + + @Test + public void consoleLogsBidiApi() { + driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html"); + + CopyOnWriteArrayList messages = new CopyOnWriteArrayList<>(); + ((HasLogEvents) driver).onLogEvent(consoleEvent(e -> messages.add(e.getMessages().get(0)))); + + driver.findElement(By.id("consoleLog")).click(); + driver.findElement(By.id("consoleError")).click(); + + wait.until(_d -> messages.size() > 1); + Assertions.assertTrue(messages.contains("Hello, world!")); + Assertions.assertTrue(messages.contains("I am console error")); + } + + @Test + public void recordResponse() { + CopyOnWriteArrayList contentType = new CopyOnWriteArrayList<>(); + + try (NetworkInterceptor ignored = + new NetworkInterceptor( + driver, + (Filter) + next -> + req -> { + HttpResponse res = next.execute(req); + contentType.add(res.getHeader("Content-Type")); + return res; + })) { + driver.get("https://www.selenium.dev/selenium/web/blank.html"); + wait.until(_d -> contentType.size() > 1); + } + + Assertions.assertEquals("text/html; charset=utf-8", contentType.get(0)); + } + + @Test + public void transformResponses() { + try (NetworkInterceptor ignored = + new NetworkInterceptor( + driver, + Route.matching(req -> true) + .to( + () -> + req -> + new HttpResponse() + .setStatus(200) + .addHeader("Content-Type", MediaType.HTML_UTF_8.toString()) + .setContent(Contents.utf8String("Creamy, delicious cheese!"))))) { + + driver.get("https://www.selenium.dev/selenium/web/blank.html"); + } + + WebElement body = driver.findElement(By.tagName("body")); + Assertions.assertEquals("Creamy, delicious cheese!", body.getText()); + } + + @Test + void replaceImage() throws IOException { + String item = "Buy rice"; + Path path = Paths.get("src/test/resources/cat-and-dog.jpg"); + byte[] sauceBotImage = Files.readAllBytes(path); + Routable replaceImage = + Route.matching(req -> req.getUri().contains("unsplash.com")) + .to( + () -> + req -> + new HttpResponse() + .addHeader("Content-Type", JPEG.toString()) + .setContent(Contents.bytes(sauceBotImage))); + + try (NetworkInterceptor ignore = new NetworkInterceptor(driver, replaceImage)) { + driver.get(APP_URL.toString()); + + String inputFieldLocator = "input[data-testid='new-item-text']"; + WebElement inputField = + wait.until(presenceOfElementLocated(By.cssSelector(inputFieldLocator))); + inputField.sendKeys(item); + + driver.findElement(By.cssSelector("button[data-testid='new-item-button']")).click(); + + String itemLocator = String.format("div[data-testid='%s']", item); + List addedItem = + wait.until(presenceOfAllElementsLocatedBy(By.cssSelector(itemLocator))); + + Assertions.assertEquals(1, addedItem.size()); + } + } + + @Test + void replacingResponse() { + String item = "Clean the bathroom"; + String mockedItem = "Go to the park"; + + Routable apiPost = + Route.matching( + req -> req.getUri().contains("items") && req.getMethod().equals(HttpMethod.POST)) + .to( + () -> + req -> + new HttpResponse() + .addHeader("Content-Type", "application/json; charset=utf-8") + .setStatus(200) + .setContent( + Contents.asJson( + ImmutableMap.of( + "id", + "f2a5514c-f451-43a6-825c-8753a2566d6e", + "name", + mockedItem, + "completed", + false)))); + + try (NetworkInterceptor ignore = new NetworkInterceptor(driver, apiPost)) { + driver.get(APP_URL.toString()); + + String inputFieldLocator = "input[data-testid='new-item-text']"; + WebElement inputField = + wait.until(presenceOfElementLocated(By.cssSelector(inputFieldLocator))); + inputField.sendKeys(item); + + driver.findElement(By.cssSelector("button[data-testid='new-item-button']")).click(); + + String itemLocator = String.format("div[data-testid='%s']", mockedItem); + List addedItem = + wait.until(presenceOfAllElementsLocatedBy(By.cssSelector(itemLocator))); + + Assertions.assertEquals(1, addedItem.size()); + } + } +} diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/DurationParameterTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/DurationParameterTest.java new file mode 100644 index 00000000..637d5c81 --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/DurationParameterTest.java @@ -0,0 +1,39 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +import java.time.Duration; +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.support.ui.WebDriverWait; + +public class DurationParameterTest extends TestBase { + + @BeforeEach + public void setup(TestInfo testInfo) { + startChromeSession(testInfo); + } + + @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/selenium_features/EdgeIE.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/EdgeIE.java new file mode 100644 index 00000000..c8e52ed3 --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/EdgeIE.java @@ -0,0 +1,25 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; +import org.openqa.selenium.ie.InternetExplorerOptions; + +public class EdgeIE extends TestBase { + @BeforeEach + public void createSauceOptions(TestInfo testInfo) { + InternetExplorerOptions options = new InternetExplorerOptions(); + options.attachToEdgeChrome(); + options.setCapability("browserName", "microsoftedge"); + Map sauceOptions = defaultSauceOptions(testInfo); + + startSession(options, sauceOptions); + } + + @Test + public void ieMode() { + driver.get("https://www.saucedemo.com"); + } +} diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/FindByTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/FindByTest.java new file mode 100644 index 00000000..a03a42d4 --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/FindByTest.java @@ -0,0 +1,29 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; +import org.openqa.selenium.By; + +public class FindByTest extends TestBase { + + @BeforeEach + public void setup(TestInfo testInfo) { + startChromeSession(testInfo); + } + + @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/FirefoxAddonTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/FirefoxAddonTest.java new file mode 100644 index 00000000..9b86ab91 --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/FirefoxAddonTest.java @@ -0,0 +1,39 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +import java.nio.file.Paths; +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.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.firefox.HasExtensions; +import org.openqa.selenium.remote.Augmenter; + +public class FirefoxAddonTest extends TestBase { + + @BeforeEach + public void setup(TestInfo testInfo) { + startFirefoxSession(testInfo); + } + + @Test + public void addons() { + WebDriver augmentedDriver = new Augmenter().augment(driver); + String id = + ((HasExtensions) augmentedDriver) + .installExtension(Paths.get("src/test/resources/webextensions-selenium-example.xpi")); + + driver.get("https://www.saucedemo.com"); + WebElement injected = driver.findElement(By.id("webextensions-selenium-example")); + Assertions.assertEquals( + "Content injected by webextensions-selenium-example", injected.getText()); + + ((HasExtensions) augmentedDriver).uninstallExtension(id); + + driver.navigate().refresh(); + Assertions.assertEquals(0, driver.findElements(By.id("webextensions-selenium-example")).size()); + } +} diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/FirefoxContextTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/FirefoxContextTest.java new file mode 100644 index 00000000..91e0491c --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/FirefoxContextTest.java @@ -0,0 +1,53 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +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.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 TestBase { + + @BeforeEach + public void setup(TestInfo testInfo) { + FirefoxOptions firefoxOptions = new FirefoxOptions(); + firefoxOptions.addPreference("intl.accept_languages", "de-DE"); + Map sauceOptions = defaultSauceOptions(testInfo); + + startSession(firefoxOptions, sauceOptions); + } + + @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("gibt es auch")); + + 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/selenium_features/MSEdgeTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/MSEdgeTest.java new file mode 100644 index 00000000..e8c67ac3 --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/MSEdgeTest.java @@ -0,0 +1,33 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +import java.util.Collections; +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.edge.EdgeOptions; + +// Selenium 3 did not support any direct options for Chromium Edge (like excludeSwitches) +public class MSEdgeTest extends TestBase { + + @BeforeEach + public void createSauceOptions(TestInfo testInfo) { + EdgeOptions options = new EdgeOptions(); + options.setExperimentalOption( + "excludeSwitches", Collections.singletonList("disable-popup-blocking")); + Map sauceOptions = defaultSauceOptions(testInfo); + + startSession(options, sauceOptions); + } + + @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()); + } +} diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/NewWindowTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/NewWindowTest.java new file mode 100644 index 00000000..22ef7202 --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/NewWindowTest.java @@ -0,0 +1,32 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +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.Point; +import org.openqa.selenium.WindowType; + +public class NewWindowTest extends TestBase { + + @BeforeEach + public void setup(TestInfo testInfo) { + startChromeSession(testInfo); + } + + @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/selenium_features/PrintPdfChromeTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/PrintPdfChromeTest.java new file mode 100644 index 00000000..806817a0 --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/PrintPdfChromeTest.java @@ -0,0 +1,37 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +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.OutputType; +import org.openqa.selenium.Pdf; +import org.openqa.selenium.PrintsPage; +import org.openqa.selenium.print.PrintOptions; + +public class PrintPdfChromeTest extends TestBase { + public static Path directory; + + @BeforeEach + public void setup(TestInfo testInfo) throws IOException { + // PDF printing is only working in headless old mode + startChromeSession(testInfo, List.of("--headless=old")); + driver.navigate().to("https://www.saucedemo.com/v1/inventory.html"); + directory = Files.createTempDirectory("chrome-"); + directory.toFile().deleteOnExit(); + } + + @Test + public void printPage() throws IOException { + Pdf print = ((PrintsPage) driver).print(new PrintOptions()); + Path printPage = Paths.get(directory + "PrintPage.pdf"); + Files.write(printPage, OutputType.BYTES.convertFromBase64Png(print.getContent())); + Assertions.assertTrue(printPage.toFile().exists()); + } +} diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/RemoteWebDriverBuilderTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/RemoteWebDriverBuilderTest.java new file mode 100644 index 00000000..50caa97d --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/RemoteWebDriverBuilderTest.java @@ -0,0 +1,57 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +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; + +public class RemoteWebDriverBuilderTest extends TestBase { + + /** + * 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) { + this.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(); + this.driver = driver; + this.id = ((RemoteWebDriver) driver).getSessionId(); + + ((HasFullPageScreenshot) driver).getFullPageScreenshotAs(OutputType.FILE); + } +} diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/TimeoutsTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/TimeoutsTest.java new file mode 100644 index 00000000..345bd2f9 --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/TimeoutsTest.java @@ -0,0 +1,31 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +import java.time.Duration; +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.WebDriver; + +public class TimeoutsTest extends TestBase { + + @BeforeEach + public void setup(TestInfo testInfo) { + startChromeSession(testInfo); + } + + @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/selenium_features/ViewPageChromeTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/ViewPageChromeTest.java new file mode 100644 index 00000000..e28cfeee --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/ViewPageChromeTest.java @@ -0,0 +1,34 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +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.OutputType; +import org.openqa.selenium.TakesScreenshot; + +public class ViewPageChromeTest extends TestBase { + public static Path directory; + + @BeforeEach + public void setup(TestInfo testInfo) throws IOException { + startChromeSession(testInfo); + driver.navigate().to("https://www.saucedemo.com/v1/inventory.html"); + directory = Files.createTempDirectory("chrome-"); + directory.toFile().deleteOnExit(); + } + + @Test + public void takeScreenshot() throws IOException { + byte[] screenshotAs = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES); + + Path screenshot = Paths.get(directory + "Screenshot.png"); + Files.write(screenshot, screenshotAs); + Assertions.assertTrue(screenshot.toFile().exists()); + } +} diff --git a/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/ViewPageFirefoxTest.java b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/ViewPageFirefoxTest.java new file mode 100644 index 00000000..62535b6a --- /dev/null +++ b/selenium-examples/src/test/java/com/saucedemo/selenium/selenium_features/ViewPageFirefoxTest.java @@ -0,0 +1,56 @@ +package com.saucedemo.selenium.selenium_features; + +import com.saucedemo.selenium.TestBase; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +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.*; +import org.openqa.selenium.firefox.HasFullPageScreenshot; +import org.openqa.selenium.print.PrintOptions; +import org.openqa.selenium.remote.Augmenter; + +public class ViewPageFirefoxTest extends TestBase { + public static Path directory; + + @BeforeEach + public void setup(TestInfo testInfo) throws IOException { + startFirefoxSession(testInfo); + driver.navigate().to("https://www.saucedemo.com/v1/inventory.html"); + directory = Files.createTempDirectory("firefox-"); + directory.toFile().deleteOnExit(); + } + + @Test + public void printPage() throws IOException { + Pdf print = ((PrintsPage) driver).print(new PrintOptions()); + + Path printPage = Paths.get(directory + "PrintPage.pdf"); + Files.write(printPage, OutputType.BYTES.convertFromBase64Png(print.getContent())); + Assertions.assertTrue(printPage.toFile().exists()); + } + + @Test + public void takeScreenshot() throws IOException { + byte[] screenshotAs = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES); + + Path screenshot = Paths.get(directory + "Screenshot.png"); + Files.write(screenshot, screenshotAs); + Assertions.assertTrue(screenshot.toFile().exists()); + } + + @Test + public void takeFullPageScreenshot() throws IOException { + driver = new Augmenter().augment(driver); + byte[] screenshotAs = + ((HasFullPageScreenshot) driver).getFullPageScreenshotAs(OutputType.BYTES); + + Path fullPageScreenshot = Paths.get(directory + "FullPage.png"); + Files.write(fullPageScreenshot, screenshotAs); + Assertions.assertTrue(fullPageScreenshot.toFile().exists()); + } +} diff --git a/selenium-examples/src/test/resources/cat-and-dog.jpg b/selenium-examples/src/test/resources/cat-and-dog.jpg new file mode 100644 index 00000000..cfbe67e5 Binary files /dev/null and b/selenium-examples/src/test/resources/cat-and-dog.jpg differ diff --git a/selenium-examples/src/test/resources/ninja_saucebot-1.0-an+fx.xpi b/selenium-examples/src/test/resources/ninja_saucebot-1.0-an+fx.xpi deleted file mode 100644 index 1f8bcba2..00000000 Binary files a/selenium-examples/src/test/resources/ninja_saucebot-1.0-an+fx.xpi and /dev/null differ diff --git a/selenium-examples/src/test/resources/webextensions-selenium-example.xpi b/selenium-examples/src/test/resources/webextensions-selenium-example.xpi new file mode 100644 index 00000000..dca8e2e1 Binary files /dev/null and b/selenium-examples/src/test/resources/webextensions-selenium-example.xpi differ diff --git a/selenium-examples/src/test/screenshots/.keep b/selenium-examples/src/test/screenshots/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/selenium-junit4-examples/README.md b/selenium-junit4-examples/README.md new file mode 100644 index 00000000..853e9565 --- /dev/null +++ b/selenium-junit4-examples/README.md @@ -0,0 +1,12 @@ +# Selenium JUnit 4 examples + +The primary function of this project is to demonstrate using Sauce Labs with Selenium and JUnit 4, including: +* Setting valid options +* Sending test results to Sauce Labs +* Running in Parallel with Maven surefire. See [pom.xml](pom.xml) + +## Execute tests in parallel: +```bash +cd selenium-examples +mvn test -Dsurefire.parallel=20 +``` diff --git a/selenium-junit4-examples/pom.xml b/selenium-junit4-examples/pom.xml index 19679303..6ed2c85e 100644 --- a/selenium-junit4-examples/pom.xml +++ b/selenium-junit4-examples/pom.xml @@ -2,20 +2,41 @@ - - demo-java - com.saucelabs - 1.0-SNAPSHOT - 4.0.0 - selenium-junit4-examples + com.com.saucelabs + selenium_junit4_examples + 1.0-SNAPSHOT + + Sauce Labs JUnit4 Examples + Example code for using Selenium on Sauce labs + https://github.com/saucelabs-training/demo-java + + + MIT License + http://www.opensource.org/licenses/mit-license.php + repo + + + + com.saucelabs saucebindings-junit4 - ${sauce_junit4.version} + 1.5.0 + test + + + org.seleniumhq.selenium + selenium-java + 4.25.0 + + + com.titusfortner + selenium-logger + 2.4.0 test @@ -25,10 +46,10 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven.surefire.version} + 3.5.1 all - 100 + ${surefire.parallel} true false diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SauceConnectTest.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SauceConnectTest.java deleted file mode 100644 index db589754..00000000 --- a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SauceConnectTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.saucedemo.selenium.junit4; - -import com.saucelabs.saucebindings.SystemManager; -import com.saucelabs.saucebindings.junit4.SauceBaseTest; -import com.saucelabs.saucebindings.options.SauceOptions; -import org.junit.Ignore; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Test to demonstrate how Sauce Connect works. - */ -public class SauceConnectTest extends SauceBaseTest { - @Override - public SauceOptions createSauceOptions() { - return SauceOptions.chrome() - .setTunnelIdentifier(SystemManager.get("TUNNEL_IDENTIFIER")) - .setParentTunnel(SystemManager.get("PARENT_TUNNEL")) - .build(); - } - - @Ignore("this test only applies when running local app with Sauce Connect") - @Test - public void shouldOpen() { - // In order for Sauce to be able to Securely access your application, we use Sauce Connect - driver.get("http://localhost:3000"); - assertEquals("React App", driver.getTitle()); - } -} diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SimpleVisualE2ETest.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SimpleVisualE2ETest.java deleted file mode 100644 index 78ee1a60..00000000 --- a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/SimpleVisualE2ETest.java +++ /dev/null @@ -1,171 +0,0 @@ -package com.saucedemo.selenium.junit4; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.remote.CapabilityType; -import org.openqa.selenium.remote.RemoteWebDriver; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -/** - * Tests for running Visual Tests on Sauce. - */ -public class SimpleVisualE2ETest { - - protected RemoteWebDriver driver; - public String sauceUsername = System.getenv("SAUCE_USERNAME"); - public String sauceAccessKey = System.getenv("SAUCE_ACCESS_KEY"); - public String screenerApiKey = System.getenv("SCREENER_API_KEY"); - private MutableCapabilities capabilities; - private MutableCapabilities visualOptions; - - @Before - public void setUp() { - capabilities = new MutableCapabilities(); - capabilities.setCapability(CapabilityType.BROWSER_NAME, "chrome"); - capabilities.setCapability(CapabilityType.BROWSER_VERSION, "latest"); - capabilities.setCapability(CapabilityType.PLATFORM_NAME, "Windows 10"); - - MutableCapabilities sauceOptions = new MutableCapabilities(); - sauceOptions.setCapability("username", sauceUsername); - sauceOptions.setCapability("accesskey", sauceAccessKey); - capabilities.setCapability("sauce:options", sauceOptions); - - visualOptions = new MutableCapabilities(); - visualOptions.setCapability("apiKey", screenerApiKey); - visualOptions.setCapability("viewportSize", "1280x1024"); - } - - @Test - public void testVisualE2E() throws MalformedURLException { - MutableCapabilities visualOptions = new MutableCapabilities(); - visualOptions.setCapability("apiKey", screenerApiKey); - visualOptions.setCapability("projectName", "visual-e2e-test"); - visualOptions.setCapability("viewportSize", "1280x1024"); - visualOptions.setCapability("failOnNewStates", "false"); - capabilities.setCapability("sauce:visual", visualOptions); - // Visual requires validation when the browser version changes - capabilities.setCapability(CapabilityType.BROWSER_VERSION, "94"); - - URL url = new URL("https://hub.screener.io/wd/hub"); - driver = new RemoteWebDriver(url, capabilities); - - driver.get("https://saucedemo.com"); - - driver.executeScript("/*@visual.init*/", "testVisualE2E()"); - driver.executeScript("/*@visual.snapshot*/", "Home"); - Map response = (Map) driver.executeScript("/*@visual.end*/"); - assertNull(response.get("message")); - } - - @Test - public void samePagesDifferentBranches() throws MalformedURLException { - //* - // This example shows how a team might have a baseline snapshot in Prod - // that is compared against a snapshot in QA - // Since this test is against the same page, all snapshots should pass - // **/ - String projectName = "samePagesDifferentBranches()"; - visualOptions.setCapability("projectName", projectName); - visualOptions.setCapability("branch", "main"); - visualOptions.setCapability("baseBranch", "main"); - visualOptions.setCapability("alwaysAcceptBaseBranch", true); - capabilities.setCapability("sauce:visual", visualOptions); - - URL url = new URL("https://hub.screener.io/wd/hub"); - driver = new RemoteWebDriver(url, capabilities); - - driver.get("https://www.saucedemo.com"); - - // Capture a snapshot of a page on the main branch - driver.executeScript("/*@visual.init*/", "My Visual Test"); - driver.executeScript("/*@visual.snapshot*/", "Branch Compare"); - assertNoVisualDifferences(); - - //Capture a snapshot on a different branch - visualOptions.setCapability("branch", "2ndBranch"); - visualOptions.setCapability("baseBranch", "main"); - capabilities.setCapability("sauce:visual", visualOptions); - url = new URL("https://hub.screener.io/wd/hub"); - driver = new RemoteWebDriver(url, capabilities); - driver.get("https://www.saucedemo.com"); - driver.executeScript("/*@visual.init*/", "My Visual Test"); - driver.executeScript("/*@visual.snapshot*/", "Branch Compare"); - assertNoVisualDifferences(); - - visualOptions.setCapability("branch", "3rdBranch"); - visualOptions.setCapability("baseBranch", "main"); - capabilities.setCapability("sauce:visual", visualOptions); - url = new URL("https://hub.screener.io/wd/hub"); - driver = new RemoteWebDriver(url, capabilities); - driver.get("https://www.saucedemo.com"); - driver.executeScript("/*@visual.init*/", "My Visual Test"); - driver.executeScript("/*@visual.snapshot*/", "Branch Compare"); - assertNoVisualDifferences(); - } - - @Test - public void differentPagesDifferentBranches() throws MalformedURLException { - //* - // This example shows how a team might have a baseline snapshot in Prod - // that is compared against a snapshot in QA - // Since this test is against different pages, all snapshots should fail - // **/ - String projectName = "differentPagesDifferentBranches()"; - visualOptions.setCapability("projectName", projectName); - visualOptions.setCapability("branch", "main"); - visualOptions.setCapability("baseBranch", "main"); - visualOptions.setCapability("alwaysAcceptBaseBranch", true); - capabilities.setCapability("sauce:visual", visualOptions); - - URL url = new URL("https://hub.screener.io/wd/hub"); - driver = new RemoteWebDriver(url, capabilities); - - driver.get("https://www.saucedemo.com"); - - // Capture a snapshot of a page on the main branch - driver.executeScript("/*@visual.init*/", "My Visual Test"); - driver.executeScript("/*@visual.snapshot*/", "Branch Compare"); - assertNoVisualDifferences(); - - //Capture a snapshot on a different branch - visualOptions.setCapability("branch", "2ndBranch"); - visualOptions.setCapability("baseBranch", "main"); - capabilities.setCapability("sauce:visual", visualOptions); - url = new URL("https://hub.screener.io/wd/hub"); - driver = new RemoteWebDriver(url, capabilities); - driver.get("https://www.screener.io"); - driver.executeScript("/*@visual.init*/", "My Visual Test"); - driver.executeScript("/*@visual.snapshot*/", "Branch Compare"); - assertHasVisualDifferences(); - - visualOptions.setCapability("branch", "3rdBranch"); - visualOptions.setCapability("baseBranch", "main"); - capabilities.setCapability("sauce:visual", visualOptions); - url = new URL("https://hub.screener.io/wd/hub"); - driver = new RemoteWebDriver(url, capabilities); - driver.get("https://www.saucelabs.com"); - driver.executeScript("/*@visual.init*/", "My Visual Test"); - driver.executeScript("/*@visual.snapshot*/", "Branch Compare"); - assertHasVisualDifferences(); - } - - private void assertNoVisualDifferences() { - Map response = (Map) driver.executeScript("/*@visual.end*/"); - if (response.get("message") != null) { - assertNull(response.get("message")); - } - } - - private void assertHasVisualDifferences() { - Map response = (Map) driver.executeScript("/*@visual.end*/"); - assertEquals(false, response.get("passed")); - } -} diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/WindowsAuthentication.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/WindowsAuthentication.java deleted file mode 100644 index c1d45452..00000000 --- a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/WindowsAuthentication.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.saucedemo.selenium.junit4; - -import com.saucelabs.saucebindings.Prerun; -import com.saucelabs.saucebindings.SaucePlatform; -import com.saucelabs.saucebindings.SauceSession; -import com.saucelabs.saucebindings.options.SauceOptions; -import org.junit.After; -import org.junit.Ignore; -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.RemoteWebDriver; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * Tests for Basic Authentication. - */ -public class WindowsAuthentication { - - private SauceSession session; - private SauceOptions sauceOptions; - - @After - public void tearDown() { - session.stop(true); - } - - @Test - public void basicAuthTest() { - sauceOptions = new SauceOptions(); - sauceOptions.setPlatformName(SaucePlatform.WINDOWS_10); - - session = new SauceSession(sauceOptions); - RemoteWebDriver driver = session.start(); - driver.get("http://admin:admin@the-internet.herokuapp.com/basic_auth"); - WebElement content = driver.findElement(By.id("content")); - - assertTrue(content.isDisplayed()); - } - - @Test - @Ignore("doesn't work") - public void autoItScriptTest() { - //Good AutoIt docs: https://support.saucelabs.com/hc/en-us/articles/360049978374-Sample-AutoIT-Example-to-Handle-Integrated-Windows-Authentication-Dialog-IWA- - sauceOptions = new SauceOptions(); - - Map prerun = new HashMap<>(); - prerun.put(Prerun.EXECUTABLE, "sauce-storage:login.zip"); - prerun.put(Prerun.ARGS, "--silent"); - prerun.put(Prerun.ARGS, "-a"); - prerun.put(Prerun.ARGS, "-q"); - prerun.put(Prerun.BACKGROUND, true); - sauceOptions.sauce().setPrerun(prerun); - - session = new SauceSession(sauceOptions); - RemoteWebDriver driver = session.start(); - driver.get("http://the-internet.herokuapp.com/basic_auth"); - - fail(); - } -} diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/AuthenticationTest.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/AuthenticationTest.java new file mode 100644 index 00000000..33a63e1c --- /dev/null +++ b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/AuthenticationTest.java @@ -0,0 +1,54 @@ +package com.saucedemo.selenium.junit4.demo; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +public class AuthenticationTest extends TestBase { + + @Before + public void setup() { + startChromeSession(); + } + + @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']")); + Assert.assertTrue(errorElement.getText().contains("Sorry, this user has been locked out")); + } + + @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(); + + Assert.assertEquals( + "Login Not Successful", "https://www.saucedemo.com/inventory.html", driver.getCurrentUrl()); + } + + @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(); + + Assert.assertEquals( + "Logout Not Successful", "https://www.saucedemo.com/", driver.getCurrentUrl()); + } +} diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/CartTest.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/CartTest.java new file mode 100644 index 00000000..a9db1510 --- /dev/null +++ b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/CartTest.java @@ -0,0 +1,93 @@ +package com.saucedemo.selenium.junit4.demo; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; + +public class CartTest extends TestBase { + + @Before + public void setup() { + startChromeSession(); + } + + @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.id("item_1_title_link")).click(); + + driver + .findElement(By.cssSelector("button[data-test='add-to-cart-sauce-labs-bolt-t-shirt']")) + .click(); + + Assert.assertEquals( + "Item not correctly added to cart", + "1", + driver.findElement(By.className("shopping_cart_badge")).getText()); + } + + @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(); + + Assert.assertTrue(driver.findElements(By.className("shopping_cart_badge")).isEmpty()); + } + + @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(); + + Assert.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(); + + Assert.assertTrue(driver.findElements(By.className("shopping_cart_badge")).isEmpty()); + } + + @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(); + + Assert.assertTrue(driver.findElements(By.className("shopping_cart_badge")).isEmpty()); + } +} diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/CheckoutTest.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/CheckoutTest.java new file mode 100644 index 00000000..d0271408 --- /dev/null +++ b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/CheckoutTest.java @@ -0,0 +1,76 @@ +package com.saucedemo.selenium.junit4.demo; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; + +public class CheckoutTest extends TestBase { + + @Before + public void setup() { + startChromeSession(); + } + + @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(); + + Assert.assertTrue( + driver + .findElement(By.cssSelector("input[data-test='firstName']")) + .getAttribute("class") + .contains("error")); + } + + @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(); + + Assert.assertEquals( + "Information Submission Unsuccessful", + "https://www.saucedemo.com/checkout-step-two.html", + driver.getCurrentUrl()); + } + + @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(); + + Assert.assertEquals("https://www.saucedemo.com/checkout-complete.html", driver.getCurrentUrl()); + + Assert.assertTrue(driver.findElement(By.className("complete-text")).isDisplayed()); + } +} diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/ChromeExtensionTest.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/ChromeExtensionTest.java deleted file mode 100644 index 9784191f..00000000 --- a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/ChromeExtensionTest.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.saucedemo.selenium.junit4.demo; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; -import org.openqa.selenium.By; -import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.chrome.ChromeOptions; -import org.openqa.selenium.remote.RemoteWebDriver; -import org.openqa.selenium.support.ui.ExpectedConditions; -import org.openqa.selenium.support.ui.WebDriverWait; - -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; -import java.time.Duration; - -/** - * An example on how to run Java + JUnit 4 test in the Sauce Labs Desktop Web cloud Chrome Extensions - * Chrome extensions can automatically be installed by Chrome when you initially start the browser. - */ -public class ChromeExtensionTest { - public RemoteWebDriver driver; - - @Rule - public SauceTestWatcher watcher = new SauceTestWatcher(); - - @Rule - public TestName testName = new TestName(); - - @Before - public void setup() throws MalformedURLException { - MutableCapabilities sauceOptions = new MutableCapabilities(); - sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME")); - sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY")); - sauceOptions.setCapability("name", testName.getMethodName()); - - ChromeOptions browserOptions = new ChromeOptions(); - browserOptions.setCapability("platformName", "Windows 10"); - browserOptions.setCapability("browserVersion", "latest"); - // Add Extension - String chromeExtFile = "src/test/java/com/saucedemo/selenium/junit4/demo/ninja-saucebot.crx"; - File ext = new File(chromeExtFile); - browserOptions.addExtensions(ext); - - browserOptions.setCapability("sauce:options", sauceOptions); - URL url = new URL("https://ondemand.eu-central-1.saucelabs.com/wd/hub"); - driver = new RemoteWebDriver(url, browserOptions); - } - - @Test - public void chromeExtensionAddNinjaSaucebotImg() { - driver.navigate().to("https://www.saucedemo.com"); - - // Verification - Assert.assertTrue(isNinjaSaucebotExist()); - } - - public boolean isNinjaSaucebotExist() { - WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(1)); - - try { - wait.until(ExpectedConditions.visibilityOfElementLocated(By.className("bot_column2"))); - } catch (TimeoutException e){ - return false; - } - return true; - } - - /** - * Custom TestWatcher for Sauce Labs projects. - */ - protected class SauceTestWatcher extends TestWatcher { - @Override - protected void failed(Throwable e, Description description) { - driver.executeScript("sauce:job-result=failed"); - } - - @Override - protected void succeeded(Description description) { - driver.executeScript("sauce:job-result=passed"); - } - - @Override - protected void finished(Description description) { - driver.quit(); - } - } -} diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/NavigationTest.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/NavigationTest.java new file mode 100644 index 00000000..b74095f5 --- /dev/null +++ b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/NavigationTest.java @@ -0,0 +1,75 @@ +package com.saucedemo.selenium.junit4.demo; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; + +public class NavigationTest extends TestBase { + + @Before + public void setup() { + startChromeSession(); + } + + @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(); + + Assert.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(); + + Assert.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(); + + Assert.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(); + + Assert.assertEquals("https://www.saucedemo.com/checkout-step-one.html", driver.getCurrentUrl()); + } +} diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SauceBindingsJunit4Test.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SauceBindingsJunit4Test.java deleted file mode 100644 index 168b62ef..00000000 --- a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SauceBindingsJunit4Test.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.saucedemo.selenium.junit4.demo; - -import com.saucelabs.saucebindings.junit4.SauceBaseTest; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * Example Test for using JUnit 4 Sauce Bindings jar. - */ -public class SauceBindingsJunit4Test extends SauceBaseTest { - @Test - public void correctTitle() { - driver.get("https://www.saucedemo.com"); - assertEquals("Swag Labs", driver.getTitle()); - } -} diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SauceBindingsTest.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SauceBindingsTest.java deleted file mode 100644 index f94acdc8..00000000 --- a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SauceBindingsTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.saucedemo.selenium.junit4.demo; - -import com.saucelabs.saucebindings.SauceSession; -import com.saucelabs.saucebindings.options.SauceOptions; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; -import org.openqa.selenium.remote.RemoteWebDriver; - -import static org.junit.Assert.assertEquals; - -/** - * Tests for using Sauce Bindings without a Test Runner library. - */ -public class SauceBindingsTest { - private SauceSession session; - public RemoteWebDriver driver; - - @Rule - public SauceTestWatcher watcher = new SauceTestWatcher(); - - @Rule - public TestName testName = new TestName(); - - @Before - public void setup() { - SauceOptions sauceOptions = SauceOptions.chrome() - .setName(testName.getMethodName()) - .build(); - session = new SauceSession(sauceOptions); - driver = session.start(); - } - - @Test - public void correctTitle() { - driver.navigate().to("https://www.saucedemo.com"); - assertEquals("Swag Labs", driver.getTitle()); - } - - /** - * Custom TestWatcher for Sauce Labs projects. - */ - protected class SauceTestWatcher extends TestWatcher { - @Override - protected void failed(Throwable e, Description description) { - session.stop(false); - } - - @Override - protected void succeeded(Description description) { - session.stop(true); - } - } -} diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SeleniumTest.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SeleniumTest.java deleted file mode 100644 index 092d3d81..00000000 --- a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/SeleniumTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.saucedemo.selenium.junit4.demo; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestName; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; -import org.openqa.selenium.MutableCapabilities; -import org.openqa.selenium.chrome.ChromeOptions; -import org.openqa.selenium.remote.RemoteWebDriver; - -import java.net.MalformedURLException; -import java.net.URL; - -import static org.junit.Assert.assertEquals; - -/** - * Tests for running Selenium tests directly with JUnit 4. - */ -public class SeleniumTest { - public RemoteWebDriver driver; - - @Rule - public SauceTestWatcher watcher = new SauceTestWatcher(); - - @Rule - public TestName testName = new TestName(); - - @Before - public void setup() throws MalformedURLException { - MutableCapabilities sauceOptions = new MutableCapabilities(); - sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME")); - sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY")); - sauceOptions.setCapability("name", testName.getMethodName()); - sauceOptions.setCapability("browserVersion", "latest"); - - ChromeOptions options = new ChromeOptions(); - options.setCapability("sauce:options", sauceOptions); - URL url = new URL("https://ondemand.us-west-1.saucelabs.com/wd/hub"); - - driver = new RemoteWebDriver(url, options); - } - - - @Test - public void correctTitle() { - driver.navigate().to("https://www.saucedemo.com"); - assertEquals("Swag Labs", driver.getTitle()); - } - - /** - * Custom TestWatcher for Sauce Labs projects. - */ - protected class SauceTestWatcher extends TestWatcher { - @Override - protected void failed(Throwable e, Description description) { - driver.executeScript("sauce:job-result=failed"); - } - - @Override - protected void succeeded(Description description) { - driver.executeScript("sauce:job-result=passed"); - } - - @Override - protected void finished(Description description) { - driver.quit(); - } - } -} diff --git a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/TestBase.java b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/TestBase.java new file mode 100644 index 00000000..b7f750e2 --- /dev/null +++ b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/TestBase.java @@ -0,0 +1,95 @@ +package com.saucedemo.selenium.junit4.demo; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import org.junit.Rule; +import org.junit.rules.TestName; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; +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 { + + public WebDriver driver; + + @Rule public TestName testName = new TestName(); + @Rule public SauceTestWatcher watcher = new SauceTestWatcher(); + + protected SessionId id; + + public void startChromeSession() { + startSession(new ChromeOptions()); + } + + public void startFirefoxSession() { + startSession(new FirefoxOptions()); + } + + public void startSession(Capabilities options) { + startSession(options, new HashMap<>()); + } + + protected void startSession(Capabilities options, Map sauceOptions) { + Objects.requireNonNull(options, "options cannot be null"); + Objects.requireNonNull(sauceOptions, "sauceOptions cannot be null"); + + sauceOptions.put("username", System.getenv("SAUCE_USERNAME")); + sauceOptions.put("accessKey", System.getenv("SAUCE_ACCESS_KEY")); + sauceOptions.put("name", testName.getMethodName()); + sauceOptions.put("screenResolution", "1440x900"); + sauceOptions.put("seleniumVersion", "4.22.0"); + ((MutableCapabilities) options).setCapability("sauce:options", sauceOptions); + ((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(); + } + + public class SauceTestWatcher extends TestWatcher { + @Override + public void succeeded(Description description) { + 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 failed(Throwable failure, Description description) { + printResults(); + + try { + ((JavascriptExecutor) driver).executeScript("sauce:job-result=failed"); + driver.quit(); + } catch (Exception exception) { + System.out.println("problem with using driver: " + exception); + } + } + + public void printResults() { + String sauceReporter = String.format("SauceOnDemandSessionID=%s job-name=%s", id, testName); + 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-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/ninja-saucebot.crx b/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/ninja-saucebot.crx deleted file mode 100644 index 421446d2..00000000 Binary files a/selenium-junit4-examples/src/test/java/com/saucedemo/selenium/junit4/demo/ninja-saucebot.crx and /dev/null differ diff --git a/selenium-testng-examples/pom.xml b/selenium-testng-examples/pom.xml index bf746b0b..ab958e1d 100644 --- a/selenium-testng-examples/pom.xml +++ b/selenium-testng-examples/pom.xml @@ -1,37 +1,41 @@ - - - demo-java - com.saucelabs - 1.0-SNAPSHOT - - 4.0.0 - selenium-testng-examples + 4.0.0 - - - com.saucelabs - saucebindings-testng - ${sauce_testng.version} - test - - + com.saucelabs + selenium-testng-examples + 1.0-SNAPSHOT - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven.surefire.version} - - methods - 10 - false - - - - - \ No newline at end of file + Sauce Labs TestNG Examples + + 1.5.0 + 3.5.1 + + + + + com.saucelabs + saucebindings-testng + ${sauce_testng.version} + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven.surefire.version} + + methods + 10 + false + + + + + diff --git a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/CrossBrowserPlatformTest.java b/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/CrossBrowserPlatformTest.java index feeac32a..baabc13d 100644 --- a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/CrossBrowserPlatformTest.java +++ b/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/CrossBrowserPlatformTest.java @@ -2,54 +2,55 @@ import com.saucelabs.saucebindings.options.SauceOptions; import com.saucelabs.saucebindings.testng.SauceParameterizedBaseTest; +import java.lang.reflect.Method; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.lang.reflect.Method; - /** * Tests whoing how to run cross browser tests with TestNG Sauce Bindings jar when Parameterized. */ public class CrossBrowserPlatformTest extends SauceParameterizedBaseTest { - @DataProvider(name = "sauceBrowsers", parallel = true) - public static Object[][] sauceBrowserDataProvider() { - return new Object[][]{ - // Uncomment the other data providers ONLY if you have the relevant Sauce VM concurrency - new Object[]{"chrome", "latest", "macOS 11.00"}, - new Object[]{"firefox", "latest", "macOS 11.00"}, - new Object[]{"chrome", "latest", "Windows 10"}, - new Object[]{"firefox", "latest", "Windows 10"}, - new Object[]{"chrome", "latest-1", "Windows 10"} - /*new Object[]{"firefox", "latest-1", "Windows 10"}, - new Object[]{"safari", "12.0", "macOS 10.14"}, - new Object[]{"MicrosoftEdge", "latest", "Windows 10"}, - new Object[]{"firefox", "65.0", "Windows 10"}, - new Object[]{"firefox", "64.0", "macOS 10.14"}, - new Object[]{"firefox", "63.0", "macOS 10.13"}, - new Object[]{"firefox", "62.0", "macOS 10.12"}, - new Object[]{"firefox", "61.0", "macOS 10.13"},*/ - }; - } + @DataProvider(name = "sauceBrowsers", parallel = true) + public static Object[][] sauceBrowserDataProvider() { + return new Object[][] { + // Uncomment the other data providers ONLY if you have the relevant Sauce VM concurrency + new Object[] {"chrome", "latest", "macOS 13"}, + new Object[] {"firefox", "latest", "macOS 13"}, + new Object[] {"chrome", "latest", "Windows 10"}, + new Object[] {"firefox", "latest", "Windows 10"}, + new Object[] {"chrome", "latest-1", "Windows 10"} + /* + new Object[]{"firefox", "latest-1", "Windows 10"}, + new Object[]{"safari", "12.0", "macOS 10.14"}, + new Object[]{"MicrosoftEdge", "latest", "Windows 10"}, + new Object[]{"firefox", "65.0", "Windows 10"}, + new Object[]{"firefox", "64.0", "macOS 10.14"}, + new Object[]{"firefox", "63.0", "macOS 10.13"}, + new Object[]{"firefox", "62.0", "macOS 10.12"}, + new Object[]{"firefox", "61.0", "macOS 10.13"}, + */ + }; + } - @Override - protected SauceOptions createSauceOptions(Method method, Object[] parameters) { - SauceOptions sauceOptions = new SauceOptions(); - sauceOptions.setCapability("browserName", parameters[0]); - sauceOptions.setCapability("browserVersion", parameters[1]); - sauceOptions.setCapability("platformName", parameters[2]); - return sauceOptions; - } + @Override + protected SauceOptions createSauceOptions(Method method, Object[] parameters) { + SauceOptions sauceOptions = new SauceOptions(); + sauceOptions.setCapability("browserName", parameters[0]); + sauceOptions.setCapability("browserVersion", parameters[1]); + sauceOptions.setCapability("platformName", parameters[2]); + return sauceOptions; + } - @Test(dataProvider = "sauceBrowsers") - public void testCase1(String browser, String browserVersion, String platformName) { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test(dataProvider = "sauceBrowsers") + public void testCase1(String browser, String browserVersion, String platformName) { + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } - @Test(dataProvider = "sauceBrowsers") - public void testCase2(String browser, String browserVersion, String platformName) { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test(dataProvider = "sauceBrowsers") + public void testCase2(String browser, String browserVersion, String platformName) { + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } } diff --git a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/ParallelSingleBrowserTest.java b/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/ParallelSingleBrowserTest.java index 3b815db4..281d2510 100644 --- a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/ParallelSingleBrowserTest.java +++ b/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/ParallelSingleBrowserTest.java @@ -4,67 +4,66 @@ import org.testng.Assert; import org.testng.annotations.Test; -/** - * Tests for running a single browser in parallel. - */ +/** Tests for running a single browser in parallel. */ public class ParallelSingleBrowserTest extends SauceBaseTest { - @Test - public void testCase1() { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test + public void testCase1() { + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } - @Test - public void testCase2() { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test + public void testCase2() { - @Test - public void testCase3() { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } - @Test - public void testCase4() { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test + public void testCase3() { + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } - @Test - public void testCase5() { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test + public void testCase4() { + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } - @Test - public void testCase6() { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test + public void testCase5() { + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } - @Test - public void testCase7() { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test + public void testCase6() { + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } - @Test - public void testCase8() { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test + public void testCase7() { + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } - @Test - public void testCase9() { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test + public void testCase8() { + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } - @Test - public void testCase10() { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test + public void testCase9() { + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } + + @Test + public void testCase10() { + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } } diff --git a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/SampleHeadlessSauceTest.java b/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/SampleHeadlessSauceTest.java deleted file mode 100644 index dd220877..00000000 --- a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/SampleHeadlessSauceTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.saucedemo.selenium.testng; - -import com.saucelabs.saucebindings.DataCenter; -import com.saucelabs.saucebindings.SauceOptions; -import com.saucelabs.saucebindings.SaucePlatform; -import com.saucelabs.saucebindings.SauceSession; -import org.openqa.selenium.remote.RemoteWebDriver; -import org.testng.Assert; -import org.testng.ITestResult; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.Test; - -/** - * Tests for running Headless on Sauce. - */ -public class SampleHeadlessSauceTest { - private RemoteWebDriver driver; - private SauceSession sauceSession; - - @Test - public void main() { - - SauceOptions sauceOptions = new SauceOptions(); - sauceOptions.setPlatformName(SaucePlatform.LINUX); - sauceOptions.setName("headless-chrome-test-java"); - sauceOptions.setBuild("Sample Headless Test"); - - sauceSession = new SauceSession(sauceOptions); - sauceSession.setDataCenter(DataCenter.US_EAST); - driver = sauceSession.start(); - - driver.get("https://www.saucedemo.com"); - System.out.println("title of page is: " + driver.getTitle()); - Assert.assertEquals("Swag Labs", driver.getTitle()); - } - - /* Sends results to SauceLabs.com */ - @AfterMethod - public void cleanUpAfterTestMethod(ITestResult result) { - driver.executeScript("sauce:job-result=" + (result.isSuccess() ? "passed" : "failed")); - sauceSession.stop(true); - } -} diff --git a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTest.java b/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTest.java index 8a985229..da1c33e3 100644 --- a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTest.java +++ b/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTest.java @@ -11,28 +11,26 @@ import java.lang.reflect.Method; -/** - * Example Tests for running with Sauce Bindings diriectly without test runner jar. - */ +/** Example Tests for running with Sauce Bindings directly without test runner jar. */ public class SauceBindingsTest { - protected SauceSession session; - protected RemoteWebDriver driver; + protected SauceSession session; + protected RemoteWebDriver driver; - @BeforeMethod - public void setup(Method method) { - SauceOptions options = SauceOptions.chrome().setName(method.getName()).build(); - session = new SauceSession(options); - driver = session.start(); - } + @BeforeMethod + public void setup(Method method) { + SauceOptions options = SauceOptions.chrome().setName(method.getName()).build(); + session = new SauceSession(options); + driver = session.start(); + } - @Test - public void correctTitle() { - driver.navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", driver.getTitle()); - } + @Test + public void correctTitle() { + driver.navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", driver.getTitle()); + } - @AfterMethod - public void teardown(ITestResult result) { - session.stop(result.isSuccess()); - } + @AfterMethod + public void teardown(ITestResult result) { + session.stop(result.isSuccess()); + } } diff --git a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTestngTest.java b/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTestngTest.java index 3d3dae6d..3f1812ae 100644 --- a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTestngTest.java +++ b/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SauceBindingsTestngTest.java @@ -4,13 +4,12 @@ import org.testng.Assert; import org.testng.annotations.Test; -/** - * Example Test for running with the TestNG Sauce Bindings library. - */ +/** Example Test for running with the TestNG Sauce Bindings library. */ public class SauceBindingsTestngTest extends SauceBaseTest { - @Test - public void correctTitle() { - getDriver().navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", getDriver().getTitle()); - } + @Test + public void correctTitle() { + + getDriver().navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", getDriver().getTitle()); + } } diff --git a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SeleniumTest.java b/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SeleniumTest.java index 17ddd086..db1ce2e7 100644 --- a/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SeleniumTest.java +++ b/selenium-testng-examples/src/test/java/com/saucedemo/selenium/testng/demo/SeleniumTest.java @@ -13,36 +13,35 @@ import java.net.MalformedURLException; import java.net.URL; -/** - * Example of running a TestNG test without using Sauce Bindings. - */ +/** Example of running a TestNG test without using Sauce Bindings. */ public class SeleniumTest { - protected RemoteWebDriver driver; - - @BeforeMethod - public void setup(Method method) throws MalformedURLException { - MutableCapabilities sauceOptions = new MutableCapabilities(); - sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME")); - sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY")); - sauceOptions.setCapability("name", method.getName()); - sauceOptions.setCapability("browserVersion", "latest"); - - ChromeOptions options = new ChromeOptions(); - options.setCapability("sauce:options", sauceOptions); - URL url = new URL("https://ondemand.us-west-1.saucelabs.com/wd/hub"); - - driver = new RemoteWebDriver(url, options); - } - - @Test - public void correctTitle() { - driver.navigate().to("https://www.saucedemo.com"); - Assert.assertEquals("Swag Labs", driver.getTitle()); - } - - @AfterMethod - public void teardown(ITestResult result) { - String status = result.isSuccess() ? "passed" : "failed"; - driver.executeScript("sauce:job-result=" + status); - } + + protected RemoteWebDriver driver; + + @BeforeMethod + public void setup(Method method) throws MalformedURLException { + MutableCapabilities sauceOptions = new MutableCapabilities(); + sauceOptions.setCapability("username", System.getenv("SAUCE_USERNAME")); + sauceOptions.setCapability("accessKey", System.getenv("SAUCE_ACCESS_KEY")); + sauceOptions.setCapability("name", method.getName()); + sauceOptions.setCapability("browserVersion", "latest"); + + ChromeOptions options = new ChromeOptions(); + options.setCapability("sauce:options", sauceOptions); + URL url = new URL("https://ondemand.us-west-1.saucelabs.com/wd/hub"); + + driver = new RemoteWebDriver(url, options); + } + + @Test + public void correctTitle() { + driver.navigate().to("https://www.saucedemo.com"); + Assert.assertEquals("Swag Labs", driver.getTitle()); + } + + @AfterMethod + public void teardown(ITestResult result) { + String status = result.isSuccess() ? "passed" : "failed"; + driver.executeScript("sauce:job-result=" + status); + } } diff --git a/selenium3-examples/README.md b/selenium3-examples/README.md deleted file mode 100644 index 9bfdf7de..00000000 --- a/selenium3-examples/README.md +++ /dev/null @@ -1,5 +0,0 @@ -## Selenium 3 - -This code 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. Your tests and testing environments may require you to modify this framework. Issues regarding this framework should be submitted through GitHub. For questions regarding Sauce Labs integration, please see the Sauce Labs documentation at https://wiki.saucelabs.com/. This framework is not maintained by Sauce Labs Support. - -This project is just for comparison purposes with Selenium 4 Code \ No newline at end of file diff --git a/selenium3-examples/pom.xml b/selenium3-examples/pom.xml deleted file mode 100644 index 6e12fe75..00000000 --- a/selenium3-examples/pom.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - 4.0.0 - - org.example - selenium3 - 1.0-SNAPSHOT - - - - com.saucelabs - saucebindings-junit5 - 1.0.0 - - - org.seleniumhq.selenium - selenium-java - 3.141.59 - test - - - - - 8 - 8 - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M5 - - - 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 diff --git a/selenium3-examples/src/test/java/com/saucelabs/selenium3/changes/CapabilitiesMergeTest.java b/selenium3-examples/src/test/java/com/saucelabs/selenium3/changes/CapabilitiesMergeTest.java deleted file mode 100644 index d279238d..00000000 --- a/selenium3-examples/src/test/java/com/saucelabs/selenium3/changes/CapabilitiesMergeTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.saucelabs.selenium3.changes; - -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 3 Can merge in place") - @Test - public void mergesInPlace() { - ChromeOptions options1 = new ChromeOptions(); - ChromeOptions options2 = new ChromeOptions(); - - options1.setPageLoadStrategy(PageLoadStrategy.EAGER); - options2.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.IGNORE); - - options1.merge(options2); - - Assertions.assertEquals(UnexpectedAlertBehaviour.IGNORE, options1.getCapability("unhandledPromptBehavior")); - } - - @DisplayName("Selenium 3 Can merge as a new object") - @Test - public void mergesNewObject() { - ChromeOptions options1 = new ChromeOptions(); - ChromeOptions options2 = new ChromeOptions(); - - options1.setPageLoadStrategy(PageLoadStrategy.EAGER); - options2.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.IGNORE); - - options1.merge(options2); - - Assertions.assertEquals(UnexpectedAlertBehaviour.IGNORE, options1.getCapability("unhandledPromptBehavior")); - } -} diff --git a/selenium3-examples/src/test/java/com/saucelabs/selenium3/changes/DurationParameterTest.java b/selenium3-examples/src/test/java/com/saucelabs/selenium3/changes/DurationParameterTest.java deleted file mode 100644 index d168725a..00000000 --- a/selenium3-examples/src/test/java/com/saucelabs/selenium3/changes/DurationParameterTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.saucelabs.selenium3.changes; - -import com.saucelabs.saucebindings.junit5.SauceBaseTest; -import org.junit.jupiter.api.Test; -import org.openqa.selenium.support.ui.WebDriverWait; - -import java.util.concurrent.TimeUnit; -public class DurationParameterTest extends SauceBaseTest { - - @Test - public void timeoutUnit() { - // Uses Seconds - WebDriverWait wait = new WebDriverWait(driver,5); - - // Uses Long / TimeUnit - driver.manage().timeouts().implicitlyWait(555, TimeUnit.MILLISECONDS); - } -} diff --git a/selenium3-examples/src/test/java/com/saucelabs/selenium3/changes/FindByTest.java b/selenium3-examples/src/test/java/com/saucelabs/selenium3/changes/FindByTest.java deleted file mode 100644 index 5fc04124..00000000 --- a/selenium3-examples/src/test/java/com/saucelabs/selenium3/changes/FindByTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.saucelabs.selenium3.changes; - -import com.saucelabs.saucebindings.junit5.SauceBaseTest; -import org.junit.jupiter.api.Test; -public class FindByTest extends SauceBaseTest { - - @Test - public void findElementBy() { - driver.navigate().to("https://www.saucedemo.com"); - - driver.findElementById("user-name"); - driver.findElementByCssSelector("#password"); - driver.findElementByClassName("btn_action"); - } -} diff --git a/training-sessions/advanced_demo/.gitignore b/training-sessions/advanced_demo/.gitignore deleted file mode 100644 index df9d762d..00000000 --- a/training-sessions/advanced_demo/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -### Java template -*.class - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.ear - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - -# Created by .ignore support plugin (hsz.mobi) - -target/ -.idea/ diff --git a/training-sessions/advanced_demo/README.md b/training-sessions/advanced_demo/README.md deleted file mode 100644 index bc5bea1b..00000000 --- a/training-sessions/advanced_demo/README.md +++ /dev/null @@ -1,26 +0,0 @@ -## Advanced Introduction to Sauce Labs - -This code 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. Your tests and testing environments may require you to modify this framework. Issues regarding this framework should be submitted through GitHub. For questions regarding Sauce Labs integration, please see the Sauce Labs documentation at https://wiki.saucelabs.com/. This framework is not maintained by Sauce Labs Support. - -### Training Plan - -1. `LocalExecutionTest` shows off running locally - -2. `SauceExecutionTest` shows the basics of running on Sauce Labs - a. This uses the Sauce Bindings example straight from the website - -3. `ExtraSauceTest` shows all of the main Sauce Labs specific values that can be used - -4. `TestWatcherTest` shows sending passing & failing information to Sauce - a. This uses SalsaVerde's `com.saucedemo.SauceTestWatcher` class - -5. `SauceDemoTest` shows running an actual authentication test to look at commands list - a. Note this is using SalsaVerde syntax - -6. `ExtendedDebuggingTest` - Sets Extended debugging values to show in UI - -7. `SauceConnectTest` - kick off a tunnel locally and show the sub-account: - a. Expects these sc flags: `--tunnel-identifier ORANGE --shared-tunnel --no-remove-colliding-tunnels --pidfile /tmp/pid0.log'` - b. Requires overriding Sauce Bindings defaults with different username/access key values - - diff --git a/training-sessions/advanced_demo/pom.xml b/training-sessions/advanced_demo/pom.xml deleted file mode 100644 index de98cde1..00000000 --- a/training-sessions/advanced_demo/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - 4.0.0 - - org.example - advanced_demo - 1.0-SNAPSHOT - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - - - - - - - - io.github.bonigarcia - webdrivermanager - 4.0.0 - test - - - junit - junit - 4.12 - - - com.saucelabs - salsa_verde - 0.1.0 - - - \ No newline at end of file diff --git a/training-sessions/advanced_demo/src/test/java/ExtendedDebuggingTest.java b/training-sessions/advanced_demo/src/test/java/ExtendedDebuggingTest.java deleted file mode 100644 index 5884a0c7..00000000 --- a/training-sessions/advanced_demo/src/test/java/ExtendedDebuggingTest.java +++ /dev/null @@ -1,42 +0,0 @@ -import com.saucelabs.salsaverde.Browser; -import com.saucelabs.salsaverde.junit.SauceTestWatcher; -import com.saucelabs.saucebindings.SauceOptions; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.Description; -import org.openqa.selenium.By; - -public class ExtendedDebuggingTest { - public Browser browser; - - @Rule - public SauceTestWatcher testWatcher = new SauceTestWatcher() { - @Override - protected void starting(Description description) { - SauceOptions sauceOptions = new SauceOptions(); - sauceOptions.setExtendedDebugging(true); - sauceOptions.setCapturePerformance(true); - - this.setSauceOptions(sauceOptions); - super.starting(description); - } - }; - - @Before - public void setup() { - browser = new Browser(testWatcher.getDriver()); - } - - @Test - public void ExtendedDebuggingDemo() { - browser.goTo("https://www.saucedemo.com/"); - - String email = "standard_user"; - String password = "secret_sauce"; - - browser.element(By.id("user-name")).setText(email); - browser.element(By.id("password")).setText(password); - browser.element(By.className("btn_action")).click(); - } -} diff --git a/training-sessions/advanced_demo/src/test/java/ExtraSauceTest.java b/training-sessions/advanced_demo/src/test/java/ExtraSauceTest.java deleted file mode 100644 index cf6d436a..00000000 --- a/training-sessions/advanced_demo/src/test/java/ExtraSauceTest.java +++ /dev/null @@ -1,56 +0,0 @@ -import com.saucelabs.saucebindings.Browser; -import com.saucelabs.saucebindings.SauceOptions; -import com.saucelabs.saucebindings.SaucePlatform; -import com.saucelabs.saucebindings.SauceSession; -import org.junit.Test; -import org.openqa.selenium.remote.RemoteWebDriver; - -import java.util.ArrayList; - -public class ExtraSauceTest { - - @Test - public void extraSauce() { - // https://wiki.saucelabs.com/display/DOCS/Test+Configuration+Options - SauceOptions sauceOptions = new SauceOptions(); - - // Primary Options - sauceOptions.setBrowserName(Browser.FIREFOX); - sauceOptions.setBrowserVersion("73.0"); - sauceOptions.setPlatformName(SaucePlatform.WINDOWS_8); - - // Test Details - ArrayList tags = new ArrayList<>(); - tags.add("Tag 1"); - tags.add("Tag 2"); - - sauceOptions.setName("Placeholder Test Name (always set this dynamically)"); - sauceOptions.setBuild("Placeholder Build Name + Number (always set this dynamically)"); - sauceOptions.setTags(tags); - - // System Preferences - sauceOptions.setScreenResolution("1280x1024"); - sauceOptions.setTimeZone("Alaska"); - - // Special Features - sauceOptions.setExtendedDebugging(true); - sauceOptions.setCapturePerformance(true); - - // Artifact Toggles - sauceOptions.setRecordVideo(false); - sauceOptions.setVideoUploadOnPass(false); - sauceOptions.setRecordScreenshots(false); - sauceOptions.setRecordLogs(false); - - // Timeout Values - sauceOptions.setMaxDuration(1800); - sauceOptions.setCommandTimeout(300); - sauceOptions.setIdleTimeout(90); - - - SauceSession session = new SauceSession(sauceOptions); - RemoteWebDriver driver = session.start(); - driver.get("https://www.saucedemo.com/"); - session.stop(true); - } -} diff --git a/training-sessions/advanced_demo/src/test/java/LocalExecutionTest.java b/training-sessions/advanced_demo/src/test/java/LocalExecutionTest.java deleted file mode 100644 index a2ce9bd6..00000000 --- a/training-sessions/advanced_demo/src/test/java/LocalExecutionTest.java +++ /dev/null @@ -1,25 +0,0 @@ -import io.github.bonigarcia.wdm.WebDriverManager; -import org.junit.Test; -import org.openqa.selenium.chrome.ChromeDriver; - -public class LocalExecutionTest { - - @Test - public void localExecution() { - // Options: - // - // 1. Specify location of driver - // System.setProperty("webdriver.chrome.driver", "lib/drivers/chromedriver"); - // - // 2. Add driver to PATH ENV - // - // 3. Use Driver manager - WebDriverManager.chromedriver().setup(); - - // Start session (opens browser) - RemoteWebDriver driver = new ChromeDriver(); - - // Quit session (closes browser) - driver.quit(); - } -} diff --git a/training-sessions/advanced_demo/src/test/java/SauceConnectTest.java b/training-sessions/advanced_demo/src/test/java/SauceConnectTest.java deleted file mode 100644 index ef5a8999..00000000 --- a/training-sessions/advanced_demo/src/test/java/SauceConnectTest.java +++ /dev/null @@ -1,45 +0,0 @@ -import com.saucelabs.salsaverde.Browser; -import com.saucelabs.salsaverde.junit.SauceTestWatcher; -import com.saucelabs.saucebindings.SauceOptions; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.Description; -import org.openqa.selenium.By; - -public class SauceConnectTest { - public Browser browser; - - @Rule - public SauceTestWatcher testWatcher = new SauceTestWatcher() { - @Override - protected void starting(Description description) { - System.setProperty("SAUCE_USERNAME", System.getenv("SAUCE_USER_DEMO")); - System.setProperty("SAUCE_ACCESS_KEY", System.getenv("SAUCE_KEY_DEMO")); - - SauceOptions sauceOptions = new SauceOptions(); - sauceOptions.setTunnelIdentifier("ORANGE"); - sauceOptions.setParentTunnel("titusfortner"); - - this.setSauceOptions(sauceOptions); - super.starting(description); - } - }; - - @Before - public void setup() { - browser = new Browser(testWatcher.getDriver()); - } - - @Test - public void SauceConnectDemo() { - browser.goTo("https://www.saucedemo.com/"); - - String email = "standard_user"; - String password = "secret_sauce"; - - browser.element(By.id("user-name")).setText(email); - browser.element(By.id("password")).setText(password); - browser.element(By.className("btn_action")).click(); - } -} diff --git a/training-sessions/advanced_demo/src/test/java/SauceDemoTest.java b/training-sessions/advanced_demo/src/test/java/SauceDemoTest.java deleted file mode 100644 index f86847e3..00000000 --- a/training-sessions/advanced_demo/src/test/java/SauceDemoTest.java +++ /dev/null @@ -1,30 +0,0 @@ -import com.saucelabs.salsaverde.Browser; -import com.saucelabs.salsaverde.junit.SauceTestWatcher; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.openqa.selenium.By; - -public class SauceDemoTest { - public Browser browser; - - @Rule - public SauceTestWatcher testWatcher = new SauceTestWatcher(); - - @Before - public void setup() { - browser = new Browser(testWatcher.getDriver()); - } - - @Test - public void SauceDemo() { - browser.goTo("https://www.saucedemo.com/"); - - String email = "standard_user"; - String password = "secret_sauce"; - - browser.element(By.id("user-name")).setText(email); - browser.element(By.id("password")).setText(password); - browser.element(By.className("btn_action")).click(); - } -} diff --git a/training-sessions/advanced_demo/src/test/java/SauceExecutionTest.java b/training-sessions/advanced_demo/src/test/java/SauceExecutionTest.java deleted file mode 100644 index 974ba3be..00000000 --- a/training-sessions/advanced_demo/src/test/java/SauceExecutionTest.java +++ /dev/null @@ -1,31 +0,0 @@ -import com.saucelabs.saucebindings.Browser; -import com.saucelabs.saucebindings.SauceOptions; -import com.saucelabs.saucebindings.SaucePlatform; -import com.saucelabs.saucebindings.SauceSession; -import org.junit.Test; -import org.openqa.selenium.remote.RemoteWebDriver; - -import java.net.MalformedURLException; - -public class SauceExecutionTest { - @Test - public void sauceExecution() throws MalformedURLException { - // 1. Specify the 3 basic parameters of a SauceOptions instance - SauceOptions sauceOptions = new SauceOptions(); - sauceOptions.setBrowserName(Browser.FIREFOX); - sauceOptions.setBrowserVersion("73.0"); - sauceOptions.setPlatformName(SaucePlatform.WINDOWS_8); - - // 2. Create Session object with the Options object instance - SauceSession session = new SauceSession(sauceOptions); - - // 3. Start Session to get the Driver - RemoteWebDriver driver = session.start(); - - // 4. Use the driver in your tests just like normal - driver.get("https://www.saucedemo.com/"); - - // 5. Stop the Session with whether the test passed or failed - session.stop(true); - } -} diff --git a/training-sessions/advanced_demo/src/test/java/TestWatcherTest.java b/training-sessions/advanced_demo/src/test/java/TestWatcherTest.java deleted file mode 100644 index 480997ad..00000000 --- a/training-sessions/advanced_demo/src/test/java/TestWatcherTest.java +++ /dev/null @@ -1,27 +0,0 @@ -import com.saucelabs.salsaverde.Browser; -import com.saucelabs.salsaverde.junit.SauceTestWatcher; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -public class TestWatcherTest { - public Browser browser; - - @Rule - public SauceTestWatcher testWatcher = new SauceTestWatcher(); - - @Before - public void setup() { - browser = new Browser(testWatcher.getDriver()); - } - - @Test - public void testFail() { - throw new RuntimeException("Throws Exception"); - } - - @Test - public void testPass() { - System.out.println("This should pass"); - } -} diff --git a/training-sessions/synchronization/.gitignore b/training-sessions/synchronization/.gitignore deleted file mode 100644 index df9d762d..00000000 --- a/training-sessions/synchronization/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -### Java template -*.class - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.ear - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - -# Created by .ignore support plugin (hsz.mobi) - -target/ -.idea/ diff --git a/training-sessions/synchronization/README.md b/training-sessions/synchronization/README.md deleted file mode 100644 index 5f4f5793..00000000 --- a/training-sessions/synchronization/README.md +++ /dev/null @@ -1,41 +0,0 @@ -## Synchronization Examples - -This code 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. Your tests and testing environments may require you to modify this framework. Issues regarding this framework should be submitted through GitHub. For questions regarding Sauce Labs integration, please see the Sauce Labs documentation at https://wiki.saucelabs.com/. This framework is not maintained by Sauce Labs Support. - -### Training Plan - -Start by showing http://watir.com/examples/wait.html - -1. NoSynchTest will not pass because it needs to be synchronized - -2. SynchExplicitTest shows the industry standard recommendation to get a test to pass - a. It works - b. The same code duplicated everywhere - c. It never makes sense to take an action on an element that isn't displayed - -3. SynchAbstractTest moves the synchronization code to a centralized place - a. Same number of wire calls - b. Less code duplication - -4. DeclarativeTest shows a well abstracted "real world" tests for logging in - a. Use it to show the basic extra wire calls that synchronized code means - b. (Note: this is the minimal extra, would be more powerful if more extra synch was added) - -5. SynchSalsaVerde shows an example of SalsaVerde usage that properly leverages the -"Forgiveness over Permission" Approach - -6. Show `User.bad()` results and the resulting failure and exception - -7. Show how `loginSuccessfully()` gives a good exception message because it is opinionated - -### Examples of Extra Synchronization: - -* Is the Current Window Open -* Is there an alert -* Set the driver to the default browsing context -* Verify Collection tag names match expected -* Ensure element exists -* Ensure element visible -* Ensure element enabled -* Ensure element is not read only -* Ensure element is not stale diff --git a/training-sessions/synchronization/pom.xml b/training-sessions/synchronization/pom.xml deleted file mode 100644 index 6bd623e0..00000000 --- a/training-sessions/synchronization/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - 4.0.0 - - org.example - synchronization_examples - 1.0-SNAPSHOT - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - - - - - - - - com.saucelabs - salsa_verde - 0.1.0 - - - junit - junit - 4.12 - - - - \ No newline at end of file diff --git a/training-sessions/synchronization/src/test/java/DeclarativeTest.java b/training-sessions/synchronization/src/test/java/DeclarativeTest.java deleted file mode 100644 index 9da9a954..00000000 --- a/training-sessions/synchronization/src/test/java/DeclarativeTest.java +++ /dev/null @@ -1,61 +0,0 @@ -import com.saucelabs.salsaverde.Browser; -import com.saucelabs.salsaverde.elements.Executor; -import com.saucelabs.salsaverde.junit.BaseTestWatcher; -import com.saucelabs.salsaverde.junit.SauceTestWatcher; -import com.saucelabs.salsaverde.pages.PageObject; -import data.UserData; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.openqa.selenium.remote.RemoteWebDriver; -import pages.LoginPage; - - -public class DeclarativeTest { - public Browser browser; - - @Rule - public BaseTestWatcher testWatcher = new SauceTestWatcher(); - - @Before - public void setup() { - browser = new Browser((RemoteWebDriver) testWatcher.getDriver()); - - // Explicitly sets browser rather than hiding it; it's just one line - PageObject.setBrowser(browser); - Executor.waitTime = 5; - } - - @Test - public void loginSuccessfully() { - // Use contextually informative static methods to create Data Objects - UserData userData = UserData.valid(); - - // Don't put the magic in the constructor, have a method that does what you expect it to - LoginPage loginPage = new LoginPage(); - loginPage.visit(); - - // Declarative - what it means to log in is elsewhere; - // Not data providers or ordered params, the object - loginPage.loginSuccessfully(userData); - - Assert.assertFalse(loginPage.isOnPage()); - } - - @Test - public void loginFailure() { - // Use contextually informative static methods to create Data Objects - UserData userData = UserData.valid(); - - // Don't put the magic in the constructor, have a method that does what you expect it to - LoginPage loginPage = new LoginPage(); - loginPage.visit(); - - // Declarative - what it means to log in is elsewhere; - // No data providers or ordered params, just an object - loginPage.loginSuccessfully(userData); - - Assert.assertFalse(loginPage.isOnPage()); - } -} diff --git a/training-sessions/synchronization/src/test/java/NoSynchTest.java b/training-sessions/synchronization/src/test/java/NoSynchTest.java deleted file mode 100644 index 1619dc91..00000000 --- a/training-sessions/synchronization/src/test/java/NoSynchTest.java +++ /dev/null @@ -1,42 +0,0 @@ -import com.saucelabs.saucebindings.SauceOptions; -import com.saucelabs.saucebindings.SauceSession; -import org.junit.Assert; -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.NoSuchElementException; -import org.openqa.selenium.remote.RemoteWebDriver; - - -public class NoSynchTest { - public SauceSession session; - public RemoteWebDriver driver; - - @Rule - public TestName name = new TestName(); - - @Before - public void setup() { - SauceOptions options = new SauceOptions(); - options.setName(name.getMethodName()); - session = new SauceSession(options); - driver = session.start(); - } - - @Test - public void failsToSynch() { - driver.get("http://watir.com/examples/wait.html"); - - driver.findElement(By.id("add_foobar")).click(); - - try { - driver.findElement(By.id("foobar")).click(); - session.stop(true); - } catch (NoSuchElementException e) { - session.stop(false); - Assert.assertTrue(e.getMessage(), false); - } - } -} diff --git a/training-sessions/synchronization/src/test/java/SynchAbstractTest.java b/training-sessions/synchronization/src/test/java/SynchAbstractTest.java deleted file mode 100644 index 22f8fcb1..00000000 --- a/training-sessions/synchronization/src/test/java/SynchAbstractTest.java +++ /dev/null @@ -1,73 +0,0 @@ -import com.saucelabs.saucebindings.SauceOptions; -import com.saucelabs.saucebindings.SauceSession; -import org.junit.Assert; -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.ElementNotInteractableException; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.RemoteWebDriver; -import org.openqa.selenium.support.ui.ExpectedConditions; -import org.openqa.selenium.support.ui.WebDriverWait; - - -public class SynchAbstractTest { - public SauceSession session; - public RemoteWebDriver driver; - - @Rule - public TestName name = new TestName(); - - @Before - public void setup() { - SauceOptions options = new SauceOptions(); - options.setName(name.getMethodName()); - session = new SauceSession(options); - driver = session.start(); - } - - public void click(By locator) { - WebDriverWait wait = new WebDriverWait(driver, 30); - - wait.until(ExpectedConditions.visibilityOfElementLocated(locator)).click(); - } - - public void sendKeys(By locator, String text) { - WebDriverWait wait = new WebDriverWait(driver, 30); - - WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator)); - element.clear(); - element.sendKeys(text); - } - - @Test - public void synchronizeAbstract() { - driver.get("http://watir.com/examples/wait.html"); - - click(By.id("add_foobar")); - - try { - click(By.id("foobar")); - session.stop(true); - } catch (ElementNotInteractableException e) { - session.stop(false); - Assert.assertTrue(e.getMessage(), false); - } - } - - @Test - public void fillFormAbstract() { - driver.get("http://watir.com/examples/simple_form.html"); - - sendKeys(By.id("new_user_first_name"), "First"); - sendKeys(By.id("new_user_last_name"), "Last"); - sendKeys(By.id("new_user_email"), "user@example.com"); - click(By.id("submitButton")); - - boolean result = !("http://watir.com/examples/simple_form.html").equals(driver.getCurrentUrl()); - - session.stop(result); - } -} diff --git a/training-sessions/synchronization/src/test/java/SynchExplicitTest.java b/training-sessions/synchronization/src/test/java/SynchExplicitTest.java deleted file mode 100644 index 1c6dccad..00000000 --- a/training-sessions/synchronization/src/test/java/SynchExplicitTest.java +++ /dev/null @@ -1,49 +0,0 @@ -import com.saucelabs.saucebindings.SauceOptions; -import com.saucelabs.saucebindings.SauceSession; -import org.junit.Assert; -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.ElementNotInteractableException; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.remote.RemoteWebDriver; -import org.openqa.selenium.support.ui.ExpectedConditions; -import org.openqa.selenium.support.ui.WebDriverWait; - - -public class SynchExplicitTest { - private SauceSession session; - private RemoteWebDriver driver; - - @Rule - public TestName name = new TestName(); - - @Before - public void setup() { - SauceOptions options = new SauceOptions(); - options.setName(name.getMethodName()); - session = new SauceSession(options); - driver = session.start(); - } - - @Test - public void synchronizeExplicit() { - driver.get("http://watir.com/examples/wait.html"); - WebDriverWait wait = new WebDriverWait(driver, 30); - - wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("add_foobar"))); - driver.findElement(By.id("add_foobar")).click(); - - WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("foobar"))); - - try { - element.click(); - session.stop(true); - } catch (ElementNotInteractableException e) { - session.stop(false); - Assert.assertTrue(e.getMessage(), false); - } - } -} diff --git a/training-sessions/synchronization/src/test/java/SynchSalsaVerdeTest.java b/training-sessions/synchronization/src/test/java/SynchSalsaVerdeTest.java deleted file mode 100644 index 111d1a3f..00000000 --- a/training-sessions/synchronization/src/test/java/SynchSalsaVerdeTest.java +++ /dev/null @@ -1,64 +0,0 @@ -import com.saucelabs.salsaverde.Browser; -import com.saucelabs.salsaverde.elements.Element; -import com.saucelabs.salsaverde.exceptions.ElementNotEnabledException; -import com.saucelabs.saucebindings.SauceOptions; -import com.saucelabs.saucebindings.SauceSession; -import org.junit.Assert; -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.ElementNotInteractableException; -import org.openqa.selenium.NoSuchElementException; -import org.openqa.selenium.StaleElementReferenceException; -import org.openqa.selenium.remote.RemoteWebDriver; -import org.openqa.selenium.support.ui.ExpectedConditions; -import org.openqa.selenium.support.ui.WebDriverWait; - - -public class SynchSalsaVerdeTest { - public SauceSession session; - public Browser browser; - - @Rule - public TestName name = new TestName(); - - @Before - public void setup() { - SauceOptions options = new SauceOptions(); - options.setName(name.getMethodName()); - session = new SauceSession(options); - RemoteWebDriver driver = session.start(); - browser = new Browser(driver); - } - - @Test - public void synchronizeSalsaVerde() { - browser.goTo("http://watir.com/examples/wait.html"); - - browser.element(By.id("add_foobar")).click(); - - try { - browser.element(By.id("foobar")).click(); - session.stop(true); - } catch (ElementNotInteractableException e) { - session.stop(false); - Assert.assertTrue(e.getMessage(), false); - } - } - - @Test - public void fillFormSalsaVerde() { - browser.goTo("http://watir.com/examples/simple_form.html"); - - browser.element(By.id("new_user_first_name")).setText("First"); - browser.element(By.id("new_user_last_name")).setText("Last"); - browser.element(By.id("new_user_email")).setText("user@example.com"); - browser.element(By.id("submitButton")).click(); - - boolean result = !("http://watir.com/examples/simple_form.html").equals(browser.getCurrentUrl()); - - session.stop(result); - } -} diff --git a/training-sessions/synchronization/src/test/java/data/UserData.java b/training-sessions/synchronization/src/test/java/data/UserData.java deleted file mode 100644 index f49aa78f..00000000 --- a/training-sessions/synchronization/src/test/java/data/UserData.java +++ /dev/null @@ -1,25 +0,0 @@ -package data; - -import com.saucelabs.salsaverde.data.DataObject; -import lombok.Getter; -import lombok.Setter; - -@Getter @Setter -public class UserData extends DataObject { - private String username = faker.name().username(); - private String password = faker.internet().password(); - - public static UserData valid() { - UserData userData = new UserData(); - userData.username = "standard_user"; - userData.password = "secret_sauce"; - return userData; - } - - public static UserData bad() { - UserData userData = new UserData(); - userData.username = "bad_user"; - userData.password = "wrong_password"; - return userData; - } -} diff --git a/training-sessions/synchronization/src/test/java/pages/LoginPage.java b/training-sessions/synchronization/src/test/java/pages/LoginPage.java deleted file mode 100644 index 09a8ef6d..00000000 --- a/training-sessions/synchronization/src/test/java/pages/LoginPage.java +++ /dev/null @@ -1,51 +0,0 @@ -package pages; - -import com.saucelabs.salsaverde.elements.Element; -import com.saucelabs.salsaverde.pages.OnPage; -import com.saucelabs.salsaverde.pages.PageObject; -import data.UserData; -import lombok.SneakyThrows; -import org.openqa.selenium.By; -import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.support.ui.WebDriverWait; - -@OnPage(url="https://www.saucedemo.com/", title="Swag Labs", elements={"usernameField", "passwordField"}) -public class LoginPage extends PageObject { - private final Element usernameField = browser.element(By.id("user-name")); - private final Element passwordField = browser.element(By.id("password")); - private final Element submitButton = browser.element(By.className("btn_action")); - private final Element error = browser.element(By.cssSelector("[data-test=error]")); - - // Opinionated methods allow for synchronization where it matters - @SneakyThrows - public void loginSuccessfully(UserData userData) { - login(userData); - - try { - synchWait().until((page) -> !isOnPage()); - } catch (TimeoutException e) { - throw new TimeoutException("login was unsuccessful; found error message: " + error.getText()); - } - } - - @SneakyThrows - public void loginFailure(UserData userData) { - login(userData); - - try { - synchWait().until((page) -> error.doesExist()); - } catch (TimeoutException e) { - throw new TimeoutException("expected unsuccessful login to show errors, but none were found"); - } - } - - public void login(UserData user) { - usernameField.setText(user.getUsername()); - passwordField.setText(user.getPassword()); - submitButton.click(); - } - - public WebDriverWait synchWait() { - return new WebDriverWait(browser.getDriver(), 30); - } -}