├── .doc └── selenium-docker-aws-jenkins.png ├── .gitignore ├── 01-docker ├── 01-date-finder │ └── Dockerfile ├── 02-square-finder │ ├── Dockerfile │ └── Test.java └── 03-pass-env-variable │ ├── Dockerfile │ └── Test.java ├── 02-docker-compose ├── 01-square-finder │ └── docker-compose.yaml ├── 02-nginx │ └── docker-compose.yaml ├── 03-alpine-nginx-ping │ └── docker-compose.yaml ├── 04-volume-mapping │ └── docker-compose.yaml ├── 05-override-env-variable │ └── docker-compose.yaml ├── 06-env-file │ ├── .env │ └── docker-compose.yaml ├── 07-multiple-env-files │ ├── dev.env │ ├── docker-compose.yaml │ └── qa.env ├── 08-multiple-compose-files │ ├── alpine.yaml │ └── nginx.yaml └── template.yaml ├── 03-automation-framework ├── dependencies.md └── selenium-docker │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── vinsguru │ │ │ └── pages │ │ │ ├── AbstractPage.java │ │ │ ├── flightreservation │ │ │ ├── FlightConfirmationPage.java │ │ │ ├── FlightsSearchPage.java │ │ │ ├── FlightsSelectionPage.java │ │ │ ├── RegistrationConfirmationPage.java │ │ │ └── RegistrationPage.java │ │ │ └── vendorportal │ │ │ ├── DashboardPage.java │ │ │ └── LoginPage.java │ └── resources │ │ └── logback.xml │ └── test │ ├── java │ └── com │ │ └── vinsguru │ │ ├── tests │ │ ├── AbstractTest.java │ │ ├── flightreservation │ │ │ ├── FlightReservationTest.java │ │ │ └── model │ │ │ │ └── FlightReservationTestData.java │ │ └── vendorportal │ │ │ ├── VendorPortalTest.java │ │ │ └── model │ │ │ └── VendorPortalTestData.java │ │ └── util │ │ ├── JsonUtil.java │ │ └── ResourceLoader.java │ └── resources │ ├── test-data │ ├── flight-reservation │ │ ├── passenger-1.json │ │ ├── passenger-2.json │ │ ├── passenger-3.json │ │ └── passenger-4.json │ └── vendor-portal │ │ ├── john.json │ │ ├── mike.json │ │ └── sam.json │ └── test-suites │ ├── flight-reservation.xml │ └── vendor-portal.xml ├── 04-selenium-grid ├── 01-simple-grid │ └── docker-compose.yaml ├── 02-scale-container │ └── docker-compose.yaml ├── 03-max-session │ └── docker-compose.yaml ├── 04-vnc-no-password │ └── docker-compose.yaml ├── docker-images.md └── selenium-docker │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── vinsguru │ │ │ └── pages │ │ │ ├── AbstractPage.java │ │ │ ├── flightreservation │ │ │ ├── FlightConfirmationPage.java │ │ │ ├── FlightsSearchPage.java │ │ │ ├── FlightsSelectionPage.java │ │ │ ├── RegistrationConfirmationPage.java │ │ │ └── RegistrationPage.java │ │ │ └── vendorportal │ │ │ ├── DashboardPage.java │ │ │ └── LoginPage.java │ └── resources │ │ └── logback.xml │ └── test │ ├── java │ └── com │ │ └── vinsguru │ │ ├── listener │ │ └── TestListener.java │ │ ├── tests │ │ ├── AbstractTest.java │ │ ├── flightreservation │ │ │ ├── FlightReservationTest.java │ │ │ └── model │ │ │ │ └── FlightReservationTestData.java │ │ └── vendorportal │ │ │ ├── VendorPortalTest.java │ │ │ └── model │ │ │ └── VendorPortalTestData.java │ │ └── util │ │ ├── Config.java │ │ ├── Constants.java │ │ ├── JsonUtil.java │ │ └── ResourceLoader.java │ └── resources │ ├── config │ └── default.properties │ ├── test-data │ ├── flight-reservation │ │ ├── passenger-1.json │ │ ├── passenger-2.json │ │ ├── passenger-3.json │ │ └── passenger-4.json │ └── vendor-portal │ │ ├── john.json │ │ ├── mike.json │ │ └── sam.json │ └── test-suites │ ├── flight-reservation.xml │ └── vendor-portal.xml ├── 05-dockerize ├── 01-running-tests │ └── Readme.md ├── 02-grid-and-test-suites │ └── docker-compose.yaml ├── 03-providing-test-data │ ├── docker-compose.yaml │ └── test-data │ │ └── mike.json ├── 04-scale-browser │ ├── docker-compose.yaml │ ├── grid.yaml │ └── run.sh ├── debugging-steps.md └── selenium-docker │ ├── .gitignore │ ├── Dockerfile │ ├── pom.xml │ ├── runner.sh │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── vinsguru │ │ │ └── pages │ │ │ ├── AbstractPage.java │ │ │ ├── flightreservation │ │ │ ├── FlightConfirmationPage.java │ │ │ ├── FlightsSearchPage.java │ │ │ ├── FlightsSelectionPage.java │ │ │ ├── RegistrationConfirmationPage.java │ │ │ └── RegistrationPage.java │ │ │ └── vendorportal │ │ │ ├── DashboardPage.java │ │ │ └── LoginPage.java │ └── resources │ │ └── logback.xml │ └── test │ ├── java │ └── com │ │ └── vinsguru │ │ ├── listener │ │ └── TestListener.java │ │ ├── tests │ │ ├── AbstractTest.java │ │ ├── flightreservation │ │ │ ├── FlightReservationTest.java │ │ │ └── model │ │ │ │ └── FlightReservationTestData.java │ │ └── vendorportal │ │ │ ├── VendorPortalTest.java │ │ │ └── model │ │ │ └── VendorPortalTestData.java │ │ └── util │ │ ├── Config.java │ │ ├── Constants.java │ │ ├── JsonUtil.java │ │ └── ResourceLoader.java │ └── resources │ ├── config │ └── default.properties │ ├── test-data │ ├── flight-reservation │ │ ├── passenger-1.json │ │ ├── passenger-2.json │ │ ├── passenger-3.json │ │ └── passenger-4.json │ └── vendor-portal │ │ ├── john.json │ │ ├── mike.json │ │ └── sam.json │ └── test-suites │ ├── flight-reservation.xml │ └── vendor-portal.xml ├── 06-jenkins-ci-cd ├── 01-jenkins │ └── docker-compose.yaml ├── 02-simple-pipeline │ └── Jenkinsfile ├── 03-agent-label │ └── Jenkinsfile ├── 04-env-variable │ └── Jenkinsfile ├── 05-run-container │ └── Jenkinsfile ├── 06-docker-agent │ └── Jenkinsfile ├── 07-image-builder-approach-1 │ └── Jenkinsfile ├── 08-image-builder-approach-2 │ └── Jenkinsfile ├── 09-image-builder-approach-3 │ └── Jenkinsfile ├── 10-runner-approach-1 │ ├── .env │ ├── Jenkinsfile │ ├── grid.yaml │ └── test-suites.yaml ├── 11-runner-approach-2 │ ├── .env │ ├── Jenkinsfile │ ├── grid.yaml │ └── test-suites.yaml ├── 12-sample-ci-cd │ └── Jenkinsfile └── selenium-docker │ ├── .gitignore │ ├── Dockerfile │ ├── Jenkinsfile │ ├── pom.xml │ ├── runner.sh │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── vinsguru │ │ │ └── pages │ │ │ ├── AbstractPage.java │ │ │ ├── flightreservation │ │ │ ├── FlightConfirmationPage.java │ │ │ ├── FlightsSearchPage.java │ │ │ ├── FlightsSelectionPage.java │ │ │ ├── RegistrationConfirmationPage.java │ │ │ └── RegistrationPage.java │ │ │ └── vendorportal │ │ │ ├── DashboardPage.java │ │ │ └── LoginPage.java │ └── resources │ │ └── logback.xml │ └── test │ ├── java │ └── com │ │ └── vinsguru │ │ ├── listener │ │ └── TestListener.java │ │ ├── tests │ │ ├── AbstractTest.java │ │ ├── flightreservation │ │ │ ├── FlightReservationTest.java │ │ │ └── model │ │ │ │ └── FlightReservationTestData.java │ │ └── vendorportal │ │ │ ├── VendorPortalTest.java │ │ │ └── model │ │ │ └── VendorPortalTestData.java │ │ └── util │ │ ├── Config.java │ │ ├── Constants.java │ │ ├── JsonUtil.java │ │ └── ResourceLoader.java │ └── resources │ ├── config │ └── default.properties │ ├── test-data │ ├── flight-reservation │ │ ├── passenger-1.json │ │ ├── passenger-2.json │ │ ├── passenger-3.json │ │ └── passenger-4.json │ └── vendor-portal │ │ ├── john.json │ │ ├── mike.json │ │ └── sam.json │ └── test-suites │ ├── flight-reservation.xml │ └── vendor-portal.xml ├── 07-aws ├── 01-grid-and-test-suites │ └── docker-compose.yaml ├── 02-aws-runner │ ├── .env │ ├── Jenkinsfile │ ├── grid.yaml │ └── test-suites.yaml └── Readme.md ├── 08-final-projects └── selenium-docker │ ├── .gitignore │ ├── Dockerfile │ ├── Jenkinsfile │ ├── pom.xml │ ├── runner.sh │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── vinsguru │ │ │ └── pages │ │ │ ├── AbstractPage.java │ │ │ ├── flightreservation │ │ │ ├── FlightConfirmationPage.java │ │ │ ├── FlightsSearchPage.java │ │ │ ├── FlightsSelectionPage.java │ │ │ ├── RegistrationConfirmationPage.java │ │ │ └── RegistrationPage.java │ │ │ └── vendorportal │ │ │ ├── DashboardPage.java │ │ │ └── LoginPage.java │ └── resources │ │ └── logback.xml │ └── test │ ├── java │ └── com │ │ └── vinsguru │ │ ├── listener │ │ └── TestListener.java │ │ ├── tests │ │ ├── AbstractTest.java │ │ ├── flightreservation │ │ │ ├── FlightReservationTest.java │ │ │ └── model │ │ │ │ └── FlightReservationTestData.java │ │ └── vendorportal │ │ │ ├── VendorPortalTest.java │ │ │ └── model │ │ │ └── VendorPortalTestData.java │ │ └── util │ │ ├── Config.java │ │ ├── Constants.java │ │ ├── JsonUtil.java │ │ └── ResourceLoader.java │ └── resources │ ├── config │ └── default.properties │ ├── test-data │ ├── flight-reservation │ │ ├── passenger-1.json │ │ ├── passenger-2.json │ │ ├── passenger-3.json │ │ └── passenger-4.json │ └── vendor-portal │ │ ├── john.json │ │ ├── mike.json │ │ └── sam.json │ └── test-suites │ ├── flight-reservation.xml │ └── vendor-portal.xml ├── 09-old-projects ├── 01-original-project │ ├── Dockerfile │ ├── Jenkinsfile │ ├── book-flight-module.xml │ ├── healthcheck.sh │ ├── pom.xml │ ├── search-module.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ ├── newtours │ │ │ └── pages │ │ │ │ ├── FindFlightPage.java │ │ │ │ ├── FlightConfirmationPage.java │ │ │ │ ├── FlightDetailsPage.java │ │ │ │ ├── RegistrationConfirmationPage.java │ │ │ │ └── RegistrationPage.java │ │ │ └── searchmodule │ │ │ └── pages │ │ │ └── SearchPage.java │ │ └── test │ │ └── java │ │ └── com │ │ ├── newtours │ │ └── tests │ │ │ └── BookFlightTest.java │ │ ├── searchmodule │ │ └── tests │ │ │ └── SearchTest.java │ │ └── tests │ │ └── BaseTest.java ├── 02-selenium-4.8.2-testng │ ├── .gitignore │ ├── Dockerfile │ ├── Jenkinsfile │ ├── book-flight-module.xml │ ├── dummy.png │ ├── healthcheck.sh │ ├── pom.xml │ ├── search-module.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ ├── newtours │ │ │ └── pages │ │ │ │ ├── FindFlightPage.java │ │ │ │ ├── FlightConfirmationPage.java │ │ │ │ ├── FlightDetailsPage.java │ │ │ │ ├── RegistrationConfirmationPage.java │ │ │ │ └── RegistrationPage.java │ │ │ └── searchmodule │ │ │ └── pages │ │ │ └── SearchPage.java │ │ └── test │ │ └── java │ │ └── com │ │ ├── newtours │ │ └── tests │ │ │ └── BookFlightTest.java │ │ ├── searchmodule │ │ └── tests │ │ │ └── SearchTest.java │ │ └── tests │ │ └── BaseTest.java ├── 03-selenium-4.8.2-bdd-testng │ ├── .gitignore │ ├── Dockerfile │ ├── Jenkinsfile │ ├── book-flight-module.xml │ ├── docker-compose.yaml │ ├── healthcheck.sh │ ├── pom.xml │ ├── search-module.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ ├── newtours │ │ │ └── pages │ │ │ │ ├── FindFlightPage.java │ │ │ │ ├── FlightConfirmationPage.java │ │ │ │ ├── FlightDetailsPage.java │ │ │ │ ├── RegistrationConfirmationPage.java │ │ │ │ └── RegistrationPage.java │ │ │ └── searchmodule │ │ │ └── pages │ │ │ └── SearchPage.java │ │ └── test │ │ ├── java │ │ └── com │ │ │ ├── runner │ │ │ └── TestRunner.java │ │ │ └── test │ │ │ └── stepdefs │ │ │ ├── FlightBookSteps.java │ │ │ ├── SearchSteps.java │ │ │ └── WebDriverManager.java │ │ └── resources │ │ └── features │ │ ├── flight-book.feature │ │ └── search.feature └── docker-compose-files │ ├── 01-selenium-3-grid.yaml │ ├── 02-selenium-4.8-grid.yaml │ └── 03-selenium-4.8-grid-M1-Mac.yaml ├── 10-misc └── question-template.md └── Readme.md /.doc/selenium-docker-aws-jenkins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsguru/selenium-docker/8f1092e518d2ec7999fdd63b058834722645bb52/.doc/selenium-docker-aws-jenkins.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Java template 2 | # Compiled class file 3 | **/*.class 4 | 5 | # Log file 6 | **/*.log 7 | 8 | # BlueJ files 9 | **/*.ctxt 10 | 11 | # Mobile Tools for Java (J2ME) 12 | **/.mtj.tmp/ 13 | 14 | # Package Files # 15 | **/*.jar 16 | **/*.war 17 | **/*.nar 18 | **/*.ear 19 | **/*.zip 20 | **/*.tar.gz 21 | **/*.rar 22 | 23 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 24 | **/hs_err_pid* 25 | 26 | ### Maven template 27 | **/target/ 28 | **/pom.xml.tag 29 | **/pom.xml.releaseBackup 30 | **/pom.xml.versionsBackup 31 | **/pom.xml.next 32 | **/release.properties 33 | **/dependency-reduced-pom.xml 34 | **/buildNumber.properties 35 | **/.mvn/timing.properties 36 | **/.mvn/wrapper/maven-wrapper.jar 37 | 38 | **/*.iml 39 | 40 | **/.idea/ 41 | 42 | 43 | **/HELP.md 44 | **/.mvn/ 45 | **/mvnw 46 | **/mvnw.cmd 47 | **/node_modules/ 48 | 49 | **/volumes/master 50 | **/volumes/node 51 | **/vol 52 | **/output 53 | Makefile 54 | 55 | 56 | 57 | .DS_Store 58 | -------------------------------------------------------------------------------- /01-docker/01-date-finder/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | ENTRYPOINT date -------------------------------------------------------------------------------- /01-docker/02-square-finder/Dockerfile: -------------------------------------------------------------------------------- 1 | # FROM image 2 | # ADD /my/Test.java /a/b/c/Test.java 3 | # RUN apt-get install java 4 | # ENV JAVA_HOME=/some/path 5 | # WORKDIR /a/b/c 6 | # EXPOSE 8050 7 | # ENTRYPOINT sleep 5 8 | 9 | FROM alpine 10 | RUN apk add openjdk8 11 | ENV PATH $PATH:/usr/lib/jvm/java-1.8-openjdk/bin 12 | WORKDIR /usr/share/udemy 13 | ADD Test.java Test.java 14 | ENTRYPOINT javac Test.java && java Test ${NUMBER} -------------------------------------------------------------------------------- /01-docker/02-square-finder/Test.java: -------------------------------------------------------------------------------- 1 | public class Test{ 2 | public static void main(String[] args){ 3 | 4 | System.out.println("Received # is " + args[0]); 5 | int number = Integer.parseInt(args[0]); 6 | 7 | //find squares 8 | for(int i = 1; i <= number; i++){ 9 | System.out.println("Square of " + i + " is => " + (i * i)); 10 | } 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /01-docker/03-pass-env-variable/Dockerfile: -------------------------------------------------------------------------------- 1 | # FROM image 2 | # ADD /my/Test.java /a/b/c/Test.java 3 | # RUN apt-get install java 4 | # ENV JAVA_HOME=/some/path 5 | # WORKDIR /a/b/c 6 | # EXPOSE 8050 7 | # ENTRYPOINT sleep 5 8 | 9 | FROM alpine 10 | RUN apk add openjdk8 11 | ENV PATH $PATH:/usr/lib/jvm/java-1.8-openjdk/bin 12 | WORKDIR /usr/share/udemy 13 | ADD Test.java Test.java 14 | ENTRYPOINT javac Test.java && java Test $NUMBER -------------------------------------------------------------------------------- /01-docker/03-pass-env-variable/Test.java: -------------------------------------------------------------------------------- 1 | public class Test{ 2 | public static void main(String[] args){ 3 | 4 | System.out.println("Received # is " + args[0]); 5 | int number = Integer.parseInt(args[0]); 6 | 7 | //find squares 8 | for(int i = 1; i <= number; i++){ 9 | System.out.println("Square of " + i + " is => " + (i * i)); 10 | } 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /02-docker-compose/01-square-finder/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | squares: 4 | image: vinsdocker/squares 5 | environment: 6 | - NUMBER=5 7 | -------------------------------------------------------------------------------- /02-docker-compose/02-nginx/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | nginx: 4 | image: nginx 5 | ports: 6 | - 80:80 7 | -------------------------------------------------------------------------------- /02-docker-compose/03-alpine-nginx-ping/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | nginx: 4 | image: nginx 5 | alpine: 6 | image: alpine 7 | entrypoint: "ping nginx" 8 | depends_on: 9 | - nginx -------------------------------------------------------------------------------- /02-docker-compose/04-volume-mapping/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # /a/b/c 2 | version: "3" 3 | services: 4 | nginx: 5 | image: nginx 6 | alpine: 7 | image: alpine 8 | entrypoint: "wget http://nginx" 9 | depends_on: 10 | - nginx 11 | working_dir: /a/b/c 12 | volumes: 13 | - ./vol:/a/b/c -------------------------------------------------------------------------------- /02-docker-compose/05-override-env-variable/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | squares: 4 | image: vinsdocker/squares 5 | environment: 6 | #- NUMBER=${NUM} 7 | #- NUMBER=${NUM:-7} 8 | - NUMBER 9 | 10 | 11 | # NUM=3 docker-compose up -------------------------------------------------------------------------------- /02-docker-compose/06-env-file/.env: -------------------------------------------------------------------------------- 1 | VERSION=v3 -------------------------------------------------------------------------------- /02-docker-compose/06-env-file/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # vinsdocker/sel-app:v1 2 | # vinsdocker/sel-app:v2 3 | # vinsdocker/sel-app:v3 4 | # 80 5 | 6 | version: "3" 7 | services: 8 | demo: 9 | image: vinsdocker/sel-app:${VERSION} 10 | ports: 11 | - 80:80 12 | -------------------------------------------------------------------------------- /02-docker-compose/07-multiple-env-files/dev.env: -------------------------------------------------------------------------------- 1 | VERSION=v3 2 | PORT=8050 -------------------------------------------------------------------------------- /02-docker-compose/07-multiple-env-files/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # vinsdocker/sel-app:v1 2 | # vinsdocker/sel-app:v2 3 | # vinsdocker/sel-app:v3 4 | # 80 5 | 6 | version: "3" 7 | services: 8 | demo: 9 | image: vinsdocker/sel-app:${VERSION} 10 | ports: 11 | - ${PORT}:80 12 | 13 | # docker-compose --env-file dev.env up 14 | # docker-compose --env-file qa.env up -------------------------------------------------------------------------------- /02-docker-compose/07-multiple-env-files/qa.env: -------------------------------------------------------------------------------- 1 | VERSION=v2 2 | PORT=8040 -------------------------------------------------------------------------------- /02-docker-compose/08-multiple-compose-files/alpine.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | alpine: 4 | image: alpine 5 | entrypoint: "ping nginx" 6 | 7 | # docker-compose -f alpine.yaml up 8 | # docker-compose -f alpine.yaml down -------------------------------------------------------------------------------- /02-docker-compose/08-multiple-compose-files/nginx.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | nginx: 4 | image: nginx 5 | 6 | # docker-compose -f nginx.yaml up 7 | # docker-compose -f nginx.yaml down -------------------------------------------------------------------------------- /02-docker-compose/template.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | [service-name]: 4 | image: [image-name] 5 | container_name: [some-name] 6 | entrypoint: ["command to invoke"] 7 | depends_on: 8 | - [any-other-service] 9 | working_dir: /a/b/c 10 | environment: 11 | - KEY1=value1 12 | - KEY2=value2 13 | ports: 14 | - 80:80 15 | - 1234:1234 16 | - 8080:3344 17 | volumes: 18 | - ./relative-path/host-path1:/a/b/c 19 | - /abolute-path/host-path234:/c/d/e -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | **/*.class 5 | 6 | # Log file 7 | **/*.log 8 | 9 | # BlueJ files 10 | **/*.ctxt 11 | 12 | # Mobile Tools for Java (J2ME) 13 | **/.mtj.tmp/ 14 | 15 | # Package Files # 16 | **/*.jar 17 | **/*.war 18 | **/*.nar 19 | **/*.ear 20 | **/*.zip 21 | **/*.tar.gz 22 | **/*.rar 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | **/hs_err_pid* 26 | 27 | ### Maven template 28 | **/target/ 29 | **/pom.xml.tag 30 | **/pom.xml.releaseBackup 31 | **/pom.xml.versionsBackup 32 | **/pom.xml.next 33 | **/release.properties 34 | **/dependency-reduced-pom.xml 35 | **/buildNumber.properties 36 | **/.mvn/timing.properties 37 | **/.mvn/wrapper/maven-wrapper.jar 38 | 39 | **/*.iml 40 | 41 | **/.idea/ 42 | 43 | **/HELP.md 44 | **/.mvn/ 45 | **/mvnw 46 | **/mvnw.cmd 47 | **/node_modules/ 48 | 49 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/main/java/com/vinsguru/pages/AbstractPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.support.PageFactory; 5 | import org.openqa.selenium.support.ui.WebDriverWait; 6 | 7 | import java.time.Duration; 8 | 9 | public abstract class AbstractPage { 10 | 11 | protected final WebDriver driver; 12 | protected final WebDriverWait wait; 13 | 14 | public AbstractPage(WebDriver driver){ 15 | this.driver = driver; 16 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 17 | PageFactory.initElements(driver, this); 18 | } 19 | 20 | public abstract boolean isAt(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class FlightConfirmationPage extends AbstractPage { 12 | 13 | private static final Logger log = LoggerFactory.getLogger(FlightConfirmationPage.class); 14 | 15 | @FindBy(css = "#flights-confirmation-section .card-body .row:nth-child(1) .col:nth-child(2)") 16 | private WebElement flightConfirmationElement; 17 | 18 | @FindBy(css = "#flights-confirmation-section .card-body .row:nth-child(3) .col:nth-child(2)") 19 | private WebElement totalPriceElement; 20 | 21 | public FlightConfirmationPage(WebDriver driver) { 22 | super(driver); 23 | } 24 | 25 | @Override 26 | public boolean isAt() { 27 | this.wait.until(ExpectedConditions.visibilityOf(this.flightConfirmationElement)); 28 | return this.flightConfirmationElement.isDisplayed(); 29 | } 30 | 31 | public String getPrice(){ 32 | String confirmation = this.flightConfirmationElement.getText(); 33 | String price = this.totalPriceElement.getText(); 34 | log.info("Flight confirmation# : {}", confirmation); 35 | log.info("Total price : {}", price); 36 | return price; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightsSearchPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.Select; 9 | 10 | public class FlightsSearchPage extends AbstractPage { 11 | 12 | @FindBy(id = "passengers") 13 | private WebElement passengerSelect; 14 | 15 | @FindBy(id = "search-flights") 16 | private WebElement searchFlightsButton; 17 | 18 | public FlightsSearchPage(WebDriver driver) { 19 | super(driver); 20 | } 21 | 22 | @Override 23 | public boolean isAt() { 24 | this.wait.until(ExpectedConditions.visibilityOf(this.passengerSelect)); 25 | return this.passengerSelect.isDisplayed(); 26 | } 27 | 28 | public void selectPassengers(String noOfPassengers){ 29 | Select passengers = new Select(this.passengerSelect); 30 | passengers.selectByValue(noOfPassengers); 31 | } 32 | 33 | public void searchFlights(){ 34 | this.searchFlightsButton.click(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightsSelectionPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | import java.util.List; 10 | import java.util.concurrent.ThreadLocalRandom; 11 | 12 | public class FlightsSelectionPage extends AbstractPage { 13 | 14 | @FindBy(name = "departure-flight") 15 | private List departureFlightsOptions; 16 | 17 | @FindBy(name = "arrival-flight") 18 | private List arrivalFlightsOptions; 19 | 20 | @FindBy(id = "confirm-flights") 21 | private WebElement confirmFlightsButton; 22 | 23 | public FlightsSelectionPage(WebDriver driver) { 24 | super(driver); 25 | } 26 | 27 | @Override 28 | public boolean isAt() { 29 | this.wait.until(ExpectedConditions.visibilityOf(this.confirmFlightsButton)); 30 | return this.confirmFlightsButton.isDisplayed(); 31 | } 32 | 33 | public void selectFlights(){ 34 | int random = ThreadLocalRandom.current().nextInt(0, departureFlightsOptions.size()); 35 | this.departureFlightsOptions.get(random).click(); 36 | this.arrivalFlightsOptions.get(random).click(); 37 | } 38 | 39 | public void confirmFlights(){ 40 | this.confirmFlightsButton.click(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/RegistrationConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | public class RegistrationConfirmationPage extends AbstractPage { 10 | 11 | @FindBy(id = "go-to-flights-search") 12 | private WebElement goToFlightsSearchButton; 13 | 14 | @FindBy(css = "#registration-confirmation-section p b") 15 | private WebElement firstNameElement; 16 | 17 | public RegistrationConfirmationPage(WebDriver driver){ 18 | super(driver); 19 | } 20 | 21 | @Override 22 | public boolean isAt() { 23 | this.wait.until(ExpectedConditions.visibilityOf(this.goToFlightsSearchButton)); 24 | return this.goToFlightsSearchButton.isDisplayed(); 25 | } 26 | 27 | public String getFirstName(){ 28 | return this.firstNameElement.getText(); 29 | } 30 | 31 | public void goToFlightsSearch(){ 32 | this.goToFlightsSearchButton.click(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/main/java/com/vinsguru/pages/vendorportal/LoginPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.vendorportal; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | public class LoginPage extends AbstractPage { 10 | 11 | @FindBy(id = "username") 12 | private WebElement usernameInput; 13 | 14 | @FindBy(id = "password") 15 | private WebElement passwordInput; 16 | 17 | @FindBy(id = "login") 18 | private WebElement loginButton; 19 | 20 | public LoginPage(WebDriver driver) { 21 | super(driver); 22 | } 23 | 24 | @Override 25 | public boolean isAt() { 26 | this.wait.until(ExpectedConditions.visibilityOf(this.loginButton)); 27 | return this.loginButton.isDisplayed(); 28 | } 29 | 30 | public void goTo(String url){ 31 | this.driver.get(url); 32 | } 33 | 34 | public void login(String username, String password){ 35 | this.usernameInput.sendKeys(username); 36 | this.passwordInput.sendKeys(password); 37 | this.loginButton.click(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} %-5level [%15.15t] %cyan(%-30.30logger{30}) : %m%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/java/com/vinsguru/tests/AbstractTest.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.tests; 2 | 3 | import io.github.bonigarcia.wdm.WebDriverManager; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.chrome.ChromeDriver; 6 | import org.testng.annotations.AfterTest; 7 | import org.testng.annotations.BeforeTest; 8 | 9 | public abstract class AbstractTest { 10 | 11 | protected WebDriver driver; 12 | 13 | @BeforeTest 14 | public void setDriver(){ 15 | WebDriverManager.chromedriver().setup(); 16 | this.driver = new ChromeDriver(); 17 | } 18 | 19 | @AfterTest 20 | public void quitDriver(){ 21 | this.driver.quit(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/java/com/vinsguru/tests/flightreservation/model/FlightReservationTestData.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.tests.flightreservation.model; 2 | 3 | public record FlightReservationTestData(String firstName, 4 | String lastName, 5 | String email, 6 | String password, 7 | String street, 8 | String city, 9 | String zip, 10 | String passengersCount, 11 | String expectedPrice) { 12 | } 13 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/java/com/vinsguru/util/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.vinsguru.tests.vendorportal.model.VendorPortalTestData; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.InputStream; 9 | 10 | public class JsonUtil { 11 | 12 | private static final Logger log = LoggerFactory.getLogger(JsonUtil.class); 13 | private static final ObjectMapper mapper = new ObjectMapper(); 14 | 15 | public static T getTestData(String path, Class type){ 16 | try(InputStream stream = ResourceLoader.getResource(path)){ 17 | return mapper.readValue(stream, type); 18 | }catch (Exception e){ 19 | log.error("unable to read test data {}", path, e); 20 | } 21 | return null; 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/java/com/vinsguru/util/ResourceLoader.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.InputStream; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.util.Objects; 10 | 11 | /* 12 | A simple utility to read file. 13 | first we check the classpath. if found, it is used. 14 | if not, then we check the filesystem 15 | */ 16 | public class ResourceLoader { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(ResourceLoader.class); 19 | 20 | public static InputStream getResource(String path) throws Exception { 21 | log.info("reading resource from location: {}", path); 22 | InputStream stream = ResourceLoader.class.getClassLoader().getResourceAsStream(path); 23 | if(Objects.nonNull(stream)){ 24 | return stream; 25 | } 26 | return Files.newInputStream(Path.of(path)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "michael", 3 | "lastName": "jackson", 4 | "email": "mj@pop.com", 5 | "password": "mj", 6 | "street": "123 main street", 7 | "city": "atlanta", 8 | "zip": "30001", 9 | "passengersCount": "1", 10 | "expectedPrice": "$584 USD" 11 | } -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "marshall", 3 | "lastName": "mathers", 4 | "email": "eminem@hiphop.com", 5 | "password": "m&m", 6 | "street": "456 main street", 7 | "city": "detroit", 8 | "zip": "40001", 9 | "passengersCount": "2", 10 | "expectedPrice": "$1169 USD" 11 | } -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "cheb", 3 | "lastName": "khaled", 4 | "email": "khaled@rai.com", 5 | "password": "didi", 6 | "street": "101 non main street", 7 | "city": "las vegas", 8 | "zip": "50001", 9 | "passengersCount": "3", 10 | "expectedPrice": "$1753 USD" 11 | } -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "dr", 3 | "lastName": "dre", 4 | "email": "dr@dre.com", 5 | "password": "dre", 6 | "street": "455 main street", 7 | "city": "detroit", 8 | "zip": "40001", 9 | "passengersCount": "4", 10 | "expectedPrice": "$2338 USD" 11 | } -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/resources/test-data/vendor-portal/john.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "john", 3 | "password": "john", 4 | "monthlyEarning": "$3,453", 5 | "annualEarning": "$34,485", 6 | "profitMargin": "-16%", 7 | "availableInventory": "67", 8 | "searchKeyword": "2024/01/01", 9 | "searchResultsCount": 0 10 | } -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/resources/test-data/vendor-portal/mike.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "mike", 3 | "password": "mike", 4 | "monthlyEarning": "$55,000", 5 | "annualEarning": "$563,300", 6 | "profitMargin": "80%", 7 | "availableInventory": "45", 8 | "searchKeyword": "miami", 9 | "searchResultsCount": 10 10 | } -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/resources/test-data/vendor-portal/sam.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "sam", 3 | "password": "sam", 4 | "monthlyEarning": "$40,000", 5 | "annualEarning": "$215,000", 6 | "profitMargin": "50%", 7 | "availableInventory": "18", 8 | "searchKeyword": "adams", 9 | "searchResultsCount": 8 10 | } -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/resources/test-suites/flight-reservation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /03-automation-framework/selenium-docker/src/test/resources/test-suites/vendor-portal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /04-selenium-grid/01-simple-grid/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | hub: 3 | image: selenium/hub:4.32 4 | ports: 5 | - 4444:4444 6 | # - 4442:4442 7 | # - 4443:4443 8 | chrome: 9 | image: selenium/node-chromium:4.32 10 | shm_size: '2g' 11 | depends_on: 12 | - hub 13 | environment: 14 | - SE_EVENT_BUS_HOST=hub 15 | - SE_EVENT_BUS_PUBLISH_PORT=4442 16 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 17 | firefox: 18 | image: selenium/node-firefox:4.32 19 | shm_size: '2g' 20 | depends_on: 21 | - hub 22 | environment: 23 | - SE_EVENT_BUS_HOST=hub 24 | - SE_EVENT_BUS_PUBLISH_PORT=4442 25 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 -------------------------------------------------------------------------------- /04-selenium-grid/02-scale-container/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # we can also scale by using this option below 2 | # docker-compose up --scale chrome=2 --scale firefox=2 -d 3 | 4 | services: 5 | hub: 6 | image: selenium/hub:4.32 7 | ports: 8 | - 4444:4444 9 | # - 4442:4442 10 | # - 4443:4443 11 | chrome: 12 | image: selenium/node-chromium:4.32 13 | shm_size: '2g' 14 | depends_on: 15 | - hub 16 | deploy: 17 | replicas: 4 18 | environment: 19 | - SE_EVENT_BUS_HOST=hub 20 | - SE_EVENT_BUS_PUBLISH_PORT=4442 21 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 22 | firefox: 23 | image: selenium/node-firefox:4.32 24 | shm_size: '2g' 25 | depends_on: 26 | - hub 27 | deploy: 28 | replicas: 0 29 | environment: 30 | - SE_EVENT_BUS_HOST=hub 31 | - SE_EVENT_BUS_PUBLISH_PORT=4442 32 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 -------------------------------------------------------------------------------- /04-selenium-grid/03-max-session/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | hub: 3 | image: selenium/hub:4.32 4 | ports: 5 | - 4444:4444 6 | # - 4442:4442 7 | # - 4443:4443 8 | chrome: 9 | image: selenium/node-chromium:4.32 10 | shm_size: '2g' 11 | depends_on: 12 | - hub 13 | environment: 14 | - SE_EVENT_BUS_HOST=hub 15 | - SE_EVENT_BUS_PUBLISH_PORT=4442 16 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 17 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 18 | - SE_NODE_MAX_SESSIONS=4 19 | firefox: 20 | image: selenium/node-firefox:4.32 21 | shm_size: '2g' 22 | depends_on: 23 | - hub 24 | environment: 25 | - SE_EVENT_BUS_HOST=hub 26 | - SE_EVENT_BUS_PUBLISH_PORT=4442 27 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 28 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 29 | - SE_NODE_MAX_SESSIONS=4 -------------------------------------------------------------------------------- /04-selenium-grid/04-vnc-no-password/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | hub: 3 | image: selenium/hub:4.32 4 | ports: 5 | - 4444:4444 6 | # - 4442:4442 7 | # - 4443:4443 8 | chrome: 9 | image: selenium/node-chromium:4.32 10 | shm_size: '2g' 11 | depends_on: 12 | - hub 13 | environment: 14 | - SE_EVENT_BUS_HOST=hub 15 | - SE_EVENT_BUS_PUBLISH_PORT=4442 16 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 17 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 18 | - SE_NODE_MAX_SESSIONS=4 19 | - SE_VNC_NO_PASSWORD=1 20 | firefox: 21 | image: selenium/node-firefox:4.32 22 | shm_size: '2g' 23 | depends_on: 24 | - hub 25 | environment: 26 | - SE_EVENT_BUS_HOST=hub 27 | - SE_EVENT_BUS_PUBLISH_PORT=4442 28 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 29 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 30 | - SE_NODE_MAX_SESSIONS=4 31 | - SE_VNC_NO_PASSWORD=1 -------------------------------------------------------------------------------- /04-selenium-grid/docker-images.md: -------------------------------------------------------------------------------- 1 | # Docker Images 2 | 3 | Please use these docker images for creating selenium grid. There are some known issues with latest version. 4 | So DO NOT use those. I have tested below versions. I periodically update. 5 | 6 | | Image | Verison | 7 | | :--- | :----: | 8 | | Hub | selenium/hub:4.32 | 9 | | Chrome | selenium/node-chromium:4.32 | 10 | | Firefox | selenium/node-firefox:4.32 | 11 | 12 | `We no longer need seleniarm images for Mac.` 13 | 14 | ## References: 15 | 16 | - [Selenium](https://hub.docker.com/u/selenium) 17 | - [Edge does not work in arm](https://techcommunity.microsoft.com/t5/discussions/edge-for-linux-arm64/m-p/1532272) 18 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | **/*.class 5 | 6 | # Log file 7 | **/*.log 8 | 9 | # BlueJ files 10 | **/*.ctxt 11 | 12 | # Mobile Tools for Java (J2ME) 13 | **/.mtj.tmp/ 14 | 15 | # Package Files # 16 | **/*.jar 17 | **/*.war 18 | **/*.nar 19 | **/*.ear 20 | **/*.zip 21 | **/*.tar.gz 22 | **/*.rar 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | **/hs_err_pid* 26 | 27 | ### Maven template 28 | **/target/ 29 | **/pom.xml.tag 30 | **/pom.xml.releaseBackup 31 | **/pom.xml.versionsBackup 32 | **/pom.xml.next 33 | **/release.properties 34 | **/dependency-reduced-pom.xml 35 | **/buildNumber.properties 36 | **/.mvn/timing.properties 37 | **/.mvn/wrapper/maven-wrapper.jar 38 | 39 | **/*.iml 40 | 41 | **/.idea/ 42 | 43 | 44 | **/HELP.md 45 | **/.mvn/ 46 | **/mvnw 47 | **/mvnw.cmd 48 | **/node_modules/ 49 | 50 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/main/java/com/vinsguru/pages/AbstractPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.support.PageFactory; 5 | import org.openqa.selenium.support.ui.WebDriverWait; 6 | 7 | import java.time.Duration; 8 | 9 | public abstract class AbstractPage { 10 | 11 | protected final WebDriver driver; 12 | protected final WebDriverWait wait; 13 | 14 | public AbstractPage(WebDriver driver){ 15 | this.driver = driver; 16 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 17 | PageFactory.initElements(driver, this); 18 | } 19 | 20 | public abstract boolean isAt(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class FlightConfirmationPage extends AbstractPage { 12 | 13 | private static final Logger log = LoggerFactory.getLogger(FlightConfirmationPage.class); 14 | 15 | @FindBy(css = "#flights-confirmation-section .card-body .row:nth-child(1) .col:nth-child(2)") 16 | private WebElement flightConfirmationElement; 17 | 18 | @FindBy(css = "#flights-confirmation-section .card-body .row:nth-child(3) .col:nth-child(2)") 19 | private WebElement totalPriceElement; 20 | 21 | public FlightConfirmationPage(WebDriver driver) { 22 | super(driver); 23 | } 24 | 25 | @Override 26 | public boolean isAt() { 27 | this.wait.until(ExpectedConditions.visibilityOf(this.flightConfirmationElement)); 28 | return this.flightConfirmationElement.isDisplayed(); 29 | } 30 | 31 | public String getPrice(){ 32 | String confirmation = this.flightConfirmationElement.getText(); 33 | String price = this.totalPriceElement.getText(); 34 | log.info("Flight confirmation# : {}", confirmation); 35 | log.info("Total price : {}", price); 36 | return price; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightsSearchPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.Select; 9 | 10 | public class FlightsSearchPage extends AbstractPage { 11 | 12 | @FindBy(id = "passengers") 13 | private WebElement passengerSelect; 14 | 15 | @FindBy(id = "search-flights") 16 | private WebElement searchFlightsButton; 17 | 18 | public FlightsSearchPage(WebDriver driver) { 19 | super(driver); 20 | } 21 | 22 | @Override 23 | public boolean isAt() { 24 | this.wait.until(ExpectedConditions.visibilityOf(this.passengerSelect)); 25 | return this.passengerSelect.isDisplayed(); 26 | } 27 | 28 | public void selectPassengers(String noOfPassengers){ 29 | Select passengers = new Select(this.passengerSelect); 30 | passengers.selectByValue(noOfPassengers); 31 | } 32 | 33 | public void searchFlights(){ 34 | this.searchFlightsButton.click(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightsSelectionPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | import java.util.List; 10 | import java.util.concurrent.ThreadLocalRandom; 11 | 12 | public class FlightsSelectionPage extends AbstractPage { 13 | 14 | @FindBy(name = "departure-flight") 15 | private List departureFlightsOptions; 16 | 17 | @FindBy(name = "arrival-flight") 18 | private List arrivalFlightsOptions; 19 | 20 | @FindBy(id = "confirm-flights") 21 | private WebElement confirmFlightsButton; 22 | 23 | public FlightsSelectionPage(WebDriver driver) { 24 | super(driver); 25 | } 26 | 27 | @Override 28 | public boolean isAt() { 29 | this.wait.until(ExpectedConditions.visibilityOf(this.confirmFlightsButton)); 30 | return this.confirmFlightsButton.isDisplayed(); 31 | } 32 | 33 | public void selectFlights(){ 34 | int random = ThreadLocalRandom.current().nextInt(0, departureFlightsOptions.size()); 35 | this.departureFlightsOptions.get(random).click(); 36 | this.arrivalFlightsOptions.get(random).click(); 37 | } 38 | 39 | public void confirmFlights(){ 40 | this.confirmFlightsButton.click(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/RegistrationConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | public class RegistrationConfirmationPage extends AbstractPage { 10 | 11 | @FindBy(id = "go-to-flights-search") 12 | private WebElement goToFlightsSearchButton; 13 | 14 | @FindBy(css = "#registration-confirmation-section p b") 15 | private WebElement firstNameElement; 16 | 17 | public RegistrationConfirmationPage(WebDriver driver){ 18 | super(driver); 19 | } 20 | 21 | @Override 22 | public boolean isAt() { 23 | this.wait.until(ExpectedConditions.visibilityOf(this.goToFlightsSearchButton)); 24 | return this.goToFlightsSearchButton.isDisplayed(); 25 | } 26 | 27 | public String getFirstName(){ 28 | return this.firstNameElement.getText(); 29 | } 30 | 31 | public void goToFlightsSearch(){ 32 | this.goToFlightsSearchButton.click(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/main/java/com/vinsguru/pages/vendorportal/LoginPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.vendorportal; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | public class LoginPage extends AbstractPage { 10 | 11 | @FindBy(id = "username") 12 | private WebElement usernameInput; 13 | 14 | @FindBy(id = "password") 15 | private WebElement passwordInput; 16 | 17 | @FindBy(id = "login") 18 | private WebElement loginButton; 19 | 20 | public LoginPage(WebDriver driver) { 21 | super(driver); 22 | } 23 | 24 | @Override 25 | public boolean isAt() { 26 | this.wait.until(ExpectedConditions.visibilityOf(this.loginButton)); 27 | return this.loginButton.isDisplayed(); 28 | } 29 | 30 | public void goTo(String url){ 31 | this.driver.get(url); 32 | } 33 | 34 | public void login(String username, String password){ 35 | this.usernameInput.sendKeys(username); 36 | this.passwordInput.sendKeys(password); 37 | this.loginButton.click(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} %-5level [%15.15t] %cyan(%-30.30logger{30}) : %m%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/java/com/vinsguru/listener/TestListener.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.listener; 2 | 3 | import com.vinsguru.util.Constants; 4 | import org.openqa.selenium.OutputType; 5 | import org.openqa.selenium.TakesScreenshot; 6 | import org.testng.ITestListener; 7 | import org.testng.ITestResult; 8 | import org.testng.Reporter; 9 | 10 | public class TestListener implements ITestListener { 11 | 12 | @Override 13 | public void onTestFailure(ITestResult result) { 14 | TakesScreenshot driver = (TakesScreenshot) result.getTestContext().getAttribute(Constants.DRIVER); 15 | String screenshot = driver.getScreenshotAs(OutputType.BASE64); 16 | String htmlImageFormat = ""; 17 | String htmlImage = String.format(htmlImageFormat, screenshot); 18 | Reporter.log(htmlImage); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/java/com/vinsguru/tests/flightreservation/model/FlightReservationTestData.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.tests.flightreservation.model; 2 | 3 | public record FlightReservationTestData(String firstName, 4 | String lastName, 5 | String email, 6 | String password, 7 | String street, 8 | String city, 9 | String zip, 10 | String passengersCount, 11 | String expectedPrice) { 12 | } 13 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/java/com/vinsguru/util/Config.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.InputStream; 7 | import java.util.Properties; 8 | 9 | public class Config { 10 | 11 | private static final Logger log = LoggerFactory.getLogger(Config.class); 12 | private static final String DEFAULT_PROPERTIES = "config/default.properties"; 13 | private static Properties properties; 14 | 15 | public static void initialize(){ 16 | 17 | // load default properties 18 | properties = loadProperties(); 19 | 20 | // check for any override 21 | for(String key: properties.stringPropertyNames()){ 22 | if(System.getProperties().containsKey(key)){ 23 | properties.setProperty(key, System.getProperty(key)); 24 | } 25 | } 26 | 27 | // print 28 | log.info("Test Properties"); 29 | log.info("-----------------"); 30 | for(String key: properties.stringPropertyNames()){ 31 | log.info("{}={}", key, properties.getProperty(key)); 32 | } 33 | log.info("-----------------"); 34 | 35 | } 36 | 37 | public static String get(String key){ 38 | return properties.getProperty(key); 39 | } 40 | 41 | private static Properties loadProperties(){ 42 | Properties properties = new Properties(); 43 | try(InputStream stream = ResourceLoader.getResource(DEFAULT_PROPERTIES)){ 44 | properties.load(stream); 45 | }catch (Exception e){ 46 | log.error("unable to read the property file {}", DEFAULT_PROPERTIES, e); 47 | } 48 | return properties; 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/java/com/vinsguru/util/Constants.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | public class Constants { 4 | 5 | public static final String GRID_ENABLED = "selenium.grid.enabled"; 6 | public static final String GRID_URL_FORMAT = "selenium.grid.urlFormat"; 7 | public static final String GRID_HUB_HOST = "selenium.grid.hubHost"; 8 | 9 | public static final String BROWSER = "browser"; 10 | public static final String CHROME = "chrome"; 11 | public static final String FIREFOX = "firefox"; 12 | public static final String DRIVER = "driver"; 13 | 14 | public static final String FLIGHT_RESERVATION_URL = "flightReservation.url"; 15 | public static final String VENDOR_PORTAL_URL = "vendorPortal.url"; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/java/com/vinsguru/util/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.vinsguru.tests.vendorportal.model.VendorPortalTestData; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.InputStream; 9 | 10 | public class JsonUtil { 11 | 12 | private static final Logger log = LoggerFactory.getLogger(JsonUtil.class); 13 | private static final ObjectMapper mapper = new ObjectMapper(); 14 | 15 | public static T getTestData(String path, Class type){ 16 | try(InputStream stream = ResourceLoader.getResource(path)){ 17 | return mapper.readValue(stream, type); 18 | }catch (Exception e){ 19 | log.error("unable to read test data {}", path, e); 20 | } 21 | return null; 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/java/com/vinsguru/util/ResourceLoader.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.InputStream; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.util.Objects; 10 | 11 | /* 12 | A simple utility to read file. 13 | first we check the classpath. if found, it is used. 14 | if not, then we check the filesystem 15 | */ 16 | public class ResourceLoader { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(ResourceLoader.class); 19 | 20 | public static InputStream getResource(String path) throws Exception { 21 | log.info("reading resource from location: {}", path); 22 | InputStream stream = ResourceLoader.class.getClassLoader().getResourceAsStream(path); 23 | if(Objects.nonNull(stream)){ 24 | return stream; 25 | } 26 | return Files.newInputStream(Path.of(path)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/resources/config/default.properties: -------------------------------------------------------------------------------- 1 | # selenium grid 2 | selenium.grid.enabled=false 3 | selenium.grid.urlFormat=http://%s:4444/wd/hub 4 | selenium.grid.hubHost=localhost 5 | 6 | # browser 7 | browser=chrome 8 | 9 | # application 10 | flightReservation.url=https://d1uh9e7cu07ukd.cloudfront.net/selenium-docker/reservation-app/index.html 11 | vendorPortal.url=https://d1uh9e7cu07ukd.cloudfront.net/selenium-docker/vendor-app/index.html -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "michael", 3 | "lastName": "jackson", 4 | "email": "mj@pop.com", 5 | "password": "mj", 6 | "street": "123 main street", 7 | "city": "atlanta", 8 | "zip": "30001", 9 | "passengersCount": "1", 10 | "expectedPrice": "$584 USD" 11 | } -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "marshall", 3 | "lastName": "mathers", 4 | "email": "eminem@hiphop.com", 5 | "password": "m&m", 6 | "street": "456 main street", 7 | "city": "detroit", 8 | "zip": "40001", 9 | "passengersCount": "2", 10 | "expectedPrice": "$1169 USD" 11 | } -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "cheb", 3 | "lastName": "khaled", 4 | "email": "khaled@rai.com", 5 | "password": "didi", 6 | "street": "101 non main street", 7 | "city": "las vegas", 8 | "zip": "50001", 9 | "passengersCount": "3", 10 | "expectedPrice": "$1753 USD" 11 | } -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "dr", 3 | "lastName": "dre", 4 | "email": "dr@dre.com", 5 | "password": "dre", 6 | "street": "455 main street", 7 | "city": "detroit", 8 | "zip": "40001", 9 | "passengersCount": "4", 10 | "expectedPrice": "$2338 USD" 11 | } -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/resources/test-data/vendor-portal/john.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "john", 3 | "password": "john", 4 | "monthlyEarning": "$3,453", 5 | "annualEarning": "$34,485", 6 | "profitMargin": "-16%", 7 | "availableInventory": "67", 8 | "searchKeyword": "2024/01/01", 9 | "searchResultsCount": 0 10 | } -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/resources/test-data/vendor-portal/mike.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "mike", 3 | "password": "mike", 4 | "monthlyEarning": "$55,000", 5 | "annualEarning": "$563,300", 6 | "profitMargin": "80%", 7 | "availableInventory": "45", 8 | "searchKeyword": "miami", 9 | "searchResultsCount": 10 10 | } -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/resources/test-data/vendor-portal/sam.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "sam", 3 | "password": "sam", 4 | "monthlyEarning": "$40,000", 5 | "annualEarning": "$215,000", 6 | "profitMargin": "50%", 7 | "availableInventory": "18", 8 | "searchKeyword": "adams", 9 | "searchResultsCount": 8 10 | } -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/resources/test-suites/flight-reservation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /04-selenium-grid/selenium-docker/src/test/resources/test-suites/vendor-portal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /05-dockerize/01-running-tests/Readme.md: -------------------------------------------------------------------------------- 1 | # Running Tests 2 | 3 | ### TestNG parameters 4 | 5 | - Running a test suite 6 | 7 | `java -cp 'libs/*' org.testng.TestNG test-suites/flight-reservation.xml` 8 | 9 | - Running a test suite with specific thread count 10 | 11 | `java -cp 'libs/*' org.testng.TestNG -threadcount 2 test-suites/flight-reservation.xml` 12 | 13 | - TestNG by default creates **test-output** directory. You can change it with **-d** option. 14 | 15 | `java -cp 'libs/*' org.testng.TestNG -threadcount 2 -d result test-suites/flight-reservation.xml` 16 | 17 | --- 18 | 19 | ### System Properties 20 | 21 | - To pass the browser option 22 | 23 | `java -Dbrowser=chrome -cp 'libs/*' org.testng.TestNG test-suites/flight-reservation.xml` 24 | 25 | - To run the tests using Selenium Grid 26 | 27 | `java -Dselenium.grid.enabled=true -Dselenium.grid.hubHost=localhost -cp 'libs/*' org.testng.TestNG test-suites/flight-reservation.xml` 28 | 29 | - To run the tests using Selenium Grid with specific thread count 30 | 31 | `java -Dselenium.grid.enabled=true -Dselenium.grid.hubHost=localhost -cp 'libs/*' org.testng.TestNG test-suites/flight-reservation.xml -threadcount 2` -------------------------------------------------------------------------------- /05-dockerize/02-grid-and-test-suites/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | hub: 3 | image: selenium/hub:4.32 4 | ports: 5 | - 4444:4444 6 | chrome: 7 | image: selenium/node-chromium:4.32 8 | shm_size: '2g' 9 | depends_on: 10 | - hub 11 | environment: 12 | - SE_EVENT_BUS_HOST=hub 13 | - SE_EVENT_BUS_PUBLISH_PORT=4442 14 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 15 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 16 | - SE_NODE_MAX_SESSIONS=4 17 | firefox: 18 | image: selenium/node-firefox:4.32 19 | shm_size: '2g' 20 | depends_on: 21 | - hub 22 | environment: 23 | - SE_EVENT_BUS_HOST=hub 24 | - SE_EVENT_BUS_PUBLISH_PORT=4442 25 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 26 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 27 | - SE_NODE_MAX_SESSIONS=4 28 | vendor-portal: 29 | image: vinsdocker/selenium 30 | depends_on: 31 | - chrome 32 | environment: 33 | - BROWSER=chrome 34 | - HUB_HOST=hub 35 | - THREAD_COUNT=3 36 | - TEST_SUITE=vendor-portal.xml 37 | volumes: 38 | - ./output/vendor-portal:/home/selenium-docker/test-output 39 | flight-reservation: 40 | image: vinsdocker/selenium 41 | depends_on: 42 | - firefox 43 | environment: 44 | - BROWSER=firefox 45 | - HUB_HOST=hub 46 | - THREAD_COUNT=4 47 | - TEST_SUITE=flight-reservation.xml 48 | volumes: 49 | - ./output/flight-reservation:/home/selenium-docker/test-output -------------------------------------------------------------------------------- /05-dockerize/03-providing-test-data/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | hub: 3 | image: selenium/hub:4.32 4 | ports: 5 | - 4444:4444 6 | chrome: 7 | image: selenium/node-chromium:4.32 8 | shm_size: '2g' 9 | depends_on: 10 | - hub 11 | environment: 12 | - SE_EVENT_BUS_HOST=hub 13 | - SE_EVENT_BUS_PUBLISH_PORT=4442 14 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 15 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 16 | - SE_NODE_MAX_SESSIONS=4 17 | firefox: 18 | image: selenium/node-firefox:4.32 19 | shm_size: '2g' 20 | depends_on: 21 | - hub 22 | environment: 23 | - SE_EVENT_BUS_HOST=hub 24 | - SE_EVENT_BUS_PUBLISH_PORT=4442 25 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 26 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 27 | - SE_NODE_MAX_SESSIONS=4 28 | vendor-portal: 29 | image: vinsdocker/selenium 30 | depends_on: 31 | - chrome 32 | environment: 33 | - BROWSER=chrome 34 | - HUB_HOST=hub 35 | - THREAD_COUNT=3 36 | - TEST_SUITE=vendor-portal.xml 37 | volumes: 38 | - ./output/vendor-portal:/home/selenium-docker/test-output 39 | - ./test-data/mike.json:/home/selenium-docker/test-data/vendor-portal/mike.json 40 | flight-reservation: 41 | image: vinsdocker/selenium 42 | depends_on: 43 | - firefox 44 | environment: 45 | - BROWSER=firefox 46 | - HUB_HOST=hub 47 | - THREAD_COUNT=4 48 | - TEST_SUITE=flight-reservation.xml 49 | volumes: 50 | - ./output/flight-reservation:/home/selenium-docker/test-output -------------------------------------------------------------------------------- /05-dockerize/03-providing-test-data/test-data/mike.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "mike", 3 | "password": "mike", 4 | "monthlyEarning": "$55,000", 5 | "annualEarning": "$563,300", 6 | "profitMargin": "80%", 7 | "availableInventory": "45", 8 | "searchKeyword": "miami", 9 | "searchResultsCount": 8 10 | } -------------------------------------------------------------------------------- /05-dockerize/04-scale-browser/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | vendor-portal: 3 | image: vinsdocker/selenium 4 | environment: 5 | - BROWSER=${BROWSER} 6 | - HUB_HOST=hub 7 | - THREAD_COUNT=3 8 | - TEST_SUITE=vendor-portal.xml 9 | volumes: 10 | - ./output/vendor-portal:/home/selenium-docker/test-output 11 | flight-reservation: 12 | image: vinsdocker/selenium 13 | environment: 14 | - BROWSER=${BROWSER} 15 | - HUB_HOST=hub 16 | - THREAD_COUNT=4 17 | - TEST_SUITE=flight-reservation.xml 18 | volumes: 19 | - ./output/flight-reservation:/home/selenium-docker/test-output -------------------------------------------------------------------------------- /05-dockerize/04-scale-browser/grid.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | hub: 4 | image: selenium/hub:4.32 5 | chrome: 6 | image: selenium/node-chromium:4.32 7 | shm_size: '2g' 8 | depends_on: 9 | - hub 10 | deploy: 11 | replicas: 0 12 | environment: 13 | - SE_EVENT_BUS_HOST=hub 14 | - SE_EVENT_BUS_PUBLISH_PORT=4442 15 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 16 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 17 | - SE_NODE_MAX_SESSIONS=4 18 | firefox: 19 | image: selenium/node-firefox:4.32 20 | shm_size: '2g' 21 | depends_on: 22 | - hub 23 | deploy: 24 | replicas: 0 25 | environment: 26 | - SE_EVENT_BUS_HOST=hub 27 | - SE_EVENT_BUS_PUBLISH_PORT=4442 28 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 29 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 30 | - SE_NODE_MAX_SESSIONS=4 -------------------------------------------------------------------------------- /05-dockerize/04-scale-browser/run.sh: -------------------------------------------------------------------------------- 1 | # start the grid with 2 chrome containers 2 | docker-compose -f grid.yaml up --scale chrome=2 -d 3 | 4 | # run test suites with chrome 5 | BROWSER=chrome docker-compose up 6 | 7 | # stop chrome and run firefox containers 8 | docker-compose -f grid.yaml up --scale firefox=2 -d 9 | 10 | # run test suites with firefox 11 | BROWSER=firefox docker-compose up 12 | 13 | # bring down all 14 | docker-compose -f grid.yaml down 15 | docker-compose down -------------------------------------------------------------------------------- /05-dockerize/debugging-steps.md: -------------------------------------------------------------------------------- 1 | # Follow these instructions carefully to debug your issues 2 | 3 | - Ensure that you completely replace your pom dependencies with [this](../03-automation-framework/dependencies.md). 4 | - Compare your project with mine. 5 | - [This](./selenium-docker/) is my project. 6 | - Use tools like [WinMerge](https://winmerge.org/?lang=en) which can spot the difference between your project and my project. 7 | - Run your test runs via IDE. It should work. 8 | - Issue this command. `mvn clean package -DskipTests`. You should see `docker-resources` under `target`. 9 | - `docker-resources` should contain following directories. Ensure that files are present under these directories. 10 | - config 11 | - libs 12 | - test-data 13 | - test-suites 14 | - Go to `docker-resources` via command line. Then issue this command. One of them should work. 15 | - `java -cp 'libs/*' org.testng.TestNG test-suites/flight-reservation.xml` 16 | - `java -cp libs/* org.testng.TestNG test-suites/flight-reservation.xml` 17 | - `java -cp "libs/*" org.testng.TestNG test-suites/flight-reservation.xml` 18 | - Windows Users 19 | - Try in PS 20 | - Try in regular command prompt. (`cmd`) 21 | - Mac/Linux Users 22 | - Try via `bash` -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | **/*.class 5 | 6 | # Log file 7 | **/*.log 8 | 9 | # BlueJ files 10 | **/*.ctxt 11 | 12 | # Mobile Tools for Java (J2ME) 13 | **/.mtj.tmp/ 14 | 15 | # Package Files # 16 | **/*.jar 17 | **/*.war 18 | **/*.nar 19 | **/*.ear 20 | **/*.zip 21 | **/*.tar.gz 22 | **/*.rar 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | **/hs_err_pid* 26 | 27 | ### Maven template 28 | **/target/ 29 | **/pom.xml.tag 30 | **/pom.xml.releaseBackup 31 | **/pom.xml.versionsBackup 32 | **/pom.xml.next 33 | **/release.properties 34 | **/dependency-reduced-pom.xml 35 | **/buildNumber.properties 36 | **/.mvn/timing.properties 37 | **/.mvn/wrapper/maven-wrapper.jar 38 | 39 | **/*.iml 40 | 41 | **/.idea/ 42 | 43 | 44 | **/HELP.md 45 | **/.mvn/ 46 | **/mvnw 47 | **/mvnw.cmd 48 | **/node_modules/ 49 | 50 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM bellsoft/liberica-openjdk-alpine:21 2 | 3 | # Install curl jq 4 | RUN apk add curl jq 5 | 6 | # workspace 7 | WORKDIR /home/selenium-docker 8 | 9 | # Add the required files 10 | ADD target/docker-resources ./ 11 | ADD runner.sh runner.sh 12 | 13 | # Start the runner.sh 14 | ENTRYPOINT sh runner.sh -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/runner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #------------------------------------------------------------------- 4 | # This script expects the following environment variables 5 | # HUB_HOST 6 | # BROWSER 7 | # THREAD_COUNT 8 | # TEST_SUITE 9 | #------------------------------------------------------------------- 10 | 11 | # Let's print what we have received 12 | echo "-------------------------------------------" 13 | echo "HUB_HOST : ${HUB_HOST:-hub}" 14 | echo "BROWSER : ${BROWSER:-chrome}" 15 | echo "THREAD_COUNT : ${THREAD_COUNT:-1}" 16 | echo "TEST_SUITE : ${TEST_SUITE}" 17 | echo "-------------------------------------------" 18 | 19 | # Do not start the tests immediately. Hub has to be ready with browser nodes 20 | echo "Checking if hub is ready..!" 21 | count=0 22 | while [ "$( curl -s http://${HUB_HOST:-hub}:4444/status | jq -r .value.ready )" != "true" ] 23 | do 24 | count=$((count+1)) 25 | echo "Attempt: ${count}" 26 | if [ "$count" -ge 30 ] 27 | then 28 | echo "**** HUB IS NOT READY WITHIN 30 SECONDS ****" 29 | exit 1 30 | fi 31 | sleep 1 32 | done 33 | 34 | # At this point, selenium grid should be up! 35 | echo "Selenium Grid is up and running. Running the test...." 36 | 37 | # Start the java command 38 | java -cp 'libs/*' \ 39 | -Dselenium.grid.enabled=true \ 40 | -Dselenium.grid.hubHost="${HUB_HOST:-hub}" \ 41 | -Dbrowser="${BROWSER:-chrome}" \ 42 | org.testng.TestNG \ 43 | -threadcount "${THREAD_COUNT:-1}" \ 44 | test-suites/"${TEST_SUITE}" -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/main/java/com/vinsguru/pages/AbstractPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.support.PageFactory; 5 | import org.openqa.selenium.support.ui.WebDriverWait; 6 | 7 | import java.time.Duration; 8 | 9 | public abstract class AbstractPage { 10 | 11 | protected final WebDriver driver; 12 | protected final WebDriverWait wait; 13 | 14 | public AbstractPage(WebDriver driver){ 15 | this.driver = driver; 16 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 17 | PageFactory.initElements(driver, this); 18 | } 19 | 20 | public abstract boolean isAt(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class FlightConfirmationPage extends AbstractPage { 12 | 13 | private static final Logger log = LoggerFactory.getLogger(FlightConfirmationPage.class); 14 | 15 | @FindBy(css = "#flights-confirmation-section .card-body .row:nth-child(1) .col:nth-child(2)") 16 | private WebElement flightConfirmationElement; 17 | 18 | @FindBy(css = "#flights-confirmation-section .card-body .row:nth-child(3) .col:nth-child(2)") 19 | private WebElement totalPriceElement; 20 | 21 | public FlightConfirmationPage(WebDriver driver) { 22 | super(driver); 23 | } 24 | 25 | @Override 26 | public boolean isAt() { 27 | this.wait.until(ExpectedConditions.visibilityOf(this.flightConfirmationElement)); 28 | return this.flightConfirmationElement.isDisplayed(); 29 | } 30 | 31 | public String getPrice(){ 32 | String confirmation = this.flightConfirmationElement.getText(); 33 | String price = this.totalPriceElement.getText(); 34 | log.info("Flight confirmation# : {}", confirmation); 35 | log.info("Total price : {}", price); 36 | return price; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightsSearchPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.Select; 9 | 10 | public class FlightsSearchPage extends AbstractPage { 11 | 12 | @FindBy(id = "passengers") 13 | private WebElement passengerSelect; 14 | 15 | @FindBy(id = "search-flights") 16 | private WebElement searchFlightsButton; 17 | 18 | public FlightsSearchPage(WebDriver driver) { 19 | super(driver); 20 | } 21 | 22 | @Override 23 | public boolean isAt() { 24 | this.wait.until(ExpectedConditions.visibilityOf(this.passengerSelect)); 25 | return this.passengerSelect.isDisplayed(); 26 | } 27 | 28 | public void selectPassengers(String noOfPassengers){ 29 | Select passengers = new Select(this.passengerSelect); 30 | passengers.selectByValue(noOfPassengers); 31 | } 32 | 33 | public void searchFlights(){ 34 | this.searchFlightsButton.click(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightsSelectionPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | import java.util.List; 10 | import java.util.concurrent.ThreadLocalRandom; 11 | 12 | public class FlightsSelectionPage extends AbstractPage { 13 | 14 | @FindBy(name = "departure-flight") 15 | private List departureFlightsOptions; 16 | 17 | @FindBy(name = "arrival-flight") 18 | private List arrivalFlightsOptions; 19 | 20 | @FindBy(id = "confirm-flights") 21 | private WebElement confirmFlightsButton; 22 | 23 | public FlightsSelectionPage(WebDriver driver) { 24 | super(driver); 25 | } 26 | 27 | @Override 28 | public boolean isAt() { 29 | this.wait.until(ExpectedConditions.visibilityOf(this.confirmFlightsButton)); 30 | return this.confirmFlightsButton.isDisplayed(); 31 | } 32 | 33 | public void selectFlights(){ 34 | int random = ThreadLocalRandom.current().nextInt(0, departureFlightsOptions.size()); 35 | this.departureFlightsOptions.get(random).click(); 36 | this.arrivalFlightsOptions.get(random).click(); 37 | } 38 | 39 | public void confirmFlights(){ 40 | this.confirmFlightsButton.click(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/RegistrationConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | public class RegistrationConfirmationPage extends AbstractPage { 10 | 11 | @FindBy(id = "go-to-flights-search") 12 | private WebElement goToFlightsSearchButton; 13 | 14 | @FindBy(css = "#registration-confirmation-section p b") 15 | private WebElement firstNameElement; 16 | 17 | public RegistrationConfirmationPage(WebDriver driver){ 18 | super(driver); 19 | } 20 | 21 | @Override 22 | public boolean isAt() { 23 | this.wait.until(ExpectedConditions.visibilityOf(this.goToFlightsSearchButton)); 24 | return this.goToFlightsSearchButton.isDisplayed(); 25 | } 26 | 27 | public String getFirstName(){ 28 | return this.firstNameElement.getText(); 29 | } 30 | 31 | public void goToFlightsSearch(){ 32 | this.goToFlightsSearchButton.click(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/main/java/com/vinsguru/pages/vendorportal/LoginPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.vendorportal; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | public class LoginPage extends AbstractPage { 10 | 11 | @FindBy(id = "username") 12 | private WebElement usernameInput; 13 | 14 | @FindBy(id = "password") 15 | private WebElement passwordInput; 16 | 17 | @FindBy(id = "login") 18 | private WebElement loginButton; 19 | 20 | public LoginPage(WebDriver driver) { 21 | super(driver); 22 | } 23 | 24 | @Override 25 | public boolean isAt() { 26 | this.wait.until(ExpectedConditions.visibilityOf(this.loginButton)); 27 | return this.loginButton.isDisplayed(); 28 | } 29 | 30 | public void goTo(String url){ 31 | this.driver.get(url); 32 | } 33 | 34 | public void login(String username, String password){ 35 | this.usernameInput.sendKeys(username); 36 | this.passwordInput.sendKeys(password); 37 | this.loginButton.click(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} %-5level [%15.15t] %cyan(%-30.30logger{30}) : %m%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/java/com/vinsguru/listener/TestListener.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.listener; 2 | 3 | import com.vinsguru.util.Constants; 4 | import org.openqa.selenium.OutputType; 5 | import org.openqa.selenium.TakesScreenshot; 6 | import org.testng.ITestListener; 7 | import org.testng.ITestResult; 8 | import org.testng.Reporter; 9 | 10 | public class TestListener implements ITestListener { 11 | 12 | @Override 13 | public void onTestFailure(ITestResult result) { 14 | TakesScreenshot driver = (TakesScreenshot) result.getTestContext().getAttribute(Constants.DRIVER); 15 | String screenshot = driver.getScreenshotAs(OutputType.BASE64); 16 | String htmlImageFormat = ""; 17 | String htmlImage = String.format(htmlImageFormat, screenshot); 18 | Reporter.log(htmlImage); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/java/com/vinsguru/tests/flightreservation/model/FlightReservationTestData.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.tests.flightreservation.model; 2 | 3 | public record FlightReservationTestData(String firstName, 4 | String lastName, 5 | String email, 6 | String password, 7 | String street, 8 | String city, 9 | String zip, 10 | String passengersCount, 11 | String expectedPrice) { 12 | } 13 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/java/com/vinsguru/util/Config.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.InputStream; 7 | import java.util.Properties; 8 | 9 | public class Config { 10 | 11 | private static final Logger log = LoggerFactory.getLogger(Config.class); 12 | private static final String DEFAULT_PROPERTIES = "config/default.properties"; 13 | private static Properties properties; 14 | 15 | public static void initialize(){ 16 | 17 | // load default properties 18 | properties = loadProperties(); 19 | 20 | // check for any override 21 | for(String key: properties.stringPropertyNames()){ 22 | if(System.getProperties().containsKey(key)){ 23 | properties.setProperty(key, System.getProperty(key)); 24 | } 25 | } 26 | 27 | // print 28 | log.info("Test Properties"); 29 | log.info("-----------------"); 30 | for(String key: properties.stringPropertyNames()){ 31 | log.info("{}={}", key, properties.getProperty(key)); 32 | } 33 | log.info("-----------------"); 34 | 35 | } 36 | 37 | public static String get(String key){ 38 | return properties.getProperty(key); 39 | } 40 | 41 | private static Properties loadProperties(){ 42 | Properties properties = new Properties(); 43 | try(InputStream stream = ResourceLoader.getResource(DEFAULT_PROPERTIES)){ 44 | properties.load(stream); 45 | }catch (Exception e){ 46 | log.error("unable to read the property file {}", DEFAULT_PROPERTIES, e); 47 | } 48 | return properties; 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/java/com/vinsguru/util/Constants.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | public class Constants { 4 | 5 | public static final String GRID_ENABLED = "selenium.grid.enabled"; 6 | public static final String GRID_URL_FORMAT = "selenium.grid.urlFormat"; 7 | public static final String GRID_HUB_HOST = "selenium.grid.hubHost"; 8 | 9 | public static final String BROWSER = "browser"; 10 | public static final String CHROME = "chrome"; 11 | public static final String FIREFOX = "firefox"; 12 | public static final String DRIVER = "driver"; 13 | 14 | public static final String FLIGHT_RESERVATION_URL = "flightReservation.url"; 15 | public static final String VENDOR_PORTAL_URL = "vendorPortal.url"; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/java/com/vinsguru/util/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.vinsguru.tests.vendorportal.model.VendorPortalTestData; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.InputStream; 9 | 10 | public class JsonUtil { 11 | 12 | private static final Logger log = LoggerFactory.getLogger(JsonUtil.class); 13 | private static final ObjectMapper mapper = new ObjectMapper(); 14 | 15 | public static T getTestData(String path, Class type){ 16 | try(InputStream stream = ResourceLoader.getResource(path)){ 17 | return mapper.readValue(stream, type); 18 | }catch (Exception e){ 19 | log.error("unable to read test data {}", path, e); 20 | } 21 | return null; 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/java/com/vinsguru/util/ResourceLoader.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.InputStream; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.util.Objects; 10 | 11 | /* 12 | A simple utility to read file. 13 | first we check the classpath. if found, it is used. 14 | if not, then we check the filesystem 15 | */ 16 | public class ResourceLoader { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(ResourceLoader.class); 19 | 20 | public static InputStream getResource(String path) throws Exception { 21 | log.info("reading resource from location: {}", path); 22 | InputStream stream = ResourceLoader.class.getClassLoader().getResourceAsStream(path); 23 | if(Objects.nonNull(stream)){ 24 | return stream; 25 | } 26 | return Files.newInputStream(Path.of(path)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/resources/config/default.properties: -------------------------------------------------------------------------------- 1 | # selenium grid 2 | selenium.grid.enabled=false 3 | selenium.grid.urlFormat=http://%s:4444/wd/hub 4 | selenium.grid.hubHost=localhost 5 | 6 | # browser 7 | browser=chrome 8 | 9 | # application 10 | flightReservation.url=https://d1uh9e7cu07ukd.cloudfront.net/selenium-docker/reservation-app/index.html 11 | vendorPortal.url=https://d1uh9e7cu07ukd.cloudfront.net/selenium-docker/vendor-app/index.html -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "michael", 3 | "lastName": "jackson", 4 | "email": "mj@pop.com", 5 | "password": "mj", 6 | "street": "123 main street", 7 | "city": "atlanta", 8 | "zip": "30001", 9 | "passengersCount": "1", 10 | "expectedPrice": "$584 USD" 11 | } -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "marshall", 3 | "lastName": "mathers", 4 | "email": "eminem@hiphop.com", 5 | "password": "m&m", 6 | "street": "456 main street", 7 | "city": "detroit", 8 | "zip": "40001", 9 | "passengersCount": "2", 10 | "expectedPrice": "$1169 USD" 11 | } -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "cheb", 3 | "lastName": "khaled", 4 | "email": "khaled@rai.com", 5 | "password": "didi", 6 | "street": "101 non main street", 7 | "city": "las vegas", 8 | "zip": "50001", 9 | "passengersCount": "3", 10 | "expectedPrice": "$1753 USD" 11 | } -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "dr", 3 | "lastName": "dre", 4 | "email": "dr@dre.com", 5 | "password": "dre", 6 | "street": "455 main street", 7 | "city": "detroit", 8 | "zip": "40001", 9 | "passengersCount": "4", 10 | "expectedPrice": "$2338 USD" 11 | } -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/resources/test-data/vendor-portal/john.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "john", 3 | "password": "john", 4 | "monthlyEarning": "$3,453", 5 | "annualEarning": "$34,485", 6 | "profitMargin": "-16%", 7 | "availableInventory": "67", 8 | "searchKeyword": "2024/01/01", 9 | "searchResultsCount": 0 10 | } -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/resources/test-data/vendor-portal/mike.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "mike", 3 | "password": "mike", 4 | "monthlyEarning": "$55,000", 5 | "annualEarning": "$563,300", 6 | "profitMargin": "80%", 7 | "availableInventory": "45", 8 | "searchKeyword": "miami", 9 | "searchResultsCount": 10 10 | } -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/resources/test-data/vendor-portal/sam.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "sam", 3 | "password": "sam", 4 | "monthlyEarning": "$40,000", 5 | "annualEarning": "$215,000", 6 | "profitMargin": "50%", 7 | "availableInventory": "18", 8 | "searchKeyword": "adams", 9 | "searchResultsCount": 8 10 | } -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/resources/test-suites/flight-reservation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /05-dockerize/selenium-docker/src/test/resources/test-suites/vendor-portal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/01-jenkins/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | jenkins: 3 | image: jenkins/jenkins:lts 4 | user: root 5 | ports: 6 | - 8080:8080 7 | - 50000:50000 8 | volumes: 9 | - ./volumes/master:/var/jenkins_home 10 | environment: 11 | - JAVA_OPTS="-Dhudson.model.DirectoryBrowserSupport.CSP=" -------------------------------------------------------------------------------- /06-jenkins-ci-cd/02-simple-pipeline/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline{ 2 | 3 | agent any 4 | 5 | stages{ 6 | 7 | stage('stage-1'){ 8 | steps{ 9 | echo "doing mvn clean" 10 | echo "doing mvn package" 11 | } 12 | } 13 | 14 | stage('stage-2'){ 15 | steps{ 16 | echo "building docker image" 17 | } 18 | } 19 | 20 | stage('stage-3'){ 21 | steps{ 22 | echo "pushing docker image" 23 | } 24 | } 25 | 26 | } 27 | 28 | post { 29 | always { 30 | echo "doing clean up" 31 | } 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/03-agent-label/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline{ 2 | 3 | agent { 4 | label 'echo' 5 | } 6 | 7 | stages{ 8 | 9 | stage('stage-1'){ 10 | steps{ 11 | echo "doing mvn clean" 12 | echo "doing mvn package" 13 | } 14 | } 15 | 16 | stage('stage-2'){ 17 | steps{ 18 | echo "building docker image" 19 | } 20 | } 21 | 22 | stage('stage-3'){ 23 | steps{ 24 | echo "pushing docker image" 25 | } 26 | } 27 | 28 | } 29 | 30 | post { 31 | always { 32 | echo "doing clean up" 33 | } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/04-env-variable/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline{ 2 | 3 | agent any 4 | 5 | environment { 6 | NUMBER = 3 7 | } 8 | 9 | stages{ 10 | 11 | stage('stage-1'){ 12 | steps{ 13 | echo "doing mvn clean" 14 | echo "NUMBER = ${NUMBER}" 15 | } 16 | } 17 | 18 | stage('stage-2'){ 19 | environment { 20 | NUMBER = 6 21 | } 22 | steps{ 23 | echo "NUMBER = ${NUMBER}" 24 | } 25 | } 26 | 27 | stage('stage-3'){ 28 | steps{ 29 | echo "NUMBER = ${NUMBER}" 30 | } 31 | } 32 | 33 | } 34 | 35 | post { 36 | always { 37 | echo "doing clean up" 38 | } 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/05-run-container/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline{ 2 | 3 | agent any 4 | 5 | environment { 6 | NUMBER = 3 7 | } 8 | 9 | stages{ 10 | 11 | stage('stage-1'){ 12 | steps{ 13 | //bat "docker run -e NUMBER=${NUMBER} vinsdocker/squares" 14 | sh "docker run -e NUMBER=${NUMBER} vinsdocker/squares" 15 | } 16 | } 17 | 18 | stage('stage-2'){ 19 | environment { 20 | NUMBER = 6 21 | } 22 | steps{ 23 | sh "docker run -e NUMBER=${NUMBER} vinsdocker/squares" 24 | } 25 | } 26 | 27 | stage('stage-3'){ 28 | steps{ 29 | sh "docker run -e NUMBER=${NUMBER} vinsdocker/squares" 30 | } 31 | } 32 | 33 | } 34 | 35 | post { 36 | always { 37 | sh "docker system prune -f" 38 | } 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/06-docker-agent/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline{ 2 | 3 | agent { 4 | docker { 5 | image "alpine" 6 | } 7 | } 8 | 9 | stages{ 10 | 11 | stage('access-google-home'){ 12 | steps{ 13 | sh "wget www.google.com" 14 | } 15 | } 16 | 17 | } 18 | 19 | post { 20 | always { 21 | archiveArtifacts artifacts: 'index.html', followSymlinks: false 22 | } 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/07-image-builder-approach-1/Jenkinsfile: -------------------------------------------------------------------------------- 1 | /* 2 | Note: 3 | 4 | Windows users use "bat" instead of "sh" 5 | For ex: bat 'docker build -t=vinsdocker/selenium .' 6 | 7 | Do not use "vinsdocker" to push. Use your dockerhub account 8 | */ 9 | pipeline{ 10 | 11 | agent any 12 | 13 | stages{ 14 | 15 | stage('Build Jar'){ 16 | steps{ 17 | sh 'mvn clean package -DskipTests' 18 | } 19 | } 20 | 21 | stage('Build Image'){ 22 | steps{ 23 | sh 'docker build -t=vinsdocker/selenium .' 24 | } 25 | } 26 | 27 | stage('Push Image'){ 28 | environment{ 29 | // assuming you have stored the credentials with this name 30 | DOCKER_HUB = credentials('dockerhub-creds') 31 | } 32 | steps{ 33 | // There might be a warning. 34 | sh 'docker login -u ${DOCKER_HUB_USR} -p ${DOCKER_HUB_PSW}' 35 | sh 'docker push vinsdocker/selenium' 36 | } 37 | } 38 | 39 | } 40 | 41 | post { 42 | always { 43 | sh 'docker logout' 44 | } 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/08-image-builder-approach-2/Jenkinsfile: -------------------------------------------------------------------------------- 1 | /* 2 | Note: 3 | 4 | Windows users use "bat" instead of "sh" 5 | For ex: bat 'docker build -t=vinsdocker/selenium .' 6 | 7 | Do not use "vinsdocker" to push. Use your dockerhub account 8 | */ 9 | pipeline{ 10 | 11 | agent any 12 | 13 | stages{ 14 | 15 | stage('Build Jar'){ 16 | steps{ 17 | sh 'mvn clean package -DskipTests' 18 | } 19 | } 20 | 21 | stage('Build Image'){ 22 | steps{ 23 | sh 'docker build -t=vinsdocker/selenium .' 24 | } 25 | } 26 | 27 | stage('Push Image'){ 28 | environment{ 29 | // assuming you have stored the credentials with this name 30 | DOCKER_HUB = credentials('dockerhub-creds') 31 | } 32 | steps{ 33 | sh 'echo ${DOCKER_HUB_PSW} | docker login -u ${DOCKER_HUB_USR} --password-stdin' 34 | sh 'docker push vinsdocker/selenium' 35 | } 36 | } 37 | 38 | } 39 | 40 | post { 41 | always { 42 | sh 'docker logout' 43 | } 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/09-image-builder-approach-3/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent none 3 | stages { 4 | stage('Build Jar') { 5 | agent { 6 | docker { 7 | image 'maven:3.9.3-eclipse-temurin-17-focal' 8 | args '-u root -v /tmp/m2:/root/.m2' 9 | } 10 | } 11 | steps { 12 | sh 'mvn clean package -DskipTests' 13 | } 14 | } 15 | stage('Build Image') { 16 | steps { 17 | script { 18 | app = docker.build('vinsdocker/selenium') 19 | } 20 | } 21 | } 22 | 23 | stage('Push Image'){ 24 | steps{ 25 | script { 26 | // registry url is blank for dockerhub 27 | docker.withRegistry('', 'dockerhub-creds') { 28 | app.push("latest") 29 | } 30 | } 31 | } 32 | } 33 | 34 | } 35 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/10-runner-approach-1/.env: -------------------------------------------------------------------------------- 1 | SE_EVENT_BUS_HOST=hub 2 | SE_EVENT_BUS_PUBLISH_PORT=4442 3 | SE_EVENT_BUS_SUBSCRIBE_PORT=4443 4 | SE_NODE_OVERRIDE_MAX_SESSIONS=true 5 | SE_NODE_MAX_SESSIONS=4 -------------------------------------------------------------------------------- /06-jenkins-ci-cd/10-runner-approach-1/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline{ 2 | 3 | agent any 4 | 5 | stages{ 6 | 7 | stage('Start Grid'){ 8 | steps{ 9 | sh "docker-compose -f grid.yaml up -d" 10 | } 11 | } 12 | 13 | stage('Run Test'){ 14 | steps{ 15 | sh "docker-compose -f test-suites.yaml up --pull=always" 16 | } 17 | } 18 | 19 | } 20 | 21 | post { 22 | always { 23 | sh "docker-compose -f grid.yaml down" 24 | sh "docker-compose -f test-suites.yaml down" 25 | archiveArtifacts artifacts: 'output/flight-reservation/emailable-report.html', followSymlinks: false 26 | archiveArtifacts artifacts: 'output/vendor-portal/emailable-report.html', followSymlinks: false 27 | } 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/10-runner-approach-1/grid.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | hub: 3 | image: selenium/hub:4.32 4 | chrome: 5 | image: selenium/node-chromium:4.32 6 | shm_size: '2g' 7 | depends_on: 8 | - hub 9 | deploy: 10 | replicas: 1 11 | env_file: .env 12 | firefox: 13 | image: selenium/node-firefox:4.32 14 | shm_size: '2g' 15 | depends_on: 16 | - hub 17 | deploy: 18 | replicas: 1 19 | env_file: .env -------------------------------------------------------------------------------- /06-jenkins-ci-cd/10-runner-approach-1/test-suites.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | vendor-portal: 4 | image: vinsdocker/selenium 5 | environment: 6 | - BROWSER=chrome 7 | - HUB_HOST=hub 8 | - THREAD_COUNT=3 9 | - TEST_SUITE=vendor-portal.xml 10 | volumes: 11 | - ./output/vendor-portal:/home/selenium-docker/test-output 12 | flight-reservation: 13 | image: vinsdocker/selenium 14 | environment: 15 | - BROWSER=firefox 16 | - HUB_HOST=hub 17 | - THREAD_COUNT=4 18 | - TEST_SUITE=flight-reservation.xml 19 | volumes: 20 | - ./output/flight-reservation:/home/selenium-docker/test-output -------------------------------------------------------------------------------- /06-jenkins-ci-cd/11-runner-approach-2/.env: -------------------------------------------------------------------------------- 1 | SE_EVENT_BUS_HOST=hub 2 | SE_EVENT_BUS_PUBLISH_PORT=4442 3 | SE_EVENT_BUS_SUBSCRIBE_PORT=4443 4 | SE_NODE_OVERRIDE_MAX_SESSIONS=true 5 | SE_NODE_MAX_SESSIONS=4 -------------------------------------------------------------------------------- /06-jenkins-ci-cd/11-runner-approach-2/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline{ 2 | 3 | agent any 4 | 5 | parameters { 6 | choice choices: ['chrome', 'firefox'], description: 'Select the browser', name: 'BROWSER' 7 | } 8 | 9 | stages{ 10 | 11 | stage('Start Grid'){ 12 | steps{ 13 | sh "docker-compose -f grid.yaml up --scale ${params.BROWSER}=2 -d" 14 | } 15 | } 16 | 17 | stage('Run Test'){ 18 | steps{ 19 | sh "docker-compose -f test-suites.yaml up --pull=always" 20 | script { 21 | if(fileExists('output/flight-reservation/testng-failed.xml') || fileExists('output/vendor-portal/testng-failed.xml')){ 22 | error('failed tests found') 23 | } 24 | } 25 | } 26 | } 27 | 28 | } 29 | 30 | post { 31 | always { 32 | sh "docker-compose -f grid.yaml down" 33 | sh "docker-compose -f test-suites.yaml down" 34 | archiveArtifacts artifacts: 'output/flight-reservation/emailable-report.html', followSymlinks: false 35 | archiveArtifacts artifacts: 'output/vendor-portal/emailable-report.html', followSymlinks: false 36 | } 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/11-runner-approach-2/grid.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | hub: 3 | image: selenium/hub:4.32 4 | chrome: 5 | image: selenium/node-chromium:4.32 6 | shm_size: '2g' 7 | depends_on: 8 | - hub 9 | deploy: 10 | replicas: 0 11 | env_file: .env 12 | firefox: 13 | image: selenium/node-firefox:4.32 14 | shm_size: '2g' 15 | depends_on: 16 | - hub 17 | deploy: 18 | replicas: 0 19 | env_file: .env -------------------------------------------------------------------------------- /06-jenkins-ci-cd/11-runner-approach-2/test-suites.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | vendor-portal: 4 | image: vinsdocker/selenium 5 | environment: 6 | - BROWSER 7 | - HUB_HOST=hub 8 | - THREAD_COUNT=3 9 | - TEST_SUITE=vendor-portal.xml 10 | volumes: 11 | - ./output/vendor-portal:/home/selenium-docker/test-output 12 | flight-reservation: 13 | image: vinsdocker/selenium 14 | environment: 15 | - BROWSER 16 | - HUB_HOST=hub 17 | - THREAD_COUNT=4 18 | - TEST_SUITE=flight-reservation.xml 19 | volumes: 20 | - ./output/flight-reservation:/home/selenium-docker/test-output -------------------------------------------------------------------------------- /06-jenkins-ci-cd/12-sample-ci-cd/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline{ 2 | 3 | agent any 4 | 5 | stages{ 6 | 7 | stage('mvn-test'){ 8 | steps{ 9 | echo "running unit tests" 10 | echo "running integrations tests" 11 | } 12 | } 13 | 14 | stage('package'){ 15 | steps{ 16 | echo "build application docker image (flight-reservation app)" 17 | } 18 | } 19 | 20 | stage('deploy-to-qa'){ 21 | steps{ 22 | echo "deploying flight-reservation app to QA env" 23 | } 24 | } 25 | 26 | stage('selenium-test'){ 27 | steps{ 28 | build job: 'SELENIUM_DOCKER_RUNNER', parameters: [string(name: 'BROWSER', value: 'firefox')] 29 | } 30 | } 31 | 32 | stage('deploy-to-prod'){ 33 | steps{ 34 | echo "deploying flight-reservation app to PROD env" 35 | } 36 | } 37 | 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | **/*.class 5 | 6 | # Log file 7 | **/*.log 8 | 9 | # BlueJ files 10 | **/*.ctxt 11 | 12 | # Mobile Tools for Java (J2ME) 13 | **/.mtj.tmp/ 14 | 15 | # Package Files # 16 | **/*.jar 17 | **/*.war 18 | **/*.nar 19 | **/*.ear 20 | **/*.zip 21 | **/*.tar.gz 22 | **/*.rar 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | **/hs_err_pid* 26 | 27 | ### Maven template 28 | **/target/ 29 | **/pom.xml.tag 30 | **/pom.xml.releaseBackup 31 | **/pom.xml.versionsBackup 32 | **/pom.xml.next 33 | **/release.properties 34 | **/dependency-reduced-pom.xml 35 | **/buildNumber.properties 36 | **/.mvn/timing.properties 37 | **/.mvn/wrapper/maven-wrapper.jar 38 | 39 | **/*.iml 40 | 41 | **/.idea/ 42 | 43 | 44 | **/HELP.md 45 | **/.mvn/ 46 | **/mvnw 47 | **/mvnw.cmd 48 | **/node_modules/ 49 | 50 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM bellsoft/liberica-openjdk-alpine:21 2 | 3 | # Install curl jq 4 | RUN apk add curl jq 5 | 6 | # workspace 7 | WORKDIR /home/selenium-docker 8 | 9 | # Add the required files 10 | ADD target/docker-resources ./ 11 | ADD runner.sh runner.sh 12 | 13 | # Start the runner.sh 14 | ENTRYPOINT sh runner.sh -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline{ 2 | 3 | agent any 4 | 5 | stages{ 6 | 7 | stage('Build Jar'){ 8 | steps{ 9 | sh 'mvn clean package -DskipTests' 10 | } 11 | } 12 | 13 | stage('Build Image'){ 14 | steps{ 15 | sh 'docker build -t=vinsdocker/selenium:latest .' 16 | } 17 | } 18 | 19 | stage('Push Image'){ 20 | environment{ 21 | DOCKER_HUB = credentials('dockerhub-creds') 22 | } 23 | steps{ 24 | sh 'echo ${DOCKER_HUB_PSW} | docker login -u ${DOCKER_HUB_USR} --password-stdin' 25 | sh 'docker push vinsdocker/selenium:latest' 26 | sh "docker tag vinsdocker/selenium:latest vinsdocker/selenium:${env.BUILD_NUMBER}" 27 | sh "docker push vinsdocker/selenium:${env.BUILD_NUMBER}" 28 | } 29 | } 30 | 31 | } 32 | 33 | post { 34 | always { 35 | sh 'docker logout' 36 | } 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/runner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #------------------------------------------------------------------- 4 | # This script expects the following environment variables 5 | # HUB_HOST 6 | # BROWSER 7 | # THREAD_COUNT 8 | # TEST_SUITE 9 | #------------------------------------------------------------------- 10 | 11 | # Let's print what we have received 12 | echo "-------------------------------------------" 13 | echo "HUB_HOST : ${HUB_HOST:-hub}" 14 | echo "BROWSER : ${BROWSER:-chrome}" 15 | echo "THREAD_COUNT : ${THREAD_COUNT:-1}" 16 | echo "TEST_SUITE : ${TEST_SUITE}" 17 | echo "-------------------------------------------" 18 | 19 | # Do not start the tests immediately. Hub has to be ready with browser nodes 20 | echo "Checking if hub is ready..!" 21 | count=0 22 | while [ "$( curl -s http://${HUB_HOST:-hub}:4444/status | jq -r .value.ready )" != "true" ] 23 | do 24 | count=$((count+1)) 25 | echo "Attempt: ${count}" 26 | if [ "$count" -ge 30 ] 27 | then 28 | echo "**** HUB IS NOT READY WITHIN 30 SECONDS ****" 29 | exit 1 30 | fi 31 | sleep 1 32 | done 33 | 34 | # At this point, selenium grid should be up! 35 | echo "Selenium Grid is up and running. Running the test...." 36 | 37 | # Start the java command 38 | java -cp 'libs/*' \ 39 | -Dselenium.grid.enabled=true \ 40 | -Dselenium.grid.hubHost="${HUB_HOST:-hub}" \ 41 | -Dbrowser="${BROWSER:-chrome}" \ 42 | org.testng.TestNG \ 43 | -threadcount "${THREAD_COUNT:-1}" \ 44 | test-suites/"${TEST_SUITE}" -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/main/java/com/vinsguru/pages/AbstractPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.support.PageFactory; 5 | import org.openqa.selenium.support.ui.WebDriverWait; 6 | 7 | import java.time.Duration; 8 | 9 | public abstract class AbstractPage { 10 | 11 | protected final WebDriver driver; 12 | protected final WebDriverWait wait; 13 | 14 | public AbstractPage(WebDriver driver){ 15 | this.driver = driver; 16 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 17 | PageFactory.initElements(driver, this); 18 | } 19 | 20 | public abstract boolean isAt(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class FlightConfirmationPage extends AbstractPage { 12 | 13 | private static final Logger log = LoggerFactory.getLogger(FlightConfirmationPage.class); 14 | 15 | @FindBy(css = "#flights-confirmation-section .card-body .row:nth-child(1) .col:nth-child(2)") 16 | private WebElement flightConfirmationElement; 17 | 18 | @FindBy(css = "#flights-confirmation-section .card-body .row:nth-child(3) .col:nth-child(2)") 19 | private WebElement totalPriceElement; 20 | 21 | public FlightConfirmationPage(WebDriver driver) { 22 | super(driver); 23 | } 24 | 25 | @Override 26 | public boolean isAt() { 27 | this.wait.until(ExpectedConditions.visibilityOf(this.flightConfirmationElement)); 28 | return this.flightConfirmationElement.isDisplayed(); 29 | } 30 | 31 | public String getPrice(){ 32 | String confirmation = this.flightConfirmationElement.getText(); 33 | String price = this.totalPriceElement.getText(); 34 | log.info("Flight confirmation# : {}", confirmation); 35 | log.info("Total price : {}", price); 36 | return price; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightsSearchPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.Select; 9 | 10 | public class FlightsSearchPage extends AbstractPage { 11 | 12 | @FindBy(id = "passengers") 13 | private WebElement passengerSelect; 14 | 15 | @FindBy(id = "search-flights") 16 | private WebElement searchFlightsButton; 17 | 18 | public FlightsSearchPage(WebDriver driver) { 19 | super(driver); 20 | } 21 | 22 | @Override 23 | public boolean isAt() { 24 | this.wait.until(ExpectedConditions.visibilityOf(this.passengerSelect)); 25 | return this.passengerSelect.isDisplayed(); 26 | } 27 | 28 | public void selectPassengers(String noOfPassengers){ 29 | Select passengers = new Select(this.passengerSelect); 30 | passengers.selectByValue(noOfPassengers); 31 | } 32 | 33 | public void searchFlights(){ 34 | this.searchFlightsButton.click(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightsSelectionPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | import java.util.List; 10 | import java.util.concurrent.ThreadLocalRandom; 11 | 12 | public class FlightsSelectionPage extends AbstractPage { 13 | 14 | @FindBy(name = "departure-flight") 15 | private List departureFlightsOptions; 16 | 17 | @FindBy(name = "arrival-flight") 18 | private List arrivalFlightsOptions; 19 | 20 | @FindBy(id = "confirm-flights") 21 | private WebElement confirmFlightsButton; 22 | 23 | public FlightsSelectionPage(WebDriver driver) { 24 | super(driver); 25 | } 26 | 27 | @Override 28 | public boolean isAt() { 29 | this.wait.until(ExpectedConditions.visibilityOf(this.confirmFlightsButton)); 30 | return this.confirmFlightsButton.isDisplayed(); 31 | } 32 | 33 | public void selectFlights(){ 34 | int random = ThreadLocalRandom.current().nextInt(0, departureFlightsOptions.size()); 35 | this.departureFlightsOptions.get(random).click(); 36 | this.arrivalFlightsOptions.get(random).click(); 37 | } 38 | 39 | public void confirmFlights(){ 40 | this.confirmFlightsButton.click(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/RegistrationConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | public class RegistrationConfirmationPage extends AbstractPage { 10 | 11 | @FindBy(id = "go-to-flights-search") 12 | private WebElement goToFlightsSearchButton; 13 | 14 | @FindBy(css = "#registration-confirmation-section p b") 15 | private WebElement firstNameElement; 16 | 17 | public RegistrationConfirmationPage(WebDriver driver){ 18 | super(driver); 19 | } 20 | 21 | @Override 22 | public boolean isAt() { 23 | this.wait.until(ExpectedConditions.visibilityOf(this.goToFlightsSearchButton)); 24 | return this.goToFlightsSearchButton.isDisplayed(); 25 | } 26 | 27 | public String getFirstName(){ 28 | return this.firstNameElement.getText(); 29 | } 30 | 31 | public void goToFlightsSearch(){ 32 | this.goToFlightsSearchButton.click(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/main/java/com/vinsguru/pages/vendorportal/LoginPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.vendorportal; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | public class LoginPage extends AbstractPage { 10 | 11 | @FindBy(id = "username") 12 | private WebElement usernameInput; 13 | 14 | @FindBy(id = "password") 15 | private WebElement passwordInput; 16 | 17 | @FindBy(id = "login") 18 | private WebElement loginButton; 19 | 20 | public LoginPage(WebDriver driver) { 21 | super(driver); 22 | } 23 | 24 | @Override 25 | public boolean isAt() { 26 | this.wait.until(ExpectedConditions.visibilityOf(this.loginButton)); 27 | return this.loginButton.isDisplayed(); 28 | } 29 | 30 | public void goTo(String url){ 31 | this.driver.get(url); 32 | } 33 | 34 | public void login(String username, String password){ 35 | this.usernameInput.sendKeys(username); 36 | this.passwordInput.sendKeys(password); 37 | this.loginButton.click(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} %-5level [%15.15t] %cyan(%-30.30logger{30}) : %m%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/java/com/vinsguru/listener/TestListener.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.listener; 2 | 3 | import com.vinsguru.util.Constants; 4 | import org.openqa.selenium.OutputType; 5 | import org.openqa.selenium.TakesScreenshot; 6 | import org.testng.ITestListener; 7 | import org.testng.ITestResult; 8 | import org.testng.Reporter; 9 | 10 | public class TestListener implements ITestListener { 11 | 12 | @Override 13 | public void onTestFailure(ITestResult result) { 14 | TakesScreenshot driver = (TakesScreenshot) result.getTestContext().getAttribute(Constants.DRIVER); 15 | String screenshot = driver.getScreenshotAs(OutputType.BASE64); 16 | String htmlImageFormat = ""; 17 | String htmlImage = String.format(htmlImageFormat, screenshot); 18 | Reporter.log(htmlImage); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/java/com/vinsguru/tests/flightreservation/model/FlightReservationTestData.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.tests.flightreservation.model; 2 | 3 | public record FlightReservationTestData(String firstName, 4 | String lastName, 5 | String email, 6 | String password, 7 | String street, 8 | String city, 9 | String zip, 10 | String passengersCount, 11 | String expectedPrice) { 12 | } 13 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/java/com/vinsguru/util/Config.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.InputStream; 7 | import java.util.Properties; 8 | 9 | public class Config { 10 | 11 | private static final Logger log = LoggerFactory.getLogger(Config.class); 12 | private static final String DEFAULT_PROPERTIES = "config/default.properties"; 13 | private static Properties properties; 14 | 15 | public static void initialize(){ 16 | 17 | // load default properties 18 | properties = loadProperties(); 19 | 20 | // check for any override 21 | for(String key: properties.stringPropertyNames()){ 22 | if(System.getProperties().containsKey(key)){ 23 | properties.setProperty(key, System.getProperty(key)); 24 | } 25 | } 26 | 27 | // print 28 | log.info("Test Properties"); 29 | log.info("-----------------"); 30 | for(String key: properties.stringPropertyNames()){ 31 | log.info("{}={}", key, properties.getProperty(key)); 32 | } 33 | log.info("-----------------"); 34 | 35 | } 36 | 37 | public static String get(String key){ 38 | return properties.getProperty(key); 39 | } 40 | 41 | private static Properties loadProperties(){ 42 | Properties properties = new Properties(); 43 | try(InputStream stream = ResourceLoader.getResource(DEFAULT_PROPERTIES)){ 44 | properties.load(stream); 45 | }catch (Exception e){ 46 | log.error("unable to read the property file {}", DEFAULT_PROPERTIES, e); 47 | } 48 | return properties; 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/java/com/vinsguru/util/Constants.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | public class Constants { 4 | 5 | public static final String GRID_ENABLED = "selenium.grid.enabled"; 6 | public static final String GRID_URL_FORMAT = "selenium.grid.urlFormat"; 7 | public static final String GRID_HUB_HOST = "selenium.grid.hubHost"; 8 | 9 | public static final String BROWSER = "browser"; 10 | public static final String CHROME = "chrome"; 11 | public static final String FIREFOX = "firefox"; 12 | public static final String DRIVER = "driver"; 13 | 14 | public static final String FLIGHT_RESERVATION_URL = "flightReservation.url"; 15 | public static final String VENDOR_PORTAL_URL = "vendorPortal.url"; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/java/com/vinsguru/util/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.vinsguru.tests.vendorportal.model.VendorPortalTestData; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.InputStream; 9 | 10 | public class JsonUtil { 11 | 12 | private static final Logger log = LoggerFactory.getLogger(JsonUtil.class); 13 | private static final ObjectMapper mapper = new ObjectMapper(); 14 | 15 | public static T getTestData(String path, Class type){ 16 | try(InputStream stream = ResourceLoader.getResource(path)){ 17 | return mapper.readValue(stream, type); 18 | }catch (Exception e){ 19 | log.error("unable to read test data {}", path, e); 20 | } 21 | return null; 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/java/com/vinsguru/util/ResourceLoader.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.InputStream; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.util.Objects; 10 | 11 | /* 12 | A simple utility to read file. 13 | first we check the classpath. if found, it is used. 14 | if not, then we check the filesystem 15 | */ 16 | public class ResourceLoader { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(ResourceLoader.class); 19 | 20 | public static InputStream getResource(String path) throws Exception { 21 | log.info("reading resource from location: {}", path); 22 | InputStream stream = ResourceLoader.class.getClassLoader().getResourceAsStream(path); 23 | if(Objects.nonNull(stream)){ 24 | return stream; 25 | } 26 | return Files.newInputStream(Path.of(path)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/resources/config/default.properties: -------------------------------------------------------------------------------- 1 | # selenium grid 2 | selenium.grid.enabled=false 3 | selenium.grid.urlFormat=http://%s:4444/wd/hub 4 | selenium.grid.hubHost=localhost 5 | 6 | # browser 7 | browser=chrome 8 | 9 | # application 10 | flightReservation.url=https://d1uh9e7cu07ukd.cloudfront.net/selenium-docker/reservation-app/index.html 11 | vendorPortal.url=https://d1uh9e7cu07ukd.cloudfront.net/selenium-docker/vendor-app/index.html -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "michael", 3 | "lastName": "jackson", 4 | "email": "mj@pop.com", 5 | "password": "mj", 6 | "street": "123 main street", 7 | "city": "atlanta", 8 | "zip": "30001", 9 | "passengersCount": "1", 10 | "expectedPrice": "$584 USD" 11 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "marshall", 3 | "lastName": "mathers", 4 | "email": "eminem@hiphop.com", 5 | "password": "m&m", 6 | "street": "456 main street", 7 | "city": "detroit", 8 | "zip": "40001", 9 | "passengersCount": "2", 10 | "expectedPrice": "$1169 USD" 11 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "cheb", 3 | "lastName": "khaled", 4 | "email": "khaled@rai.com", 5 | "password": "didi", 6 | "street": "101 non main street", 7 | "city": "las vegas", 8 | "zip": "50001", 9 | "passengersCount": "3", 10 | "expectedPrice": "$1753 USD" 11 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "dr", 3 | "lastName": "dre", 4 | "email": "dr@dre.com", 5 | "password": "dre", 6 | "street": "455 main street", 7 | "city": "detroit", 8 | "zip": "40001", 9 | "passengersCount": "4", 10 | "expectedPrice": "$2338 USD" 11 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/resources/test-data/vendor-portal/john.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "john", 3 | "password": "john", 4 | "monthlyEarning": "$3,453", 5 | "annualEarning": "$34,485", 6 | "profitMargin": "-16%", 7 | "availableInventory": "67", 8 | "searchKeyword": "2024/01/01", 9 | "searchResultsCount": 0 10 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/resources/test-data/vendor-portal/mike.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "mike", 3 | "password": "mike", 4 | "monthlyEarning": "$55,000", 5 | "annualEarning": "$563,300", 6 | "profitMargin": "80%", 7 | "availableInventory": "45", 8 | "searchKeyword": "miami", 9 | "searchResultsCount": 10 10 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/resources/test-data/vendor-portal/sam.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "sam", 3 | "password": "sam", 4 | "monthlyEarning": "$40,000", 5 | "annualEarning": "$215,000", 6 | "profitMargin": "50%", 7 | "availableInventory": "18", 8 | "searchKeyword": "adams", 9 | "searchResultsCount": 8 10 | } -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/resources/test-suites/flight-reservation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /06-jenkins-ci-cd/selenium-docker/src/test/resources/test-suites/vendor-portal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /07-aws/01-grid-and-test-suites/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | hub: 3 | image: selenium/hub:4.32 4 | ports: 5 | - 4444:4444 6 | chrome: 7 | image: selenium/node-chromium:4.32 8 | shm_size: '1g' 9 | depends_on: 10 | - hub 11 | environment: 12 | - SE_EVENT_BUS_HOST=hub 13 | - SE_EVENT_BUS_PUBLISH_PORT=4442 14 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 15 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 16 | - SE_NODE_MAX_SESSIONS=1 17 | firefox: 18 | image: selenium/node-firefox:4.32 19 | shm_size: '1g' 20 | depends_on: 21 | - hub 22 | environment: 23 | - SE_EVENT_BUS_HOST=hub 24 | - SE_EVENT_BUS_PUBLISH_PORT=4442 25 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 26 | - SE_NODE_OVERRIDE_MAX_SESSIONS=true 27 | - SE_NODE_MAX_SESSIONS=1 28 | vendor-portal: 29 | image: vinsdocker/selenium 30 | depends_on: 31 | - chrome 32 | environment: 33 | - BROWSER=chrome 34 | - HUB_HOST=hub 35 | - THREAD_COUNT=1 36 | - TEST_SUITE=vendor-portal.xml 37 | volumes: 38 | - ./output/vendor-portal:/home/selenium-docker/test-output 39 | flight-reservation: 40 | image: vinsdocker/selenium 41 | depends_on: 42 | - firefox 43 | environment: 44 | - BROWSER=firefox 45 | - HUB_HOST=hub 46 | - THREAD_COUNT=1 47 | - TEST_SUITE=flight-reservation.xml 48 | volumes: 49 | - ./output/flight-reservation:/home/selenium-docker/test-output -------------------------------------------------------------------------------- /07-aws/02-aws-runner/.env: -------------------------------------------------------------------------------- 1 | SE_EVENT_BUS_HOST=hub 2 | SE_EVENT_BUS_PUBLISH_PORT=4442 3 | SE_EVENT_BUS_SUBSCRIBE_PORT=4443 4 | SE_NODE_OVERRIDE_MAX_SESSIONS=true 5 | SE_NODE_MAX_SESSIONS=2 -------------------------------------------------------------------------------- /07-aws/02-aws-runner/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline{ 2 | 3 | agent any 4 | 5 | parameters { 6 | choice choices: ['chrome', 'firefox'], description: 'Select the browser', name: 'BROWSER' 7 | } 8 | 9 | stages{ 10 | 11 | stage('Start Grid'){ 12 | steps{ 13 | sh "docker-compose -f grid.yaml up --scale ${params.BROWSER}=1 -d" 14 | } 15 | } 16 | 17 | stage('Run Test'){ 18 | steps{ 19 | sh "docker-compose -f test-suites.yaml up --pull=always" 20 | script { 21 | if(fileExists('output/flight-reservation/testng-failed.xml') || fileExists('output/vendor-portal/testng-failed.xml')){ 22 | error('failed tests found') 23 | } 24 | } 25 | } 26 | } 27 | 28 | } 29 | 30 | post { 31 | always { 32 | sh "docker-compose -f grid.yaml down" 33 | sh "docker-compose -f test-suites.yaml down" 34 | archiveArtifacts artifacts: 'output/flight-reservation/emailable-report.html', followSymlinks: false 35 | archiveArtifacts artifacts: 'output/vendor-portal/emailable-report.html', followSymlinks: false 36 | } 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /07-aws/02-aws-runner/grid.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | hub: 3 | image: selenium/hub:4.32 4 | chrome: 5 | image: selenium/node-chromium:4.32 6 | shm_size: '1g' 7 | depends_on: 8 | - hub 9 | deploy: 10 | replicas: 0 11 | env_file: .env 12 | firefox: 13 | image: selenium/node-firefox:4.32 14 | shm_size: '1g' 15 | depends_on: 16 | - hub 17 | deploy: 18 | replicas: 0 19 | env_file: .env -------------------------------------------------------------------------------- /07-aws/02-aws-runner/test-suites.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | vendor-portal: 3 | image: vinsdocker/selenium 4 | environment: 5 | - BROWSER 6 | - HUB_HOST=hub 7 | - THREAD_COUNT=1 8 | - TEST_SUITE=vendor-portal.xml 9 | volumes: 10 | - ./output/vendor-portal:/home/selenium-docker/test-output 11 | flight-reservation: 12 | image: vinsdocker/selenium 13 | environment: 14 | - BROWSER 15 | - HUB_HOST=hub 16 | - THREAD_COUNT=1 17 | - TEST_SUITE=flight-reservation.xml 18 | volumes: 19 | - ./output/flight-reservation:/home/selenium-docker/test-output -------------------------------------------------------------------------------- /07-aws/Readme.md: -------------------------------------------------------------------------------- 1 | # AMI Setup 2 | 3 | ## docker-compose install 4 | - [Reference](https://github.com/docker/compose/releases) 5 | - ARM: 6 | 7 | `sudo curl -SL https://github.com/docker/compose/releases/download/v2.21.0/docker-compose-linux-aarch64 -o /usr/bin/docker-compose` 8 | 9 | - X86: 10 | 11 | `sudo curl -SL https://github.com/docker/compose/releases/download/v2.21.0/docker-compose-linux-x86_64 -o /usr/bin/docker-compose` 12 | 13 | ## Make it executable 14 | `sudo chmod +x /usr/bin/docker-compose` 15 | 16 | ## Instal Java 17 | `sudo apt install openjdk-17-jre-headless -y` 18 | 19 | ## Run docker without sudo 20 | `sudo usermod -aG docker $USER` -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | **/*.class 5 | 6 | # Log file 7 | **/*.log 8 | 9 | # BlueJ files 10 | **/*.ctxt 11 | 12 | # Mobile Tools for Java (J2ME) 13 | **/.mtj.tmp/ 14 | 15 | # Package Files # 16 | **/*.jar 17 | **/*.war 18 | **/*.nar 19 | **/*.ear 20 | **/*.zip 21 | **/*.tar.gz 22 | **/*.rar 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | **/hs_err_pid* 26 | 27 | ### Maven template 28 | **/target/ 29 | **/pom.xml.tag 30 | **/pom.xml.releaseBackup 31 | **/pom.xml.versionsBackup 32 | **/pom.xml.next 33 | **/release.properties 34 | **/dependency-reduced-pom.xml 35 | **/buildNumber.properties 36 | **/.mvn/timing.properties 37 | **/.mvn/wrapper/maven-wrapper.jar 38 | 39 | **/*.iml 40 | 41 | **/.idea/ 42 | 43 | 44 | **/HELP.md 45 | **/.mvn/ 46 | **/mvnw 47 | **/mvnw.cmd 48 | **/node_modules/ 49 | 50 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM bellsoft/liberica-openjdk-alpine:21 2 | 3 | # Install curl jq 4 | RUN apk add curl jq 5 | 6 | # workspace 7 | WORKDIR /home/selenium-docker 8 | 9 | # Add the required files 10 | ADD target/docker-resources ./ 11 | ADD runner.sh runner.sh 12 | 13 | # Start the runner.sh 14 | ENTRYPOINT sh runner.sh -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline{ 2 | 3 | agent any 4 | 5 | stages{ 6 | 7 | stage('Build Jar'){ 8 | steps{ 9 | sh 'mvn clean package -DskipTests' 10 | } 11 | } 12 | 13 | stage('Build Image'){ 14 | steps{ 15 | sh 'docker build -t=vinsdocker/selenium:latest .' 16 | } 17 | } 18 | 19 | stage('Push Image'){ 20 | environment{ 21 | DOCKER_HUB = credentials('dockerhub-creds') 22 | } 23 | steps{ 24 | sh 'echo ${DOCKER_HUB_PSW} | docker login -u ${DOCKER_HUB_USR} --password-stdin' 25 | sh 'docker push vinsdocker/selenium:latest' 26 | sh "docker tag vinsdocker/selenium:latest vinsdocker/selenium:${env.BUILD_NUMBER}" 27 | sh "docker push vinsdocker/selenium:${env.BUILD_NUMBER}" 28 | } 29 | } 30 | 31 | } 32 | 33 | post { 34 | always { 35 | sh 'docker logout' 36 | } 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/runner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #------------------------------------------------------------------- 4 | # This script expects the following environment variables 5 | # HUB_HOST 6 | # BROWSER 7 | # THREAD_COUNT 8 | # TEST_SUITE 9 | #------------------------------------------------------------------- 10 | 11 | # Let's print what we have received 12 | echo "-------------------------------------------" 13 | echo "HUB_HOST : ${HUB_HOST:-hub}" 14 | echo "BROWSER : ${BROWSER:-chrome}" 15 | echo "THREAD_COUNT : ${THREAD_COUNT:-1}" 16 | echo "TEST_SUITE : ${TEST_SUITE}" 17 | echo "-------------------------------------------" 18 | 19 | # Do not start the tests immediately. Hub has to be ready with browser nodes 20 | echo "Checking if hub is ready..!" 21 | count=0 22 | while [ "$( curl -s http://${HUB_HOST:-hub}:4444/status | jq -r .value.ready )" != "true" ] 23 | do 24 | count=$((count+1)) 25 | echo "Attempt: ${count}" 26 | if [ "$count" -ge 30 ] 27 | then 28 | echo "**** HUB IS NOT READY WITHIN 30 SECONDS ****" 29 | exit 1 30 | fi 31 | sleep 1 32 | done 33 | 34 | # At this point, selenium grid should be up! 35 | echo "Selenium Grid is up and running. Running the test...." 36 | 37 | # Start the java command 38 | java -cp 'libs/*' \ 39 | -Dselenium.grid.enabled=true \ 40 | -Dselenium.grid.hubHost="${HUB_HOST:-hub}" \ 41 | -Dbrowser="${BROWSER:-chrome}" \ 42 | org.testng.TestNG \ 43 | -threadcount "${THREAD_COUNT:-1}" \ 44 | test-suites/"${TEST_SUITE}" -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/main/java/com/vinsguru/pages/AbstractPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.support.PageFactory; 5 | import org.openqa.selenium.support.ui.WebDriverWait; 6 | 7 | import java.time.Duration; 8 | 9 | public abstract class AbstractPage { 10 | 11 | protected final WebDriver driver; 12 | protected final WebDriverWait wait; 13 | 14 | public AbstractPage(WebDriver driver){ 15 | this.driver = driver; 16 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 17 | PageFactory.initElements(driver, this); 18 | } 19 | 20 | public abstract boolean isAt(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | public class FlightConfirmationPage extends AbstractPage { 12 | 13 | private static final Logger log = LoggerFactory.getLogger(FlightConfirmationPage.class); 14 | 15 | @FindBy(css = "#flights-confirmation-section .card-body .row:nth-child(1) .col:nth-child(2)") 16 | private WebElement flightConfirmationElement; 17 | 18 | @FindBy(css = "#flights-confirmation-section .card-body .row:nth-child(3) .col:nth-child(2)") 19 | private WebElement totalPriceElement; 20 | 21 | public FlightConfirmationPage(WebDriver driver) { 22 | super(driver); 23 | } 24 | 25 | @Override 26 | public boolean isAt() { 27 | this.wait.until(ExpectedConditions.visibilityOf(this.flightConfirmationElement)); 28 | return this.flightConfirmationElement.isDisplayed(); 29 | } 30 | 31 | public String getPrice(){ 32 | String confirmation = this.flightConfirmationElement.getText(); 33 | String price = this.totalPriceElement.getText(); 34 | log.info("Flight confirmation# : {}", confirmation); 35 | log.info("Total price : {}", price); 36 | return price; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightsSearchPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.Select; 9 | 10 | public class FlightsSearchPage extends AbstractPage { 11 | 12 | @FindBy(id = "passengers") 13 | private WebElement passengerSelect; 14 | 15 | @FindBy(id = "search-flights") 16 | private WebElement searchFlightsButton; 17 | 18 | public FlightsSearchPage(WebDriver driver) { 19 | super(driver); 20 | } 21 | 22 | @Override 23 | public boolean isAt() { 24 | this.wait.until(ExpectedConditions.visibilityOf(this.passengerSelect)); 25 | return this.passengerSelect.isDisplayed(); 26 | } 27 | 28 | public void selectPassengers(String noOfPassengers){ 29 | Select passengers = new Select(this.passengerSelect); 30 | passengers.selectByValue(noOfPassengers); 31 | } 32 | 33 | public void searchFlights(){ 34 | this.searchFlightsButton.click(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/FlightsSelectionPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | import java.util.List; 10 | import java.util.concurrent.ThreadLocalRandom; 11 | 12 | public class FlightsSelectionPage extends AbstractPage { 13 | 14 | @FindBy(name = "departure-flight") 15 | private List departureFlightsOptions; 16 | 17 | @FindBy(name = "arrival-flight") 18 | private List arrivalFlightsOptions; 19 | 20 | @FindBy(id = "confirm-flights") 21 | private WebElement confirmFlightsButton; 22 | 23 | public FlightsSelectionPage(WebDriver driver) { 24 | super(driver); 25 | } 26 | 27 | @Override 28 | public boolean isAt() { 29 | this.wait.until(ExpectedConditions.visibilityOf(this.confirmFlightsButton)); 30 | return this.confirmFlightsButton.isDisplayed(); 31 | } 32 | 33 | public void selectFlights(){ 34 | int random = ThreadLocalRandom.current().nextInt(0, departureFlightsOptions.size()); 35 | this.departureFlightsOptions.get(random).click(); 36 | this.arrivalFlightsOptions.get(random).click(); 37 | } 38 | 39 | public void confirmFlights(){ 40 | this.confirmFlightsButton.click(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/main/java/com/vinsguru/pages/flightreservation/RegistrationConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.flightreservation; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | public class RegistrationConfirmationPage extends AbstractPage { 10 | 11 | @FindBy(id = "go-to-flights-search") 12 | private WebElement goToFlightsSearchButton; 13 | 14 | @FindBy(css = "#registration-confirmation-section p b") 15 | private WebElement firstNameElement; 16 | 17 | public RegistrationConfirmationPage(WebDriver driver){ 18 | super(driver); 19 | } 20 | 21 | @Override 22 | public boolean isAt() { 23 | this.wait.until(ExpectedConditions.visibilityOf(this.goToFlightsSearchButton)); 24 | return this.goToFlightsSearchButton.isDisplayed(); 25 | } 26 | 27 | public String getFirstName(){ 28 | return this.firstNameElement.getText(); 29 | } 30 | 31 | public void goToFlightsSearch(){ 32 | this.goToFlightsSearchButton.click(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/main/java/com/vinsguru/pages/vendorportal/LoginPage.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.pages.vendorportal; 2 | 3 | import com.vinsguru.pages.AbstractPage; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | 9 | public class LoginPage extends AbstractPage { 10 | 11 | @FindBy(id = "username") 12 | private WebElement usernameInput; 13 | 14 | @FindBy(id = "password") 15 | private WebElement passwordInput; 16 | 17 | @FindBy(id = "login") 18 | private WebElement loginButton; 19 | 20 | public LoginPage(WebDriver driver) { 21 | super(driver); 22 | } 23 | 24 | @Override 25 | public boolean isAt() { 26 | this.wait.until(ExpectedConditions.visibilityOf(this.loginButton)); 27 | return this.loginButton.isDisplayed(); 28 | } 29 | 30 | public void goTo(String url){ 31 | this.driver.get(url); 32 | } 33 | 34 | public void login(String username, String password){ 35 | this.usernameInput.sendKeys(username); 36 | this.passwordInput.sendKeys(password); 37 | this.loginButton.click(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} %-5level [%15.15t] %cyan(%-30.30logger{30}) : %m%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/java/com/vinsguru/listener/TestListener.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.listener; 2 | 3 | import com.vinsguru.util.Constants; 4 | import org.openqa.selenium.OutputType; 5 | import org.openqa.selenium.TakesScreenshot; 6 | import org.testng.ITestListener; 7 | import org.testng.ITestResult; 8 | import org.testng.Reporter; 9 | 10 | public class TestListener implements ITestListener { 11 | 12 | @Override 13 | public void onTestFailure(ITestResult result) { 14 | TakesScreenshot driver = (TakesScreenshot) result.getTestContext().getAttribute(Constants.DRIVER); 15 | String screenshot = driver.getScreenshotAs(OutputType.BASE64); 16 | String htmlImageFormat = ""; 17 | String htmlImage = String.format(htmlImageFormat, screenshot); 18 | Reporter.log(htmlImage); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/java/com/vinsguru/tests/flightreservation/model/FlightReservationTestData.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.tests.flightreservation.model; 2 | 3 | public record FlightReservationTestData(String firstName, 4 | String lastName, 5 | String email, 6 | String password, 7 | String street, 8 | String city, 9 | String zip, 10 | String passengersCount, 11 | String expectedPrice) { 12 | } 13 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/java/com/vinsguru/util/Config.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.InputStream; 7 | import java.util.Properties; 8 | 9 | public class Config { 10 | 11 | private static final Logger log = LoggerFactory.getLogger(Config.class); 12 | private static final String DEFAULT_PROPERTIES = "config/default.properties"; 13 | private static Properties properties; 14 | 15 | public static void initialize(){ 16 | 17 | // load default properties 18 | properties = loadProperties(); 19 | 20 | // check for any override 21 | for(String key: properties.stringPropertyNames()){ 22 | if(System.getProperties().containsKey(key)){ 23 | properties.setProperty(key, System.getProperty(key)); 24 | } 25 | } 26 | 27 | // print 28 | log.info("Test Properties"); 29 | log.info("-----------------"); 30 | for(String key: properties.stringPropertyNames()){ 31 | log.info("{}={}", key, properties.getProperty(key)); 32 | } 33 | log.info("-----------------"); 34 | 35 | } 36 | 37 | public static String get(String key){ 38 | return properties.getProperty(key); 39 | } 40 | 41 | private static Properties loadProperties(){ 42 | Properties properties = new Properties(); 43 | try(InputStream stream = ResourceLoader.getResource(DEFAULT_PROPERTIES)){ 44 | properties.load(stream); 45 | }catch (Exception e){ 46 | log.error("unable to read the property file {}", DEFAULT_PROPERTIES, e); 47 | } 48 | return properties; 49 | } 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/java/com/vinsguru/util/Constants.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | public class Constants { 4 | 5 | public static final String GRID_ENABLED = "selenium.grid.enabled"; 6 | public static final String GRID_URL_FORMAT = "selenium.grid.urlFormat"; 7 | public static final String GRID_HUB_HOST = "selenium.grid.hubHost"; 8 | 9 | public static final String BROWSER = "browser"; 10 | public static final String CHROME = "chrome"; 11 | public static final String FIREFOX = "firefox"; 12 | public static final String DRIVER = "driver"; 13 | 14 | public static final String FLIGHT_RESERVATION_URL = "flightReservation.url"; 15 | public static final String VENDOR_PORTAL_URL = "vendorPortal.url"; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/java/com/vinsguru/util/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.vinsguru.tests.vendorportal.model.VendorPortalTestData; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.InputStream; 9 | 10 | public class JsonUtil { 11 | 12 | private static final Logger log = LoggerFactory.getLogger(JsonUtil.class); 13 | private static final ObjectMapper mapper = new ObjectMapper(); 14 | 15 | public static T getTestData(String path, Class type){ 16 | try(InputStream stream = ResourceLoader.getResource(path)){ 17 | return mapper.readValue(stream, type); 18 | }catch (Exception e){ 19 | log.error("unable to read test data {}", path, e); 20 | } 21 | return null; 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/java/com/vinsguru/util/ResourceLoader.java: -------------------------------------------------------------------------------- 1 | package com.vinsguru.util; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.InputStream; 7 | import java.nio.file.Files; 8 | import java.nio.file.Path; 9 | import java.util.Objects; 10 | 11 | /* 12 | A simple utility to read file. 13 | first we check the classpath. if found, it is used. 14 | if not, then we check the filesystem 15 | */ 16 | public class ResourceLoader { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(ResourceLoader.class); 19 | 20 | public static InputStream getResource(String path) throws Exception { 21 | log.info("reading resource from location: {}", path); 22 | InputStream stream = ResourceLoader.class.getClassLoader().getResourceAsStream(path); 23 | if(Objects.nonNull(stream)){ 24 | return stream; 25 | } 26 | return Files.newInputStream(Path.of(path)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/resources/config/default.properties: -------------------------------------------------------------------------------- 1 | # selenium grid 2 | selenium.grid.enabled=false 3 | selenium.grid.urlFormat=http://%s:4444/wd/hub 4 | selenium.grid.hubHost=localhost 5 | 6 | # browser 7 | browser=chrome 8 | 9 | # application 10 | flightReservation.url=https://d1uh9e7cu07ukd.cloudfront.net/selenium-docker/reservation-app/index.html 11 | vendorPortal.url=https://d1uh9e7cu07ukd.cloudfront.net/selenium-docker/vendor-app/index.html -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "michael", 3 | "lastName": "jackson", 4 | "email": "mj@pop.com", 5 | "password": "mj", 6 | "street": "123 main street", 7 | "city": "atlanta", 8 | "zip": "30001", 9 | "passengersCount": "1", 10 | "expectedPrice": "$584 USD" 11 | } -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "marshall", 3 | "lastName": "mathers", 4 | "email": "eminem@hiphop.com", 5 | "password": "m&m", 6 | "street": "456 main street", 7 | "city": "detroit", 8 | "zip": "40001", 9 | "passengersCount": "2", 10 | "expectedPrice": "$1169 USD" 11 | } -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "cheb", 3 | "lastName": "khaled", 4 | "email": "khaled@rai.com", 5 | "password": "didi", 6 | "street": "101 non main street", 7 | "city": "las vegas", 8 | "zip": "50001", 9 | "passengersCount": "3", 10 | "expectedPrice": "$1753 USD" 11 | } -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/resources/test-data/flight-reservation/passenger-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "dr", 3 | "lastName": "dre", 4 | "email": "dr@dre.com", 5 | "password": "dre", 6 | "street": "455 main street", 7 | "city": "detroit", 8 | "zip": "40001", 9 | "passengersCount": "4", 10 | "expectedPrice": "$2338 USD" 11 | } -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/resources/test-data/vendor-portal/john.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "john", 3 | "password": "john", 4 | "monthlyEarning": "$3,453", 5 | "annualEarning": "$34,485", 6 | "profitMargin": "-16%", 7 | "availableInventory": "67", 8 | "searchKeyword": "2024/01/01", 9 | "searchResultsCount": 0 10 | } -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/resources/test-data/vendor-portal/mike.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "mike", 3 | "password": "mike", 4 | "monthlyEarning": "$55,000", 5 | "annualEarning": "$563,300", 6 | "profitMargin": "80%", 7 | "availableInventory": "45", 8 | "searchKeyword": "miami", 9 | "searchResultsCount": 10 10 | } -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/resources/test-data/vendor-portal/sam.json: -------------------------------------------------------------------------------- 1 | { 2 | "username": "sam", 3 | "password": "sam", 4 | "monthlyEarning": "$40,000", 5 | "annualEarning": "$215,000", 6 | "profitMargin": "50%", 7 | "availableInventory": "18", 8 | "searchKeyword": "adams", 9 | "searchResultsCount": 8 10 | } -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/resources/test-suites/flight-reservation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /08-final-projects/selenium-docker/src/test/resources/test-suites/vendor-portal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /09-old-projects/01-original-project/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8u191-jre-alpine3.8 2 | 3 | RUN apk add curl jq 4 | 5 | # Workspace 6 | WORKDIR /usr/share/udemy 7 | 8 | # ADD .jar under target from host 9 | # into this image 10 | ADD target/selenium-docker.jar selenium-docker.jar 11 | ADD target/selenium-docker-tests.jar selenium-docker-tests.jar 12 | ADD target/libs libs 13 | 14 | # in case of any other dependency like .csv / .json / .xls 15 | # please ADD that as well 16 | 17 | # ADD suite files 18 | ADD book-flight-module.xml book-flight-module.xml 19 | ADD search-module.xml search-module.xml 20 | 21 | # ADD health check script 22 | ADD healthcheck.sh healthcheck.sh 23 | 24 | # BROWSER 25 | # HUB_HOST 26 | # MODULE 27 | 28 | ENTRYPOINT sh healthcheck.sh -------------------------------------------------------------------------------- /09-old-projects/01-original-project/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent none 3 | stages { 4 | stage('Build Jar') { 5 | agent { 6 | docker { 7 | image 'maven:3-alpine' 8 | args '-v $HOME/.m2:/root/.m2' 9 | } 10 | } 11 | steps { 12 | sh 'mvn clean package -DskipTests' 13 | } 14 | } 15 | stage('Build Image') { 16 | steps { 17 | script { 18 | app = docker.build("vinsdocker/selenium-docker") 19 | } 20 | } 21 | } 22 | stage('Push Image') { 23 | steps { 24 | script { 25 | docker.withRegistry('https://registry.hub.docker.com', 'dockerhub') { 26 | app.push("${BUILD_NUMBER}") 27 | app.push("latest") 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /09-old-projects/01-original-project/book-flight-module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /09-old-projects/01-original-project/healthcheck.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Environment Variables 3 | # HUB_HOST 4 | # BROWSER 5 | # MODULE 6 | 7 | echo "Checking if hub is ready - $HUB_HOST" 8 | 9 | while [ "$( curl -s http://$HUB_HOST:4444/wd/hub/status | jq -r .value.ready )" != "true" ] 10 | do 11 | sleep 1 12 | done 13 | 14 | # start the java command 15 | java -cp selenium-docker.jar:selenium-docker-tests.jar:libs/* \ 16 | -DHUB_HOST=$HUB_HOST \ 17 | -DBROWSER=$BROWSER \ 18 | org.testng.TestNG $MODULE -------------------------------------------------------------------------------- /09-old-projects/01-original-project/search-module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /09-old-projects/01-original-project/src/main/java/com/newtours/pages/FindFlightPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.WebDriverWait; 9 | 10 | public class FindFlightPage { 11 | 12 | private WebDriver driver; 13 | private WebDriverWait wait; 14 | 15 | @FindBy(name = "reserveFlights") 16 | private WebElement firstSubmitBtn; 17 | 18 | @FindBy(name = "buyFlights") 19 | private WebElement secondSubmitBtn; 20 | 21 | public FindFlightPage(WebDriver driver){ 22 | this.driver = driver; 23 | this.wait = new WebDriverWait(driver, 30); 24 | PageFactory.initElements(driver, this); 25 | } 26 | 27 | public void submitFindFlightPage(){ 28 | this.wait.until(ExpectedConditions.elementToBeClickable(this.firstSubmitBtn)); 29 | this.firstSubmitBtn.click(); 30 | } 31 | 32 | public void goToFlightConfirmationPage(){ 33 | this.wait.until(ExpectedConditions.elementToBeClickable(this.secondSubmitBtn)); 34 | this.secondSubmitBtn.click(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /09-old-projects/01-original-project/src/main/java/com/newtours/pages/FlightConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.WebDriverWait; 9 | 10 | import java.util.List; 11 | 12 | public class FlightConfirmationPage { 13 | 14 | private WebDriver driver; 15 | private WebDriverWait wait; 16 | 17 | @FindBy(xpath = "//font[contains(text(), 'Confirmation')]") 18 | private WebElement flightConfirmationHeader; 19 | 20 | @FindBy(xpath = "//font[contains(text(), 'USD')]") 21 | private List prices; 22 | 23 | @FindBy(linkText = "SIGN-OFF") 24 | private WebElement signOffLink; 25 | 26 | public FlightConfirmationPage(WebDriver driver){ 27 | this.driver = driver; 28 | this.wait = new WebDriverWait(driver, 30); 29 | PageFactory.initElements(driver, this); 30 | } 31 | 32 | public String getPrice(){ 33 | this.wait.until(ExpectedConditions.visibilityOf(this.flightConfirmationHeader)); 34 | System.out.println(this.flightConfirmationHeader.getText()); 35 | System.out.println(this.prices.get(1).getText()); 36 | String price = this.prices.get(1).getText(); 37 | this.signOffLink.click(); 38 | return price; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /09-old-projects/01-original-project/src/main/java/com/newtours/pages/FlightDetailsPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.Select; 9 | import org.openqa.selenium.support.ui.WebDriverWait; 10 | 11 | public class FlightDetailsPage { 12 | 13 | private WebDriver driver; 14 | private WebDriverWait wait; 15 | 16 | @FindBy(name = "passCount") 17 | private WebElement passengers; 18 | 19 | @FindBy(name = "findFlights") 20 | private WebElement submitBtn; 21 | 22 | public FlightDetailsPage(WebDriver driver){ 23 | this.driver = driver; 24 | this.wait = new WebDriverWait(driver, 30); 25 | PageFactory.initElements(driver, this); 26 | } 27 | 28 | public void selectPassengers(String noOfPassengers){ 29 | this.wait.until(ExpectedConditions.elementToBeClickable(passengers)); 30 | Select select = new Select(passengers); 31 | select.selectByValue(noOfPassengers); 32 | } 33 | 34 | public void goToFindFlightsPage(){ 35 | this.submitBtn.click(); 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /09-old-projects/01-original-project/src/main/java/com/newtours/pages/RegistrationConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.WebDriverWait; 9 | 10 | public class RegistrationConfirmationPage { 11 | 12 | private WebDriver driver; 13 | private WebDriverWait wait; 14 | 15 | @FindBy(partialLinkText = "sign-in") 16 | private WebElement signinLink; 17 | 18 | @FindBy(linkText = "Flights") 19 | private WebElement flightsLink; 20 | 21 | public RegistrationConfirmationPage(WebDriver driver){ 22 | this.driver = driver; 23 | this.wait = new WebDriverWait(driver, 30); 24 | PageFactory.initElements(driver, this); 25 | } 26 | 27 | public void goToFlightDetailsPage(){ 28 | this.wait.until(ExpectedConditions.visibilityOf(this.signinLink)); 29 | this.flightsLink.click(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /09-old-projects/01-original-project/src/main/java/com/newtours/pages/RegistrationPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.WebDriverWait; 9 | 10 | public class RegistrationPage { 11 | 12 | private WebDriver driver; 13 | private WebDriverWait wait; 14 | 15 | @FindBy(name = "firstName") 16 | private WebElement firstNameTxt; 17 | 18 | @FindBy(name = "lastName") 19 | private WebElement lastNameTxt; 20 | 21 | @FindBy(name = "email") 22 | private WebElement usernameTxt; 23 | 24 | @FindBy(name = "password") 25 | private WebElement passwordTxt; 26 | 27 | @FindBy(name = "confirmPassword") 28 | private WebElement confirmPasswordTxt; 29 | 30 | @FindBy(name = "register") 31 | private WebElement submitBtn; 32 | 33 | public RegistrationPage(WebDriver driver){ 34 | this.driver = driver; 35 | this.wait = new WebDriverWait(driver, 30); 36 | PageFactory.initElements(driver, this); 37 | } 38 | 39 | public void goTo(){ 40 | this.driver.get("https://vins-udemy.s3.amazonaws.com/docker/docker-book-flight.html"); 41 | this.wait.until(ExpectedConditions.visibilityOf(this.firstNameTxt)); 42 | } 43 | 44 | public void enterUserDetails(String firstName, String lastName){ 45 | this.firstNameTxt.sendKeys(firstName); 46 | this.lastNameTxt.sendKeys(lastName); 47 | } 48 | 49 | public void enterUserCredentials(String username, String password){ 50 | this.usernameTxt.sendKeys(username); 51 | this.passwordTxt.sendKeys(password); 52 | this.confirmPasswordTxt.sendKeys(password); 53 | } 54 | 55 | public void submit(){ 56 | this.submitBtn.click(); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /09-old-projects/01-original-project/src/main/java/com/searchmodule/pages/SearchPage.java: -------------------------------------------------------------------------------- 1 | package com.searchmodule.pages; 2 | 3 | import org.openqa.selenium.By; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.PageFactory; 8 | import org.openqa.selenium.support.ui.ExpectedConditions; 9 | import org.openqa.selenium.support.ui.WebDriverWait; 10 | 11 | import java.util.List; 12 | 13 | public class SearchPage { 14 | 15 | private WebDriver driver; 16 | private WebDriverWait wait; 17 | 18 | @FindBy(name="q") 19 | private WebElement searchTxt; 20 | 21 | @FindBy(id = "search_button_homepage") 22 | private WebElement searchBtn; 23 | 24 | @FindBy(linkText = "Videos") 25 | private WebElement videosLink; 26 | 27 | @FindBy(className = "tile--vid") 28 | private List allVideos; 29 | 30 | public SearchPage(WebDriver driver){ 31 | this.driver = driver; 32 | this.wait = new WebDriverWait(driver, 30); 33 | PageFactory.initElements(driver, this); 34 | } 35 | 36 | public void goTo(){ 37 | this.driver.get("https://duckduckgo.com/"); 38 | } 39 | 40 | public void doSearch(String keyword){ 41 | this.wait.until(ExpectedConditions.visibilityOf(this.searchTxt)); 42 | this.searchTxt.sendKeys(keyword); 43 | this.searchBtn.click(); 44 | } 45 | 46 | public void goToVideos(){ 47 | this.wait.until(ExpectedConditions.visibilityOf(this.videosLink)); 48 | this.videosLink.click(); 49 | } 50 | 51 | public int getResult(){ 52 | By by = By.className("tile--vid"); 53 | this.wait.until(ExpectedConditions.numberOfElementsToBeMoreThan(by, 0)); 54 | System.out.println("Search Result : " + this.allVideos.size()); 55 | return this.allVideos.size(); 56 | } 57 | 58 | 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /09-old-projects/01-original-project/src/test/java/com/searchmodule/tests/SearchTest.java: -------------------------------------------------------------------------------- 1 | package com.searchmodule.tests; 2 | 3 | import com.searchmodule.pages.SearchPage; 4 | import com.tests.BaseTest; 5 | import org.testng.Assert; 6 | import org.testng.annotations.Parameters; 7 | import org.testng.annotations.Test; 8 | 9 | public class SearchTest extends BaseTest { 10 | 11 | @Test 12 | @Parameters({"keyword"}) 13 | public void search(String keyword){ 14 | SearchPage searchPage = new SearchPage(driver); 15 | searchPage.goTo(); 16 | searchPage.doSearch(keyword); 17 | searchPage.goToVideos(); 18 | int size = searchPage.getResult(); 19 | 20 | Assert.assertTrue(size > 0); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /09-old-projects/01-original-project/src/test/java/com/tests/BaseTest.java: -------------------------------------------------------------------------------- 1 | package com.tests; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.remote.DesiredCapabilities; 5 | import org.openqa.selenium.remote.RemoteWebDriver; 6 | import org.testng.ITestContext; 7 | import org.testng.annotations.AfterTest; 8 | import org.testng.annotations.BeforeTest; 9 | 10 | import java.net.MalformedURLException; 11 | import java.net.URL; 12 | 13 | public class BaseTest { 14 | 15 | protected WebDriver driver; 16 | 17 | @BeforeTest 18 | public void setupDriver(ITestContext ctx) throws MalformedURLException { 19 | // BROWSER => chrome / firefox 20 | // HUB_HOST => localhost / 10.0.1.3 / hostname 21 | 22 | String host = "localhost"; 23 | DesiredCapabilities dc; 24 | 25 | if(System.getProperty("BROWSER") != null && 26 | System.getProperty("BROWSER").equalsIgnoreCase("firefox")){ 27 | dc = DesiredCapabilities.firefox(); 28 | }else{ 29 | dc = DesiredCapabilities.chrome(); 30 | } 31 | 32 | if(System.getProperty("HUB_HOST") != null){ 33 | host = System.getProperty("HUB_HOST"); 34 | } 35 | 36 | String testName = ctx.getCurrentXmlTest().getName(); 37 | 38 | String completeUrl = "http://" + host + ":4444/wd/hub"; 39 | dc.setCapability("name", testName); 40 | this.driver = new RemoteWebDriver(new URL(completeUrl), dc); 41 | } 42 | 43 | @AfterTest 44 | public void quitDriver(){ 45 | this.driver.quit(); 46 | } 47 | 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | **/*.class 5 | 6 | # Log file 7 | **/*.log 8 | 9 | # BlueJ files 10 | **/*.ctxt 11 | 12 | # Mobile Tools for Java (J2ME) 13 | **/.mtj.tmp/ 14 | 15 | # Package Files # 16 | **/*.jar 17 | **/*.war 18 | **/*.nar 19 | **/*.ear 20 | **/*.zip 21 | **/*.tar.gz 22 | **/*.rar 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | **/hs_err_pid* 26 | 27 | ### Maven template 28 | **/target/ 29 | **/pom.xml.tag 30 | **/pom.xml.releaseBackup 31 | **/pom.xml.versionsBackup 32 | **/pom.xml.next 33 | **/release.properties 34 | **/dependency-reduced-pom.xml 35 | **/buildNumber.properties 36 | **/.mvn/timing.properties 37 | **/.mvn/wrapper/maven-wrapper.jar 38 | 39 | **/*.iml 40 | 41 | **/.idea/ 42 | 43 | 44 | **/HELP.md 45 | **/.mvn/ 46 | **/mvnw 47 | **/mvnw.cmd 48 | **/node_modules/ -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/Dockerfile: -------------------------------------------------------------------------------- 1 | # updated image for java 17 2 | FROM bellsoft/liberica-openjdk-alpine:17.0.6 3 | 4 | RUN apk add curl jq 5 | 6 | # Workspace 7 | WORKDIR /usr/share/udemy 8 | 9 | # ADD .jar under target from host 10 | # into this image 11 | ADD target/selenium-docker.jar selenium-docker.jar 12 | ADD target/selenium-docker-tests.jar selenium-docker-tests.jar 13 | ADD target/libs libs 14 | 15 | # in case of any other dependency like .csv / .json / .xls 16 | # please ADD that as well 17 | 18 | # ADD suite files 19 | ADD book-flight-module.xml book-flight-module.xml 20 | ADD search-module.xml search-module.xml 21 | 22 | # ADD health check script 23 | ADD healthcheck.sh healthcheck.sh 24 | 25 | # BROWSER 26 | # HUB_HOST 27 | # MODULE 28 | 29 | ENTRYPOINT sh healthcheck.sh -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent none 3 | stages { 4 | stage('Build Jar') { 5 | agent { 6 | docker { 7 | image 'maven:3-alpine' 8 | args '-v $HOME/.m2:/root/.m2' 9 | } 10 | } 11 | steps { 12 | sh 'mvn clean package -DskipTests' 13 | } 14 | } 15 | stage('Build Image') { 16 | steps { 17 | script { 18 | app = docker.build("vinsdocker/selenium-docker") 19 | } 20 | } 21 | } 22 | stage('Push Image') { 23 | steps { 24 | script { 25 | docker.withRegistry('https://registry.hub.docker.com', 'dockerhub') { 26 | app.push("${BUILD_NUMBER}") 27 | app.push("latest") 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/book-flight-module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/dummy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vinsguru/selenium-docker/8f1092e518d2ec7999fdd63b058834722645bb52/09-old-projects/02-selenium-4.8.2-testng/dummy.png -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/healthcheck.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Environment Variables 3 | # HUB_HOST 4 | # BROWSER 5 | # MODULE 6 | 7 | echo "Checking if hub is ready - $HUB_HOST" 8 | 9 | while [ "$( curl -s http://$HUB_HOST:4444/wd/hub/status | jq -r .value.ready )" != "true" ] 10 | do 11 | sleep 1 12 | done 13 | 14 | # start the java command 15 | java -cp selenium-docker.jar:selenium-docker-tests.jar:libs/* \ 16 | -DHUB_HOST=$HUB_HOST \ 17 | -DBROWSER=$BROWSER \ 18 | org.testng.TestNG $MODULE -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/search-module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/src/main/java/com/newtours/pages/FindFlightPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.WebDriverWait; 9 | 10 | import java.time.Duration; 11 | 12 | public class FindFlightPage { 13 | 14 | private WebDriver driver; 15 | private WebDriverWait wait; 16 | 17 | @FindBy(name = "reserveFlights") 18 | private WebElement firstSubmitBtn; 19 | 20 | @FindBy(name = "buyFlights") 21 | private WebElement secondSubmitBtn; 22 | 23 | public FindFlightPage(WebDriver driver){ 24 | this.driver = driver; 25 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 26 | PageFactory.initElements(driver, this); 27 | } 28 | 29 | public void submitFindFlightPage(){ 30 | this.wait.until(ExpectedConditions.elementToBeClickable(this.firstSubmitBtn)); 31 | this.firstSubmitBtn.click(); 32 | } 33 | 34 | public void goToFlightConfirmationPage(){ 35 | this.wait.until(ExpectedConditions.elementToBeClickable(this.secondSubmitBtn)); 36 | this.secondSubmitBtn.click(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/src/main/java/com/newtours/pages/FlightConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.WebDriverWait; 9 | 10 | import java.time.Duration; 11 | import java.util.List; 12 | 13 | public class FlightConfirmationPage { 14 | 15 | private WebDriver driver; 16 | private WebDriverWait wait; 17 | 18 | @FindBy(xpath = "//font[contains(text(), 'Confirmation')]") 19 | private WebElement flightConfirmationHeader; 20 | 21 | @FindBy(xpath = "//font[contains(text(), 'USD')]") 22 | private List prices; 23 | 24 | @FindBy(linkText = "SIGN-OFF") 25 | private WebElement signOffLink; 26 | 27 | public FlightConfirmationPage(WebDriver driver){ 28 | this.driver = driver; 29 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 30 | PageFactory.initElements(driver, this); 31 | } 32 | 33 | public String getPrice(){ 34 | this.wait.until(ExpectedConditions.visibilityOf(this.flightConfirmationHeader)); 35 | System.out.println(this.flightConfirmationHeader.getText()); 36 | System.out.println(this.prices.get(1).getText()); 37 | String price = this.prices.get(1).getText(); 38 | this.signOffLink.click(); 39 | return price; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/src/main/java/com/newtours/pages/FlightDetailsPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.Select; 9 | import org.openqa.selenium.support.ui.WebDriverWait; 10 | 11 | import java.time.Duration; 12 | 13 | public class FlightDetailsPage { 14 | 15 | private WebDriver driver; 16 | private WebDriverWait wait; 17 | 18 | @FindBy(name = "passCount") 19 | private WebElement passengers; 20 | 21 | @FindBy(name = "findFlights") 22 | private WebElement submitBtn; 23 | 24 | public FlightDetailsPage(WebDriver driver){ 25 | this.driver = driver; 26 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 27 | PageFactory.initElements(driver, this); 28 | } 29 | 30 | public void selectPassengers(String noOfPassengers){ 31 | this.wait.until(ExpectedConditions.elementToBeClickable(passengers)); 32 | Select select = new Select(passengers); 33 | select.selectByValue(noOfPassengers); 34 | } 35 | 36 | public void goToFindFlightsPage(){ 37 | this.submitBtn.click(); 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/src/main/java/com/newtours/pages/RegistrationConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.WebDriverWait; 9 | 10 | import java.time.Duration; 11 | 12 | public class RegistrationConfirmationPage { 13 | 14 | private WebDriver driver; 15 | private WebDriverWait wait; 16 | 17 | @FindBy(partialLinkText = "sign-in") 18 | private WebElement signinLink; 19 | 20 | @FindBy(linkText = "Flights") 21 | private WebElement flightsLink; 22 | 23 | public RegistrationConfirmationPage(WebDriver driver){ 24 | this.driver = driver; 25 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 26 | PageFactory.initElements(driver, this); 27 | } 28 | 29 | public void goToFlightDetailsPage(){ 30 | this.wait.until(ExpectedConditions.visibilityOf(this.signinLink)); 31 | this.flightsLink.click(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/src/main/java/com/searchmodule/pages/SearchPage.java: -------------------------------------------------------------------------------- 1 | package com.searchmodule.pages; 2 | 3 | import org.openqa.selenium.By; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.PageFactory; 8 | import org.openqa.selenium.support.ui.ExpectedConditions; 9 | import org.openqa.selenium.support.ui.WebDriverWait; 10 | 11 | import java.time.Duration; 12 | import java.util.List; 13 | 14 | public class SearchPage { 15 | 16 | private WebDriver driver; 17 | private WebDriverWait wait; 18 | 19 | @FindBy(name="q") 20 | private WebElement searchTxt; 21 | 22 | @FindBy(id = "search_button_homepage") 23 | private WebElement searchBtn; 24 | 25 | @FindBy(linkText = "Videos") 26 | private WebElement videosLink; 27 | 28 | @FindBy(className = "tile--vid") 29 | private List allVideos; 30 | 31 | public SearchPage(WebDriver driver){ 32 | this.driver = driver; 33 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 34 | PageFactory.initElements(driver, this); 35 | } 36 | 37 | public void goTo(){ 38 | this.driver.get("https://duckduckgo.com/"); 39 | } 40 | 41 | public void doSearch(String keyword){ 42 | this.wait.until(ExpectedConditions.visibilityOf(this.searchTxt)); 43 | this.searchTxt.sendKeys(keyword); 44 | this.searchBtn.click(); 45 | } 46 | 47 | public void goToVideos(){ 48 | this.wait.until(ExpectedConditions.visibilityOf(this.videosLink)); 49 | this.videosLink.click(); 50 | } 51 | 52 | public int getResult(){ 53 | By by = By.className("tile--vid"); 54 | this.wait.until(ExpectedConditions.numberOfElementsToBeMoreThan(by, 0)); 55 | System.out.println("Search Result : " + this.allVideos.size()); 56 | return this.allVideos.size(); 57 | } 58 | 59 | 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /09-old-projects/02-selenium-4.8.2-testng/src/test/java/com/searchmodule/tests/SearchTest.java: -------------------------------------------------------------------------------- 1 | package com.searchmodule.tests; 2 | 3 | import com.searchmodule.pages.SearchPage; 4 | import com.tests.BaseTest; 5 | import org.testng.Assert; 6 | import org.testng.annotations.Parameters; 7 | import org.testng.annotations.Test; 8 | 9 | public class SearchTest extends BaseTest { 10 | 11 | @Test 12 | @Parameters({"keyword"}) 13 | public void search(String keyword){ 14 | SearchPage searchPage = new SearchPage(driver); 15 | searchPage.goTo(); 16 | searchPage.doSearch(keyword); 17 | searchPage.goToVideos(); 18 | int size = searchPage.getResult(); 19 | Assert.assertTrue(size > 0); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | **/*.class 5 | 6 | # Log file 7 | **/*.log 8 | 9 | # BlueJ files 10 | **/*.ctxt 11 | 12 | # Mobile Tools for Java (J2ME) 13 | **/.mtj.tmp/ 14 | 15 | # Package Files # 16 | **/*.jar 17 | **/*.war 18 | **/*.nar 19 | **/*.ear 20 | **/*.zip 21 | **/*.tar.gz 22 | **/*.rar 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | **/hs_err_pid* 26 | 27 | ### Maven template 28 | **/target/ 29 | **/pom.xml.tag 30 | **/pom.xml.releaseBackup 31 | **/pom.xml.versionsBackup 32 | **/pom.xml.next 33 | **/release.properties 34 | **/dependency-reduced-pom.xml 35 | **/buildNumber.properties 36 | **/.mvn/timing.properties 37 | **/.mvn/wrapper/maven-wrapper.jar 38 | 39 | **/*.iml 40 | 41 | **/.idea/ 42 | 43 | 44 | **/HELP.md 45 | **/.mvn/ 46 | **/mvnw 47 | **/mvnw.cmd 48 | **/node_modules/ -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/Dockerfile: -------------------------------------------------------------------------------- 1 | # updated image for java 17 2 | FROM bellsoft/liberica-openjdk-alpine:17.0.6 3 | 4 | RUN apk add curl jq 5 | 6 | # Workspace 7 | WORKDIR /usr/share/udemy 8 | 9 | # ADD .jar under target from host 10 | # into this image 11 | ADD target/selenium-docker.jar selenium-docker.jar 12 | ADD target/selenium-docker-tests.jar selenium-docker-tests.jar 13 | ADD target/libs libs 14 | 15 | # in case of any other dependency like .csv / .json / .xls 16 | # please ADD that as well 17 | 18 | # ADD suite files 19 | ADD book-flight-module.xml book-flight-module.xml 20 | ADD search-module.xml search-module.xml 21 | 22 | # ADD health check script 23 | ADD healthcheck.sh healthcheck.sh 24 | 25 | # BROWSER 26 | # HUB_HOST 27 | # MODULE 28 | 29 | ENTRYPOINT sh healthcheck.sh -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent none 3 | stages { 4 | stage('Build Jar') { 5 | agent { 6 | docker { 7 | image 'maven:3-alpine' 8 | args '-v $HOME/.m2:/root/.m2' 9 | } 10 | } 11 | steps { 12 | sh 'mvn clean package -DskipTests' 13 | } 14 | } 15 | stage('Build Image') { 16 | steps { 17 | script { 18 | app = docker.build("vinsdocker/selenium-docker") 19 | } 20 | } 21 | } 22 | stage('Push Image') { 23 | steps { 24 | script { 25 | docker.withRegistry('https://registry.hub.docker.com', 'dockerhub') { 26 | app.push("${BUILD_NUMBER}") 27 | app.push("latest") 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/book-flight-module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | hub: 4 | image: seleniarm/hub:4.8.2 5 | ports: 6 | - "4444:4444" 7 | chrome: 8 | image: seleniarm/node-chromium:4.8.2 9 | shm_size: '2g' 10 | depends_on: 11 | - hub 12 | environment: 13 | - SE_EVENT_BUS_HOST=hub 14 | - SE_EVENT_BUS_PUBLISH_PORT=4442 15 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 16 | firefox: 17 | image: seleniarm/node-firefox:4.8.2 18 | shm_size: '2g' 19 | depends_on: 20 | - hub 21 | environment: 22 | - SE_EVENT_BUS_HOST=hub 23 | - SE_EVENT_BUS_PUBLISH_PORT=4442 24 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 25 | search-module: 26 | image: testtaha/deneme5 27 | depends_on: 28 | - chrome 29 | - firefox 30 | environment: 31 | - HUB_HOST=hub 32 | - BROWSER=firefox 33 | - TAGS=@search 34 | volumes: 35 | - ./output/search-result:/usr/share/udemy/test-output 36 | book-flight-module: 37 | image: testtaha/deneme5 38 | depends_on: 39 | - chrome 40 | - firefox 41 | environment: 42 | - HUB_HOST=hub 43 | - BROWSER=chrome 44 | - TAGS=@book-flight 45 | volumes: 46 | - ./output/book-result:/usr/share/udemy/test-output -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/healthcheck.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Environment Variables 3 | # HUB_HOST 4 | # BROWSER 5 | # MODULE 6 | 7 | echo "Checking if hub is ready - $HUB_HOST" 8 | 9 | while [ "$( curl -s http://$HUB_HOST:4444/wd/hub/status | jq -r .value.ready )" != "true" ] 10 | do 11 | sleep 1 12 | done 13 | 14 | # start the java command 15 | java -cp selenium-docker.jar:selenium-docker-tests.jar:libs/* \ 16 | -DHUB_HOST=$HUB_HOST \ 17 | -DBROWSER=$BROWSER \ 18 | io.cucumber.core.cli.Main \ 19 | classpath:features \ 20 | --tags $TAGS \ 21 | --glue com.test.stepdefs -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/search-module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/src/main/java/com/newtours/pages/FindFlightPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.WebDriverWait; 9 | 10 | import java.time.Duration; 11 | 12 | public class FindFlightPage { 13 | 14 | private WebDriver driver; 15 | private WebDriverWait wait; 16 | 17 | @FindBy(name = "reserveFlights") 18 | private WebElement firstSubmitBtn; 19 | 20 | @FindBy(name = "buyFlights") 21 | private WebElement secondSubmitBtn; 22 | 23 | public FindFlightPage(WebDriver driver){ 24 | this.driver = driver; 25 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 26 | PageFactory.initElements(driver, this); 27 | } 28 | 29 | public void submitFindFlightPage(){ 30 | this.wait.until(ExpectedConditions.elementToBeClickable(this.firstSubmitBtn)); 31 | this.firstSubmitBtn.click(); 32 | } 33 | 34 | public void goToFlightConfirmationPage(){ 35 | this.wait.until(ExpectedConditions.elementToBeClickable(this.secondSubmitBtn)); 36 | this.secondSubmitBtn.click(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/src/main/java/com/newtours/pages/FlightConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.WebDriverWait; 9 | 10 | import java.time.Duration; 11 | import java.util.List; 12 | 13 | public class FlightConfirmationPage { 14 | 15 | private WebDriver driver; 16 | private WebDriverWait wait; 17 | 18 | @FindBy(xpath = "//font[contains(text(), 'Confirmation')]") 19 | private WebElement flightConfirmationHeader; 20 | 21 | @FindBy(xpath = "//font[contains(text(), 'USD')]") 22 | private List prices; 23 | 24 | @FindBy(linkText = "SIGN-OFF") 25 | private WebElement signOffLink; 26 | 27 | public FlightConfirmationPage(WebDriver driver){ 28 | this.driver = driver; 29 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 30 | PageFactory.initElements(driver, this); 31 | } 32 | 33 | public String getPrice(){ 34 | this.wait.until(ExpectedConditions.visibilityOf(this.flightConfirmationHeader)); 35 | System.out.println(this.flightConfirmationHeader.getText()); 36 | System.out.println(this.prices.get(1).getText()); 37 | String price = this.prices.get(1).getText(); 38 | this.signOffLink.click(); 39 | return price; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/src/main/java/com/newtours/pages/FlightDetailsPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.Select; 9 | import org.openqa.selenium.support.ui.WebDriverWait; 10 | 11 | import java.time.Duration; 12 | 13 | public class FlightDetailsPage { 14 | 15 | private WebDriver driver; 16 | private WebDriverWait wait; 17 | 18 | @FindBy(name = "passCount") 19 | private WebElement passengers; 20 | 21 | @FindBy(name = "findFlights") 22 | private WebElement submitBtn; 23 | 24 | public FlightDetailsPage(WebDriver driver){ 25 | this.driver = driver; 26 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 27 | PageFactory.initElements(driver, this); 28 | } 29 | 30 | public void selectPassengers(String noOfPassengers){ 31 | this.wait.until(ExpectedConditions.elementToBeClickable(passengers)); 32 | Select select = new Select(passengers); 33 | select.selectByValue(noOfPassengers); 34 | } 35 | 36 | public void goToFindFlightsPage(){ 37 | this.submitBtn.click(); 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/src/main/java/com/newtours/pages/RegistrationConfirmationPage.java: -------------------------------------------------------------------------------- 1 | package com.newtours.pages; 2 | 3 | import org.openqa.selenium.WebDriver; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.openqa.selenium.support.PageFactory; 7 | import org.openqa.selenium.support.ui.ExpectedConditions; 8 | import org.openqa.selenium.support.ui.WebDriverWait; 9 | 10 | import java.time.Duration; 11 | 12 | public class RegistrationConfirmationPage { 13 | 14 | private WebDriver driver; 15 | private WebDriverWait wait; 16 | 17 | @FindBy(partialLinkText = "sign-in") 18 | private WebElement signinLink; 19 | 20 | @FindBy(linkText = "Flights") 21 | private WebElement flightsLink; 22 | 23 | public RegistrationConfirmationPage(WebDriver driver){ 24 | this.driver = driver; 25 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 26 | PageFactory.initElements(driver, this); 27 | } 28 | 29 | public void goToFlightDetailsPage(){ 30 | this.wait.until(ExpectedConditions.visibilityOf(this.signinLink)); 31 | this.flightsLink.click(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/src/main/java/com/searchmodule/pages/SearchPage.java: -------------------------------------------------------------------------------- 1 | package com.searchmodule.pages; 2 | 3 | import org.openqa.selenium.By; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | import org.openqa.selenium.support.PageFactory; 8 | import org.openqa.selenium.support.ui.ExpectedConditions; 9 | import org.openqa.selenium.support.ui.WebDriverWait; 10 | 11 | import java.time.Duration; 12 | import java.util.List; 13 | 14 | public class SearchPage { 15 | 16 | private WebDriver driver; 17 | private WebDriverWait wait; 18 | 19 | @FindBy(name="q") 20 | private WebElement searchTxt; 21 | 22 | @FindBy(id = "search_button_homepage") 23 | private WebElement searchBtn; 24 | 25 | @FindBy(linkText = "Videos") 26 | private WebElement videosLink; 27 | 28 | @FindBy(className = "tile--vid") 29 | private List allVideos; 30 | 31 | public SearchPage(WebDriver driver){ 32 | this.driver = driver; 33 | this.wait = new WebDriverWait(driver, Duration.ofSeconds(30)); 34 | PageFactory.initElements(driver, this); 35 | } 36 | 37 | public void goTo(){ 38 | this.driver.get("https://duckduckgo.com/"); 39 | } 40 | 41 | public void doSearch(String keyword){ 42 | this.wait.until(ExpectedConditions.visibilityOf(this.searchTxt)); 43 | this.searchTxt.sendKeys(keyword); 44 | this.searchBtn.click(); 45 | } 46 | 47 | public void goToVideos(){ 48 | this.wait.until(ExpectedConditions.visibilityOf(this.videosLink)); 49 | this.videosLink.click(); 50 | } 51 | 52 | public int getResult(){ 53 | By by = By.className("tile--vid"); 54 | this.wait.until(ExpectedConditions.numberOfElementsToBeMoreThan(by, 0)); 55 | System.out.println("Search Result : " + this.allVideos.size()); 56 | return this.allVideos.size(); 57 | } 58 | 59 | 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/src/test/java/com/runner/TestRunner.java: -------------------------------------------------------------------------------- 1 | package com.runner; 2 | 3 | 4 | import io.cucumber.testng.AbstractTestNGCucumberTests; 5 | import io.cucumber.testng.CucumberOptions; 6 | 7 | @CucumberOptions( 8 | features = "src/test/resources/features", 9 | glue = {"com.test.stepdefs"}, 10 | tags = "@search", 11 | plugin = { 12 | "pretty", 13 | "html:target/cucumber-reports/cucumber-pretty", 14 | "json:target/cucumber-reports/json-reports/CucumberTestReport.json", 15 | "rerun:target/cucumber-reports/rerun-reports/rerun.txt" 16 | }) 17 | public class TestRunner extends AbstractTestNGCucumberTests { 18 | 19 | } -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/src/test/java/com/test/stepdefs/SearchSteps.java: -------------------------------------------------------------------------------- 1 | package com.test.stepdefs; 2 | 3 | import com.searchmodule.pages.SearchPage; 4 | import io.cucumber.java.After; 5 | import io.cucumber.java.Before; 6 | import io.cucumber.java.en.And; 7 | import io.cucumber.java.en.Given; 8 | import io.cucumber.java.en.Then; 9 | import org.openqa.selenium.WebDriver; 10 | import org.testng.Assert; 11 | 12 | public class SearchSteps { 13 | 14 | private SearchPage searchPage; 15 | private WebDriver driver; 16 | 17 | @Given("^I am on the website duck-duck-go$") 18 | public void launchSite() { 19 | searchPage = new SearchPage(driver); 20 | searchPage.goTo(); 21 | } 22 | 23 | @And("^I enter the \"([^\"]*)\" to search$") 24 | public void enterKeyword(String keyword) { 25 | searchPage.doSearch(keyword); 26 | } 27 | 28 | @And("^I navigate to videos search$") 29 | public void navigateTovideos() { 30 | searchPage.goToVideos(); 31 | } 32 | 33 | @Then("^I should get minimum (\\d+) search results$") 34 | public void verifySearchResults(int min) { 35 | int size = searchPage.getResult(); 36 | Assert.assertTrue(size > min); 37 | } 38 | 39 | @Before 40 | public void setupDriver() throws Exception { 41 | this.driver = WebDriverManager.getDriver(); 42 | } 43 | 44 | @After 45 | public void quitDriver() { 46 | WebDriverManager.quitDriver(); 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/src/test/java/com/test/stepdefs/WebDriverManager.java: -------------------------------------------------------------------------------- 1 | package com.test.stepdefs; 2 | 3 | import org.openqa.selenium.Capabilities; 4 | import org.openqa.selenium.WebDriver; 5 | import org.openqa.selenium.chrome.ChromeOptions; 6 | import org.openqa.selenium.firefox.FirefoxOptions; 7 | import org.openqa.selenium.remote.RemoteWebDriver; 8 | 9 | import java.net.MalformedURLException; 10 | import java.net.URL; 11 | import java.util.Objects; 12 | 13 | public class WebDriverManager { 14 | 15 | private static final ThreadLocal DRIVERS = new ThreadLocal<>(); 16 | 17 | public static WebDriver getDriver() throws Exception { 18 | WebDriver driver = DRIVERS.get(); 19 | if(Objects.isNull(driver)){ 20 | DRIVERS.set(setupDriver()); 21 | driver = DRIVERS.get(); 22 | } 23 | return driver; 24 | } 25 | 26 | private static WebDriver setupDriver() throws MalformedURLException { 27 | // BROWSER => chrome / firefox 28 | // HUB_HOST => localhost / 10.0.1.3 / hostname 29 | String host = "localhost"; 30 | Capabilities dc; 31 | 32 | if(System.getProperty("BROWSER") != null && 33 | System.getProperty("BROWSER").equalsIgnoreCase("firefox")){ 34 | dc = new FirefoxOptions(); 35 | }else{ 36 | dc = new ChromeOptions(); 37 | } 38 | 39 | if(System.getProperty("HUB_HOST") != null){ 40 | host = System.getProperty("HUB_HOST"); 41 | } 42 | 43 | String completeUrl = "http://" + host + ":4444/wd/hub"; 44 | return new RemoteWebDriver(new URL(completeUrl), dc); 45 | } 46 | 47 | public static void quitDriver(){ 48 | WebDriver driver = DRIVERS.get(); 49 | if(Objects.nonNull(driver)){ 50 | driver.quit(); 51 | DRIVERS.remove(); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/src/test/resources/features/flight-book.feature: -------------------------------------------------------------------------------- 1 | Feature: Flight Book 2 | 3 | @book-flight 4 | Scenario Outline: I should be able to book tickets for a given flight search 5 | Given I am on flight book page 6 | When I go to flight details page 7 | And I select the passengers as "" 8 | And I go the find flights page 9 | Then Flight confirmation page should show the price as "" 10 | 11 | Examples: 12 | | noOfPassengers | expectedPrice | 13 | | 1 | $584 USD | 14 | | 2 | $1169 USD | 15 | | 3 | $1753 USD | 16 | | 4 | $2338 USD | 17 | -------------------------------------------------------------------------------- /09-old-projects/03-selenium-4.8.2-bdd-testng/src/test/resources/features/search.feature: -------------------------------------------------------------------------------- 1 | Feature: Duck Duck Go Search 2 | 3 | @search 4 | Scenario Outline: I want to search on duck-duck-go site 5 | Given I am on the website duck-duck-go 6 | And I enter the "" to search 7 | And I navigate to videos search 8 | Then I should get minimum 2 search results 9 | 10 | Examples: 11 | | keyword | 12 | | java | 13 | | webdriver | 14 | | docker | 15 | | kubernetes | -------------------------------------------------------------------------------- /09-old-projects/docker-compose-files/01-selenium-3-grid.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | hub: 4 | image: selenium/hub:3.14 5 | chrome: 6 | image: selenium/node-chrome:3.14 7 | depends_on: 8 | - hub 9 | environment: 10 | - HUB_HOST=hub 11 | firefox: 12 | image: selenium/node-firefox:3.14 13 | shm_size: '1gb' 14 | depends_on: 15 | - hub 16 | environment: 17 | - HUB_HOST=hub 18 | search-module: 19 | image: vinsdocker/selenium-docker 20 | depends_on: 21 | - chrome 22 | - firefox 23 | environment: 24 | - HUB_HOST=hub 25 | - BROWSER=firefox 26 | - MODULE=search-module.xml 27 | volumes: 28 | - ./output/search-result:/usr/share/udemy/test-output 29 | book-flight-module: 30 | image: vinsdocker/selenium-docker 31 | depends_on: 32 | - chrome 33 | - firefox 34 | environment: 35 | - HUB_HOST=hub 36 | - BROWSER=chrome 37 | - MODULE=book-flight-module.xml 38 | volumes: 39 | - ./output/book-result:/usr/share/udemy/test-output -------------------------------------------------------------------------------- /09-old-projects/docker-compose-files/02-selenium-4.8-grid.yaml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | hub: 4 | image: selenium/hub:4.8.2 5 | ports: 6 | - "4444:4444" 7 | chrome: 8 | image: selenium/node-chrome:4.8.2 9 | shm_size: '2g' 10 | depends_on: 11 | - hub 12 | environment: 13 | - SE_EVENT_BUS_HOST=hub 14 | - SE_EVENT_BUS_PUBLISH_PORT=4442 15 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 16 | firefox: 17 | image: selenium/node-firefox:4.8.2 18 | shm_size: '2g' 19 | depends_on: 20 | - hub 21 | environment: 22 | - SE_EVENT_BUS_HOST=hub 23 | - SE_EVENT_BUS_PUBLISH_PORT=4442 24 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 25 | # search-module: 26 | # image: vinsdocker/selenium-docker-bdd 27 | # depends_on: 28 | # - chrome 29 | # - firefox 30 | # environment: 31 | # - HUB_HOST=hub 32 | # - BROWSER=firefox 33 | # - TAGS=@search 34 | # volumes: 35 | # - ./output/search-result:/usr/share/udemy/test-output 36 | # book-flight-module: 37 | # image: vinsdocker/selenium-docker-bdd 38 | # depends_on: 39 | # - chrome 40 | # - firefox 41 | # environment: 42 | # - HUB_HOST=hub 43 | # - BROWSER=chrome 44 | # - TAGS=@book-flight 45 | # volumes: 46 | # - ./output/book-result:/usr/share/udemy/test-output -------------------------------------------------------------------------------- /09-old-projects/docker-compose-files/03-selenium-4.8-grid-M1-Mac.yaml: -------------------------------------------------------------------------------- 1 | # https://github.com/SeleniumHQ/docker-selenium#experimental-mult-arch-aarch64armhfamd64-images 2 | version: "3" 3 | services: 4 | hub: 5 | image: seleniarm/hub:4.10 6 | ports: 7 | - "4444:4444" 8 | chrome: 9 | image: seleniarm/node-chromium:4.10 10 | shm_size: '2g' 11 | depends_on: 12 | - hub 13 | environment: 14 | - SE_EVENT_BUS_HOST=hub 15 | - SE_EVENT_BUS_PUBLISH_PORT=4442 16 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 17 | firefox: 18 | image: seleniarm/node-firefox:4.10 19 | shm_size: '2g' 20 | depends_on: 21 | - hub 22 | environment: 23 | - SE_EVENT_BUS_HOST=hub 24 | - SE_EVENT_BUS_PUBLISH_PORT=4442 25 | - SE_EVENT_BUS_SUBSCRIBE_PORT=4443 26 | # search-module: 27 | # image: vinsdocker/selenium-docker-bdd 28 | # depends_on: 29 | # - chrome 30 | # - firefox 31 | # environment: 32 | # - HUB_HOST=hub 33 | # - BROWSER=firefox 34 | # - TAGS=@search 35 | # volumes: 36 | # - ./output/search-result:/usr/share/udemy/test-output 37 | # book-flight-module: 38 | # image: vinsdocker/selenium-docker-bdd 39 | # depends_on: 40 | # - chrome 41 | # - firefox 42 | # environment: 43 | # - HUB_HOST=hub 44 | # - BROWSER=chrome 45 | # - TAGS=@book-flight 46 | # volumes: 47 | # - ./output/book-result:/usr/share/udemy/test-output -------------------------------------------------------------------------------- /10-misc/question-template.md: -------------------------------------------------------------------------------- 1 | # How To Use Q/A section 2 | 3 | In case of issues, I would highly encourage you to debug yourself first. Debugging is the best way to learn and understand the mistakes. 4 | 5 | ## Debug yourself 6 | 7 | - I would highly encourage you to use the **pom dependencies version and docker image versions** I provide even if they are NOT latest. I will update periodically. However sometimes, there are some known issues. So I carefully test and provide the updated versions. 8 | 9 | - [Maven dependencies](../03-automation-framework/dependencies.md) 10 | - [Docker Images](../04-selenium-grid/docker-images.md) 11 | - Compare your project with mine. You can use tools like **WinMerge** to compare multiple files. 12 | - Worst case, clone my project and see if it works. 13 | 14 | ## Q/A Template 15 | 16 | Do note that single line issue description / some error screenshots might not help to clarify any issues. Follow this format. 17 | 18 | - What is your OS? 19 | - In which lecture you start facing the issue? 20 | - Before this lecture, was everything working fine? 21 | - List the changes you did specific to lecture with code samples / screenshots 22 | - Upload your project in Github and share the link 23 | 24 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Scalable Test Automation With Docker, Jenkins & AWS 2 | 3 | This repository contains all the source code for my course in Udemy 4 | 5 | ![](.doc/selenium-docker-aws-jenkins.png) 6 | 7 | --------------------------------------------------------------------------------