├── CBT_OS-logo_Black-V.png
├── images
├── architecture.png
└── reportportal.png
├── .mvn
└── wrapper
│ ├── maven-wrapper.jar
│ ├── maven-wrapper.properties
│ └── MavenWrapperDownloader.java
├── src
├── test
│ ├── resources
│ │ ├── settings.properties
│ │ ├── reportportal.properties
│ │ ├── logback.xml
│ │ └── suites
│ │ │ ├── SmokeSuite.xml
│ │ │ └── RegressionSuite.xml
│ └── java
│ │ ├── tests
│ │ ├── SignInTest.java
│ │ └── BaseTest.java
│ │ └── listeners
│ │ ├── HighlighterEventListener.java
│ │ └── TestListener.java
└── main
│ └── java
│ ├── helper
│ └── StringConstants.java
│ ├── annotations
│ ├── Module.java
│ ├── Window.java
│ └── TestInfo.java
│ ├── webdriver
│ ├── local
│ │ ├── EdgeDriverManager.java
│ │ ├── LocalDriverManager.java
│ │ ├── FirefoxDriverManager.java
│ │ └── ChromeDriverManager.java
│ ├── DriverFactory.java
│ ├── DriverManager.java
│ └── IDriver.java
│ ├── pages
│ ├── BasePage.java
│ ├── HomePage.java
│ └── SignInPage.java
│ ├── utils
│ ├── WebElementUtils.java
│ ├── ExecutionUtils.java
│ ├── PropertyUtils.java
│ ├── ReportUtils.java
│ ├── ServicesUtils.java
│ ├── LogUtils.java
│ └── RestUtils.java
│ ├── keywords
│ ├── Verification.java
│ ├── Action.java
│ ├── Element.java
│ └── Browser.java
│ ├── modules
│ ├── WindowInterceptor.java
│ ├── TestParameters.java
│ └── DriverModule.java
│ ├── extentreports
│ ├── ExtentTestManager.java
│ └── ExtentManager.java
│ ├── reportportal
│ ├── Launch.java
│ ├── LaunchHandler.java
│ └── SessionContext.java
│ └── ensure
│ └── Wait.java
├── .travis.yml
├── healthcheck.sh
├── .gitignore
├── run-tests.sh
├── Jenkinsfile
├── Dockerfile
├── .github
└── workflows
│ └── maven.yml
├── docker-compose.yaml
├── LICENSE
├── .circleci
└── config.yml
├── README.md
├── mvnw.cmd
├── pom.xml
└── mvnw
/CBT_OS-logo_Black-V.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zarashima/web-test-framework/HEAD/CBT_OS-logo_Black-V.png
--------------------------------------------------------------------------------
/images/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zarashima/web-test-framework/HEAD/images/architecture.png
--------------------------------------------------------------------------------
/images/reportportal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zarashima/web-test-framework/HEAD/images/reportportal.png
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zarashima/web-test-framework/HEAD/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/src/test/resources/settings.properties:
--------------------------------------------------------------------------------
1 | web.timeout=30
2 | aut.homepage=https://another-nodejs-shopping-cart.herokuapp.com/
3 | kibana.integration=false
4 |
--------------------------------------------------------------------------------
/src/test/resources/reportportal.properties:
--------------------------------------------------------------------------------
1 | rp.endpoint = http://localhost:8080
2 | rp.uuid = c892925c-cb9a-43f0-93e4-fff5b1bf1a4e
3 | rp.launch = smoke-test-build-1.0
4 | rp.project = automation-tests
5 | rp.reporting.callback=true
6 | rp.enable = false
7 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | dist: xenial
3 | services:
4 | - xvfb
5 | addons:
6 | chrome: stable
7 | firefox: latest
8 | cache:
9 | directories:
10 | - .autoconf
11 | - $HOME/.m2
12 | env:
13 | - RUNWHERE=pipeline
14 | script:
15 | - mvn test -Dsuite=SmokeSuite
16 |
--------------------------------------------------------------------------------
/src/main/java/helper/StringConstants.java:
--------------------------------------------------------------------------------
1 | package helper;
2 |
3 | import reportportal.SessionContext;
4 |
5 | public class StringConstants {
6 | public static final int TIMEOUT = 30;
7 | public static final int SUCCESS_RESPONSE_CODE = 200;
8 | public static final String RP_API_ENDPOINT = SessionContext.getEndPoint() + "/api/v1";
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/healthcheck.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | export RUNWHERE=container
3 | echo "Checking if hub is ready - $HUB_HOST"
4 |
5 | while [[ "$( curl -s http://$HUB_HOST:4444/wd/hub/status | jq -r .value.ready )" != "true" ]]
6 | do
7 | sleep 1
8 | done
9 |
10 | java -cp framework-1.0.jar:framework-1.0-tests.jar:libs/* \
11 | -DHUB_HOST="$HUB_HOST" \
12 | org.testng.TestNG "$SUITE"
13 |
--------------------------------------------------------------------------------
/src/main/java/annotations/Module.java:
--------------------------------------------------------------------------------
1 | package annotations;
2 |
3 |
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | @Retention(RetentionPolicy.RUNTIME)
10 | @Target({ElementType.TYPE})
11 | public @interface Module {
12 | String module() default "none";
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/webdriver/local/EdgeDriverManager.java:
--------------------------------------------------------------------------------
1 | package webdriver.local;
2 |
3 | import org.openqa.selenium.WebDriver;
4 | import org.openqa.selenium.edge.EdgeDriver;
5 | import org.openqa.selenium.remote.DesiredCapabilities;
6 |
7 | public class EdgeDriverManager {
8 |
9 | public WebDriver createDriver(DesiredCapabilities desiredCapabilities) {
10 | return new EdgeDriver();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/annotations/Window.java:
--------------------------------------------------------------------------------
1 | package annotations;
2 |
3 | import com.google.inject.BindingAnnotation;
4 |
5 | import java.lang.annotation.ElementType;
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.RetentionPolicy;
8 | import java.lang.annotation.Target;
9 |
10 | @BindingAnnotation
11 | @Target({ElementType.TYPE})
12 | @Retention(RetentionPolicy.RUNTIME)
13 | public @interface Window {
14 | int value() default 0;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/pages/BasePage.java:
--------------------------------------------------------------------------------
1 | package pages;
2 |
3 | import com.google.inject.Inject;
4 | import keywords.Browser;
5 | import keywords.Element;
6 | import org.openqa.selenium.WebDriver;
7 |
8 | public class BasePage {
9 |
10 | @Inject
11 | protected Browser browserKeywords;
12 |
13 | @Inject
14 | protected Element elementKeywords;
15 |
16 | @Inject
17 | protected WebDriver driver;
18 |
19 | @Inject
20 | public BasePage(WebDriver driver) {
21 | this.driver = driver;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/utils/WebElementUtils.java:
--------------------------------------------------------------------------------
1 | package utils;
2 |
3 | public class WebElementUtils {
4 | private WebElementUtils() {
5 | }
6 |
7 | public static synchronized String getElementXpathInfo(Object element) {
8 | String[] elementInfo;
9 | if (element.toString().contains("xpath: "))
10 | elementInfo = element.toString().split("xpath: ");
11 | else
12 | elementInfo = element.toString().split("css selector: ");
13 | return elementInfo[elementInfo.length - 1];
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.war
15 | *.nar
16 | *.ear
17 | *.zip
18 | *.tar.gz
19 | *.rar
20 |
21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
22 | hs_err_pid*
23 |
24 | # internal project files
25 | /.idea/
26 | .idea/
27 | factory.iml
28 | /TestReport/
29 | /target/
30 | /failed-screenshots/
31 | /test-output/
32 | /target/
33 |
--------------------------------------------------------------------------------
/src/main/java/webdriver/DriverFactory.java:
--------------------------------------------------------------------------------
1 | package webdriver;
2 |
3 | import org.openqa.selenium.remote.DesiredCapabilities;
4 | import webdriver.local.LocalDriverManager;
5 | import org.openqa.selenium.WebDriver;
6 |
7 | public class DriverFactory {
8 |
9 | private DriverFactory() {}
10 |
11 | public static WebDriver createInstance(String browser, DesiredCapabilities desiredCapabilities) {
12 | WebDriver webdriver;
13 | webdriver = new LocalDriverManager().createInstance(browser, desiredCapabilities);
14 | return webdriver;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/annotations/TestInfo.java:
--------------------------------------------------------------------------------
1 | package annotations;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Target({ElementType.TYPE})
10 | public @interface TestInfo {
11 |
12 | public enum Priority {
13 | LOW, MEDIUM, HIGH
14 | }
15 |
16 | String module() default "";
17 |
18 | Priority priority() default Priority.MEDIUM;
19 |
20 | String createdBy() default "vinh.nguyen";
21 | }
22 |
--------------------------------------------------------------------------------
/run-tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | echo "Package project"
3 | mvn clean package -DskipTests=true
4 |
5 | echo "Build docker image"
6 | docker build -t=vinh/framework-docker .
7 |
8 | echo "Cleanup previous docker compose"
9 | docker-compose down --rmi local
10 |
11 | echo "Run tests"
12 | SUITE=$1 docker-compose up -d --force-recreate
13 |
14 | echo "Execution logs"
15 | docker-compose logs > output.log
16 | while [[ !($(cat output.log | grep "Total tests run")) ]]
17 | do
18 | docker-compose logs --tail=1000
19 | docker-compose logs --tail=1000 > output.log
20 | sleep 1
21 | done
22 |
--------------------------------------------------------------------------------
/src/test/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | %d{HH:mm:ss.SSS} [%thread] %marker %-5level %logger{36} - %msg%n
5 |
6 |
7 |
8 |
9 | %d{HH:mm:ss.SSS} [%t] %-5level - %msg%n
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/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 | sh 'docker build -t=vinh/framework-docker .'
18 | }
19 | }
20 | stage('Run tests') {
21 | steps {
22 | sh 'docker-compose up -d'
23 | }
24 | }
25 | stage('Clean up') {
26 | steps {
27 | sh 'docker-compose down'
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/keywords/Verification.java:
--------------------------------------------------------------------------------
1 | package keywords;
2 |
3 | import com.google.inject.Inject;
4 | import org.openqa.selenium.WebDriver;
5 | import org.openqa.selenium.WebElement;
6 | import utils.LogUtils;
7 |
8 | import static org.assertj.core.api.Assertions.assertThat;
9 |
10 | public class Verification {
11 |
12 | protected WebElement element;
13 |
14 | @Inject
15 | WebDriver driver;
16 |
17 | @Inject
18 | public Verification(WebDriver driver) {
19 | this.driver = driver;
20 | }
21 |
22 | public void verifyEqual(Object actual, Object expect) {
23 | LogUtils.info("Verify " + actual + " equal to " + expect);
24 | assertThat(actual).isEqualTo(expect);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8u191-jre-alpine3.8
2 |
3 | RUN apk add curl jq
4 |
5 | WORKDIR /usr/share/framework
6 |
7 | # ADD .jar & libs files under target from host
8 | COPY target/framework-1.0.jar framework-1.0.jar
9 | COPY target/framework-1.0-tests.jar framework-1.0-tests.jar
10 | COPY target/libs libs
11 |
12 | # ADD resources folder
13 | COPY src/test/resources src/test/resources
14 |
15 | # ADD suite files
16 | COPY src/test/resources/suites/SmokeSuite.xml SmokeSuite.xml
17 | COPY src/test/resources/suites/RegressionSuite.xml RegressionSuite.xml
18 |
19 | # ADD bash file for execution
20 | COPY healthcheck.sh healthcheck.sh
21 |
22 | ENTRYPOINT sh healthcheck.sh
23 |
--------------------------------------------------------------------------------
/src/test/resources/suites/SmokeSuite.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/test/resources/suites/RegressionSuite.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/test/java/tests/SignInTest.java:
--------------------------------------------------------------------------------
1 | package tests;
2 |
3 | import annotations.TestInfo;
4 | import org.testng.annotations.Test;
5 | import utils.PropertyUtils;
6 |
7 | @TestInfo(module = "signin",
8 | priority = TestInfo.Priority.MEDIUM,
9 | createdBy = "vinh.nguyen")
10 | public class SignInTest extends BaseTest {
11 | @Test(description = "Verify invalid message is displayed when using invalid email and password")
12 | public void verifySignIn_invalidEmailPassword_shouldPromptInvalidMessage() {
13 | browserKeywords.goTo(PropertyUtils.getInstance().getAutHomepage());
14 | homePage.goToSignInPage();
15 | signInPage.signIn("admin", "password");
16 | verificationKeywords.verifyEqual(signInPage.getErrorMessage(), "Invalid email");
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/utils/ExecutionUtils.java:
--------------------------------------------------------------------------------
1 | package utils;
2 |
3 | public class ExecutionUtils {
4 |
5 | private ExecutionUtils() {
6 | }
7 |
8 | public static synchronized String getParameter(String name) {
9 | String value = System.getProperty(name);
10 | if (value == null)
11 | throw new RuntimeException(name + " is not a parameter!");
12 | if (value.isEmpty())
13 | throw new RuntimeException(name + " is empty!");
14 | return value;
15 | }
16 |
17 | public static synchronized void setParameter(String key, String name) {
18 | if (key == null)
19 | throw new RuntimeException(name + " is not a parameter!");
20 | if (key.isEmpty())
21 | throw new RuntimeException(name + " is empty!");
22 | System.setProperty(key, name);
23 | }
24 |
25 | public static synchronized Object getEnv(String envName) {
26 | return System.getenv(envName);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/modules/WindowInterceptor.java:
--------------------------------------------------------------------------------
1 | package modules;
2 |
3 | import annotations.Window;
4 | import org.aopalliance.intercept.MethodInterceptor;
5 | import org.aopalliance.intercept.MethodInvocation;
6 | import webdriver.DriverManager;
7 |
8 | public class WindowInterceptor implements MethodInterceptor {
9 |
10 | @Override
11 | public Object invoke(MethodInvocation methodInvocation) throws Throwable {
12 | int index = methodInvocation.getMethod().getDeclaringClass().getAnnotation(Window.class).value();
13 | this.switchToWindow(index);
14 | Object object = methodInvocation.proceed();
15 | this.switchToWindow(0);
16 | return object;
17 | }
18 |
19 | private void switchToWindow(int index) {
20 | String handle = DriverManager.getDriver().getWindowHandles().toArray(new String[0])[index];
21 | DriverManager.getDriver().switchTo().window(handle);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/extentreports/ExtentTestManager.java:
--------------------------------------------------------------------------------
1 | package extentreports;
2 |
3 | import com.aventstack.extentreports.ExtentReports;
4 | import com.aventstack.extentreports.ExtentTest;
5 |
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | public class ExtentTestManager {
10 |
11 | public static ExtentTest test;
12 | static Map extentTestMap = new HashMap();
13 | static ExtentReports extent = ExtentManager.getInstance();
14 |
15 | public static synchronized ExtentTest getTest() {
16 | return extentTestMap.get((int) Thread.currentThread().getId());
17 | }
18 |
19 | public static synchronized void endTest() {
20 | extent.flush();
21 | }
22 |
23 | public static synchronized ExtentTest startTest(String testName) {
24 | test = extent.createTest(testName);
25 | extentTestMap.put((int) Thread.currentThread().getId(), test);
26 | return test;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/pages/HomePage.java:
--------------------------------------------------------------------------------
1 | package pages;
2 |
3 | import com.google.inject.Inject;
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 |
9 | public class HomePage extends BasePage {
10 |
11 | @FindBy(xpath = "/html/body/div/div[2]/div[1]/div/div/div/a")
12 | public WebElement addToCartButton;
13 |
14 | @FindBy(css = "a[href='/user/signin']")
15 | private WebElement signInButton;
16 |
17 | @FindBy(css = "div[id='bs-example-navbar-collapse-1'] > ul > li a[href='#']")
18 | private WebElement userMenuButton;
19 |
20 | @Inject
21 | public HomePage(WebDriver driver) {
22 | super(driver);
23 | PageFactory.initElements(driver, this);
24 | }
25 |
26 | public HomePage goToSignInPage() {
27 | elementKeywords.click(userMenuButton);
28 | elementKeywords.click(signInButton);
29 | return this;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | name: build
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: ubuntu-latest
9 |
10 | steps:
11 |
12 | - uses: actions/checkout@v1
13 | - uses: actions/cache@v1
14 | with:
15 | path: ~/.m2/repository
16 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
17 | restore-keys: |
18 | ${{ runner.os }}-maven-
19 |
20 | - name: Set up JDK 1.8
21 | uses: actions/setup-java@v1
22 | with:
23 | java-version: 1.8
24 |
25 | - name: Setup chromedriver
26 | uses: nanasess/setup-chromedriver@master
27 | - run: |
28 | export DISPLAY=:99
29 | chromedriver --url-base=/wd/hub &
30 | sudo Xvfb -ac :99 -screen 0 1280x1024x24 > /dev/null 2>&1 & # optional
31 |
32 |
33 | - name: maven test
34 | env:
35 | RUNWHERE: pipeline
36 | run: |
37 | mvn clean test -Dsuite=SmokeSuite
38 |
--------------------------------------------------------------------------------
/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: "2"
2 | services:
3 | selenium-hub:
4 | image: selenium/hub:3.141.59-20200409
5 | container_name: selenium-hub
6 | ports:
7 | - "4444:4444"
8 |
9 | chrome:
10 | image: selenium/node-chrome:3.141.59-20200409
11 | volumes:
12 | - /dev/shm:/dev/shm
13 | depends_on:
14 | - selenium-hub
15 | environment:
16 | - HUB_HOST=selenium-hub
17 | - HUB_PORT=4444
18 |
19 | firefox:
20 | image: selenium/node-firefox:3.141.59-20200409
21 | volumes:
22 | - /dev/shm:/dev/shm
23 | depends_on:
24 | - selenium-hub
25 | environment:
26 | - HUB_HOST=selenium-hub
27 | - HUB_PORT=4444
28 |
29 | smoke:
30 | image: vinh/framework-docker
31 | depends_on:
32 | - chrome
33 | - firefox
34 | environment:
35 | - HUB_HOST=selenium-hub
36 | - SUITE="${SUITE}"
37 | volumes:
38 | - ./TestReport:/usr/share/framework/TestReport
39 | - ./results:/usr/share/framework/test-output
40 |
--------------------------------------------------------------------------------
/src/main/java/modules/TestParameters.java:
--------------------------------------------------------------------------------
1 | package modules;
2 |
3 | import annotations.TestInfo;
4 | import annotations.TestInfo.Priority;
5 |
6 | public class TestParameters {
7 |
8 | private static synchronized void checkTestInfoAnnotation(Class T) {
9 | if (!T.isAnnotationPresent(TestInfo.class)) {
10 | throw new RuntimeException("The class "
11 | + T.getSimpleName()
12 | + " is not annotated with TestInfo");
13 | }
14 | }
15 |
16 | public static synchronized String getModule(Class T) {
17 | checkTestInfoAnnotation(T);
18 | return ((TestInfo) T.getAnnotation(TestInfo.class)).module();
19 | }
20 |
21 | public static synchronized Priority getPriority(Class T) {
22 | checkTestInfoAnnotation(T);
23 | return ((TestInfo) T.getAnnotation(TestInfo.class)).priority();
24 | }
25 |
26 | public static synchronized String getCreatedBy(Class T) {
27 | checkTestInfoAnnotation(T);
28 | return ((TestInfo) T.getAnnotation(TestInfo.class)).createdBy();
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/webdriver/DriverManager.java:
--------------------------------------------------------------------------------
1 | package webdriver;
2 |
3 | import org.openqa.selenium.Capabilities;
4 | import org.openqa.selenium.WebDriver;
5 | import org.openqa.selenium.remote.RemoteWebDriver;
6 |
7 | public class DriverManager {
8 |
9 | private static final ThreadLocal driver = new ThreadLocal<>();
10 |
11 | private DriverManager() {}
12 |
13 | public static WebDriver getDriver() {
14 | return driver.get();
15 | }
16 |
17 | public static void setDriver(WebDriver driver) {
18 | DriverManager.driver.set(driver);
19 | }
20 |
21 | public static void quit() {
22 | DriverManager.driver.get().quit();
23 | driver.remove();
24 | }
25 |
26 | public static String getBrowserName() {
27 | Capabilities cap = ((RemoteWebDriver) DriverManager.getDriver()).getCapabilities();
28 | String browserName = cap.getBrowserName();
29 | String version = cap.getVersion();
30 | return String.format("%s_%s", browserName, version);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/test/java/listeners/HighlighterEventListener.java:
--------------------------------------------------------------------------------
1 | package listeners;
2 |
3 | import org.openqa.selenium.By;
4 | import org.openqa.selenium.JavascriptExecutor;
5 | import org.openqa.selenium.WebDriver;
6 | import org.openqa.selenium.WebElement;
7 | import org.openqa.selenium.support.events.AbstractWebDriverEventListener;
8 |
9 | class HighlighterEventListener extends AbstractWebDriverEventListener {
10 |
11 | private WebElement lastElement;
12 |
13 | @Override
14 | public void beforeFindBy(By by, WebElement element, WebDriver driver) {
15 | System.out.print("before find by");
16 | if (lastElement != null) {
17 | ((JavascriptExecutor) driver).executeScript(
18 | "arguments[0].style.border='none'", lastElement);
19 | }
20 | lastElement = null;
21 | }
22 |
23 | @Override
24 | public void afterFindBy(By by, WebElement element, WebDriver driver) {
25 | lastElement = element;
26 | ((JavascriptExecutor) driver).executeScript(
27 | "arguments[0].style.border='pink'", lastElement);
28 | System.out.print("after find by");
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/modules/DriverModule.java:
--------------------------------------------------------------------------------
1 | package modules;
2 |
3 | import annotations.Window;
4 | import com.google.inject.AbstractModule;
5 | import com.google.inject.Provides;
6 | import com.google.inject.matcher.Matchers;
7 | import ensure.Wait;
8 | import org.aopalliance.intercept.MethodInterceptor;
9 | import org.openqa.selenium.JavascriptExecutor;
10 | import org.openqa.selenium.WebDriver;
11 | import webdriver.DriverManager;
12 |
13 | public class DriverModule extends AbstractModule {
14 |
15 | @Override
16 | protected void configure() {
17 | MethodInterceptor interceptor = new WindowInterceptor();
18 | requestInjection(interceptor);
19 | bindInterceptor(Matchers.annotatedWith(Window.class), Matchers.any(), interceptor);
20 | }
21 |
22 | @Provides
23 | public WebDriver getDriver() {
24 | return DriverManager.getDriver();
25 | }
26 |
27 | @Provides
28 | public Wait getWait() {
29 | return new Wait(DriverManager.getDriver());
30 | }
31 |
32 | @Provides
33 | public JavascriptExecutor getJsExecutor() {
34 | return (JavascriptExecutor) DriverManager.getDriver();
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/utils/PropertyUtils.java:
--------------------------------------------------------------------------------
1 | package utils;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.IOException;
5 | import java.util.Properties;
6 |
7 | public class PropertyUtils {
8 |
9 | private static PropertyUtils instance;
10 | private final Properties props = new Properties();
11 | private Integer webTimeout;
12 | private String autHomePage;
13 |
14 | public static PropertyUtils getInstance() {
15 | if (instance == null) {
16 | instance = new PropertyUtils();
17 | instance.loadData();
18 | }
19 | return instance;
20 | }
21 |
22 | private void loadData() {
23 | String settingsFilePath = "src/test/resources/settings.properties";
24 | try {
25 | props.load(new FileInputStream(settingsFilePath));
26 | } catch (IOException e) {
27 | e.printStackTrace();
28 | }
29 | webTimeout = Integer.valueOf(props.getProperty("web.timeout"));
30 | autHomePage = props.getProperty("aut.homepage");
31 | }
32 |
33 | public Integer getWebTimeout() {
34 | return webTimeout;
35 | }
36 |
37 | public String getAutHomepage() {
38 | return autHomePage;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Vinh Nguyen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/main/java/keywords/Action.java:
--------------------------------------------------------------------------------
1 | package keywords;
2 |
3 | import com.google.inject.Inject;
4 | import ensure.Wait;
5 | import org.openqa.selenium.WebDriver;
6 | import org.openqa.selenium.WebElement;
7 | import org.openqa.selenium.interactions.Actions;
8 |
9 | public class Action {
10 |
11 | @Inject
12 | WebDriver driver;
13 |
14 | @Inject
15 | Wait wait;
16 |
17 | Actions builder;
18 |
19 | @Inject
20 | public Action(WebDriver driver) {
21 | this.driver = driver;
22 | wait = new Wait(driver);
23 | this.builder = new Actions(driver);
24 | }
25 |
26 | public void dragAndDrop(WebElement sourceElement, WebElement targetElement) {
27 | builder.dragAndDrop(sourceElement, targetElement).build().perform();
28 | }
29 |
30 | public void doubleClick() {
31 | builder.doubleClick().build().perform();
32 | }
33 |
34 | public void doubleClick(WebElement element) {
35 | builder.doubleClick(element).build().perform();
36 | }
37 |
38 | public void moveToElement(WebElement element) {
39 | builder.moveToElement(element).build().perform();
40 | }
41 |
42 | public void rightClick() {
43 | builder.contextClick().perform();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/webdriver/local/LocalDriverManager.java:
--------------------------------------------------------------------------------
1 | package webdriver.local;
2 |
3 | import org.openqa.selenium.remote.DesiredCapabilities;
4 | import webdriver.IDriver;
5 | import io.github.bonigarcia.wdm.WebDriverManager;
6 | import io.github.bonigarcia.wdm.config.DriverManagerType;
7 | import org.openqa.selenium.WebDriver;
8 |
9 | public class LocalDriverManager implements IDriver {
10 | @Override
11 | public WebDriver createInstance(String browser, DesiredCapabilities desiredCapabilities) {
12 | WebDriver driver;
13 | DriverManagerType driverManagerType = DriverManagerType.valueOf(browser.toUpperCase());
14 | WebDriverManager.getInstance(driverManagerType).setup();
15 | switch(driverManagerType) {
16 | case CHROME:
17 | driver = new ChromeDriverManager().createDriver(desiredCapabilities);
18 | break;
19 | case FIREFOX:
20 | driver = new FirefoxDriverManager().createDriver(desiredCapabilities);
21 | break;
22 | case EDGE:
23 | driver = new EdgeDriverManager().createDriver(desiredCapabilities);
24 | break;
25 | default:
26 | throw new IllegalArgumentException("Not supported browser");
27 | }
28 | return driver;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/pages/SignInPage.java:
--------------------------------------------------------------------------------
1 | package pages;
2 |
3 | import com.google.inject.Inject;
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 |
9 | public class SignInPage extends BasePage {
10 |
11 | @FindBy(css = "input[id='email']")
12 | private WebElement emailField;
13 |
14 | @FindBy(css = "input[id='password']")
15 | private WebElement passwordField;
16 |
17 | @FindBy(xpath = "//button[text()='Sign In']")
18 | private WebElement signInButton;
19 |
20 | @FindBy(css = "div[class='alert alert-danger']")
21 | private WebElement errorMessageDiv;
22 |
23 | @Inject
24 | public SignInPage(WebDriver driver) {
25 | super(driver);
26 | PageFactory.initElements(driver, this);
27 | }
28 |
29 | public SignInPage signIn(String email, String password) {
30 | elementKeywords.setText(emailField, email);
31 | elementKeywords.setText(passwordField, password);
32 | elementKeywords.click(signInButton);
33 | return this;
34 | }
35 |
36 | public String getErrorMessage() {
37 | return elementKeywords.getText(errorMessageDiv);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/reportportal/Launch.java:
--------------------------------------------------------------------------------
1 | package reportportal;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | public class Launch {
9 |
10 | private String uuid;
11 | private String id;
12 | private String description;
13 | private final List