Merge pull request #381 from mikementor/checks/e2e-checks
#380 example of E2E UI screenshot check
This commit is contained in:
commit
05af366f49
16 changed files with 714 additions and 0 deletions
3
kafka-ui-e2e-checks/.env.example
Normal file
3
kafka-ui-e2e-checks/.env.example
Normal file
|
@ -0,0 +1,3 @@
|
|||
USE_LOCAL_BROWSER=true
|
||||
SHOULD_START_SELENOID=false
|
||||
TURN_OFF_SCREENSHOTS=true
|
6
kafka-ui-e2e-checks/.gitignore
vendored
Normal file
6
kafka-ui-e2e-checks/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
.env
|
||||
build/
|
||||
allure-results/
|
||||
selenoid/video/
|
||||
target/
|
||||
selenoid/logs/
|
117
kafka-ui-e2e-checks/README.md
Normal file
117
kafka-ui-e2e-checks/README.md
Normal file
|
@ -0,0 +1,117 @@
|
|||
### E2E UI automation for Kafka-ui
|
||||
|
||||
This repository is for E2E UI automation.
|
||||
|
||||
### Table of Contents
|
||||
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [How to install](#how-to-install)
|
||||
- [Environment variables](#environment-variables)
|
||||
- [How to run checks](#how-to-run-checks)
|
||||
- [Reporting](#reporting)
|
||||
- [Environments setup](#environments-setup)
|
||||
- [Test Data](#test-data)
|
||||
- [Actions](#actions)
|
||||
- [Checks](#checks)
|
||||
- [Parallelization](#parallelization)
|
||||
- [How to develop](#how-to-develop)
|
||||
|
||||
### Prerequisites
|
||||
- Docker & Docker-compose
|
||||
- Java
|
||||
- Maven
|
||||
|
||||
### How to install
|
||||
```
|
||||
git clone https://github.com/provectus/kafka-ui.git
|
||||
cd kafka-ui-e2e-checks
|
||||
docker pull selenoid/vnc:chrome_86.0
|
||||
```
|
||||
### Environment variables
|
||||
|
||||
|Name | Default | Description
|
||||
|---------------------------------------|-------------|---------------------
|
||||
|`USE_LOCAL_BROWSER` | `true` | clear reports dir on startup
|
||||
|`CLEAR_REPORTS_DIR` | `true` | clear reports dir on startup
|
||||
|`SHOULD_START_SELENOID` | `false` | starts selenoid container on startup
|
||||
|`SELENOID_URL` | `http://localhost:4444/wd/hub` | URL of remote selenoid instance
|
||||
|`BASE_URL` | `http://192.168.1.2:8080/` | base url for selenide configuration
|
||||
|`PIXELS_THRESHOLD` | `200` | Amount of pixels, that should be different to fail screenshot check
|
||||
|`SCREENSHOTS_FOLDER` | `screenshots/` | folder for keeping reference screenshots
|
||||
|`DIFF_SCREENSHOTS_FOLDER` | `build/__diff__/` | folder for keeping screenshots diffs
|
||||
|`ACTUAL_SCREENSHOTS_FOLDER` | `build/__actual__/` | folder for keeping actual screenshots(during checks)
|
||||
|`SHOULD_SAVE_SCREENSHOTS_IF_NOT_EXIST` | `true` | folder for keeping actual screenshots(during checks)
|
||||
|`TURN_OFF_SCREENSHOTS` | `false` | If true, `compareScreenshots` will not fail on different screenshots. Useful for functional debugging on local machine, while preserving golden screenshots made in selenoid
|
||||
|
||||
### How to run checks
|
||||
|
||||
1. Run `kafka-ui`
|
||||
```
|
||||
cd docker
|
||||
docker-compose -f kafka-ui.yaml up -d
|
||||
```
|
||||
2. Run `selenoid-ui`
|
||||
```
|
||||
cd kafka-ui-e2e-checks/docker
|
||||
docker-compose -f selenoid.yaml up -d
|
||||
```
|
||||
3. Run checks
|
||||
```
|
||||
cd kafka-ui-e2e-checks
|
||||
mvn test
|
||||
```
|
||||
|
||||
* There are several ways to run checks
|
||||
|
||||
1. If you don't have selenoid run on your machine
|
||||
```
|
||||
mvn test -DSHOULD_START_SELENOID=true
|
||||
```
|
||||
⚠️ If you want to run checks in IDE with this approach, you'd need to set up
|
||||
environment variable(`SHOULD_START_SELENOID=true`) in `Run/Edit Configurations..`
|
||||
|
||||
2. For development purposes it is better to just start separate selenoid in docker-compose
|
||||
Do it in separate window
|
||||
```
|
||||
cd docker
|
||||
docker-compose -f selenoid.yaml up
|
||||
```
|
||||
Then you can just `mvn test`. By default, `SELENOID_URL` will resolve to `http://localhost:4444/wd/hub`
|
||||
|
||||
It's preferred way to run.
|
||||
|
||||
* If you have remote selenoid instance, set
|
||||
|
||||
`SELENOID_URL` environment variable
|
||||
|
||||
Example:
|
||||
`mvn test -DSELENOID_URL=http://localhost:4444/wd/hub`
|
||||
That's the way to run tests in CI with selenoid set up somewhere in cloud
|
||||
|
||||
### Reporting
|
||||
|
||||
Reports are in `allure-results` folder.
|
||||
If you have installed allure commandline(e.g. like [here](https://docs.qameta.io/allure/#_installing_a_commandline) or [here](https://www.npmjs.com/package/allure-commandline))
|
||||
You can see allure report with command:
|
||||
```
|
||||
allure serve
|
||||
```
|
||||
### Screenshots
|
||||
|
||||
Reference screenshots are in `SCREENSHOTS_FOLDER` (default,`kafka-ui-e2e-checks/screenshots`)
|
||||
|
||||
### How to develop
|
||||
> ⚠️ todo
|
||||
### Setting for different environments
|
||||
> ⚠️ todo
|
||||
### Test Data
|
||||
> ⚠️ todo
|
||||
### Actions
|
||||
> ⚠️ todo
|
||||
### Checks
|
||||
> ⚠️ todo
|
||||
### Parallelization
|
||||
> ⚠️ todo
|
||||
### Tips
|
||||
- install `Selenium UI Testing plugin` in IDEA
|
||||
|
25
kafka-ui-e2e-checks/docker/selenoid.yaml
Normal file
25
kafka-ui-e2e-checks/docker/selenoid.yaml
Normal file
|
@ -0,0 +1,25 @@
|
|||
version: '3'
|
||||
|
||||
services:
|
||||
selenoid:
|
||||
network_mode: bridge
|
||||
image: aerokube/selenoid:1.10.3
|
||||
volumes:
|
||||
- "../selenoid/config:/etc/selenoid"
|
||||
- "/var/run/docker.sock:/var/run/docker.sock"
|
||||
- "../selenoid/video:/video"
|
||||
- "../selenoid/logs:/opt/selenoid/logs"
|
||||
environment:
|
||||
- OVERRIDE_VIDEO_OUTPUT_DIR=video
|
||||
command: [ "-conf", "/etc/selenoid/browsers.json", "-video-output-dir", "/opt/selenoid/video", "-log-output-dir", "/opt/selenoid/logs" ]
|
||||
ports:
|
||||
- "4444:4444"
|
||||
|
||||
selenoid-ui:
|
||||
network_mode: bridge
|
||||
image: aerokube/selenoid-ui:latest-release
|
||||
links:
|
||||
- selenoid
|
||||
ports:
|
||||
- "8081:8080"
|
||||
command: [ "--selenoid-uri", "http://selenoid:4444" ]
|
182
kafka-ui-e2e-checks/pom.xml
Normal file
182
kafka-ui-e2e-checks/pom.xml
Normal file
|
@ -0,0 +1,182 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>kafka-ui</artifactId>
|
||||
<groupId>com.provectus</groupId>
|
||||
<version>0.0.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>kafka-ui-e2e-checks</artifactId>
|
||||
<properties>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<junit.version>5.7.0</junit.version>
|
||||
<aspectj.version>1.9.6</aspectj.version>
|
||||
<allure.version>2.13.7</allure.version>
|
||||
<testcontainers.version>1.15.2</testcontainers.version>
|
||||
<selenide.version>5.16.2</selenide.version>
|
||||
<assertj.version>3.17.1</assertj.version>
|
||||
<google.auto-service.version>1.0-rc7</google.auto-service.version>
|
||||
<hamcrest.version>2.2</hamcrest.version>
|
||||
<slf4j.version>1.7.29</slf4j.version>
|
||||
<testcontainers.junit-jupiter.version>1.15.1</testcontainers.junit-jupiter.version>
|
||||
<allure.java-commons.version>2.13.6</allure.java-commons.version>
|
||||
<dotenv.version>2.2.0</dotenv.version>
|
||||
<junit.platform-launcher.version>1.6.2</junit.platform-launcher.version>
|
||||
<allure.maven-plugin.version>2.6</allure.maven-plugin.version>
|
||||
<ashot.version>1.5.4</ashot.version>
|
||||
<allure.screendiff-plugin.version>2.13.9</allure.screendiff-plugin.version>
|
||||
<maven.surefire-plugin.version>2.22.2</maven.surefire-plugin.version>
|
||||
<allure-maven.version>2.10.0</allure-maven.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.kafka</groupId>
|
||||
<artifactId>kafka_2.13</artifactId>
|
||||
<version>${kafka.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>testcontainers</artifactId>
|
||||
<version>${testcontainers.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.qameta.allure</groupId>
|
||||
<artifactId>allure-junit5</artifactId>
|
||||
<version>${allure.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.codeborne</groupId>
|
||||
<artifactId>selenide</artifactId>
|
||||
<version>${selenide.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.qameta.allure</groupId>
|
||||
<artifactId>allure-selenide</artifactId>
|
||||
<version>${allure.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest</artifactId>
|
||||
<version>${hamcrest.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto.service</groupId>
|
||||
<artifactId>auto-service</artifactId>
|
||||
<version>${google.auto-service.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${org.projectlombok.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>${aspectj.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${testcontainers.junit-jupiter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.qameta.allure</groupId>
|
||||
<artifactId>allure-java-commons</artifactId>
|
||||
<version>${allure.java-commons.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.cdimascio</groupId>
|
||||
<artifactId>dotenv-java</artifactId>
|
||||
<version>${dotenv.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-launcher</artifactId>
|
||||
<version>${junit.platform-launcher.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.yandex.qatools.allure</groupId>
|
||||
<artifactId>allure-maven-plugin</artifactId>
|
||||
<version>${allure.maven-plugin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.yandex.qatools.ashot</groupId>
|
||||
<artifactId>ashot</artifactId>
|
||||
<version>${ashot.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.seleniumhq.selenium</groupId>
|
||||
<artifactId>selenium-remote-driver</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.qameta.allure.plugins</groupId>
|
||||
<artifactId>screen-diff-plugin</artifactId>
|
||||
<version>${allure.screendiff-plugin.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven.surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<argLine>
|
||||
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
|
||||
</argLine>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>${aspectj.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>io.qameta.allure</groupId>
|
||||
<artifactId>allure-maven</artifactId>
|
||||
<version>${allure-maven.version}</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>15</source>
|
||||
<target>15</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
BIN
kafka-ui-e2e-checks/screenshots/main.png
Normal file
BIN
kafka-ui-e2e-checks/screenshots/main.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 227 KiB |
11
kafka-ui-e2e-checks/selenoid/config/browsers.json
Normal file
11
kafka-ui-e2e-checks/selenoid/config/browsers.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"chrome": {
|
||||
"default": "86.0",
|
||||
"versions": {
|
||||
"86.0": {
|
||||
"image": "selenoid/vnc:chrome_86.0",
|
||||
"port": "4444"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package com.provectus.kafka.ui.base;
|
||||
|
||||
import com.codeborne.selenide.Configuration;
|
||||
import com.codeborne.selenide.logevents.SelenideLogger;
|
||||
import com.provectus.kafka.ui.pages.Pages;
|
||||
import com.provectus.kafka.ui.screenshots.Screenshooter;
|
||||
import io.github.cdimascio.dotenv.Dotenv;
|
||||
import io.qameta.allure.selenide.AllureSelenide;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.DisplayNameGeneration;
|
||||
import org.openqa.selenium.remote.DesiredCapabilities;
|
||||
import org.testcontainers.containers.BindMode;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static com.codeborne.selenide.Selenide.closeWebDriver;
|
||||
|
||||
@Slf4j
|
||||
@DisplayNameGeneration(CamelCaseToSpacedDisplayNameGenerator.class)
|
||||
public class BaseTest {
|
||||
|
||||
protected Pages pages = Pages.INSTANCE;
|
||||
|
||||
private Screenshooter screenshooter = new Screenshooter();
|
||||
|
||||
public void compareScreenshots(String name) {
|
||||
screenshooter.compareScreenshots(name);
|
||||
}
|
||||
|
||||
public void compareScreenshots(String name, Boolean shouldUpdateScreenshots) {
|
||||
screenshooter.compareScreenshots(name, shouldUpdateScreenshots);
|
||||
}
|
||||
|
||||
public static GenericContainer selenoid =
|
||||
new GenericContainer(DockerImageName.parse("aerokube/selenoid:latest-release"))
|
||||
.withExposedPorts(4444)
|
||||
.withFileSystemBind("selenoid/config/", "/etc/selenoid", BindMode.READ_WRITE)
|
||||
.withFileSystemBind("/var/run/docker.sock", "/var/run/docker.sock", BindMode.READ_WRITE)
|
||||
.withFileSystemBind("selenoid/video", "/opt/selenoid/video", BindMode.READ_WRITE)
|
||||
.withFileSystemBind("selenoid/logs", "/opt/selenoid/logs", BindMode.READ_WRITE)
|
||||
.withEnv("OVERRIDE_VIDEO_OUTPUT_DIR", "/opt/selenoid/video")
|
||||
.withCommand(
|
||||
"-conf", "/etc/selenoid/browsers.json", "-log-output-dir", "/opt/selenoid/logs");
|
||||
|
||||
static {
|
||||
Dotenv.load().entries().forEach(env -> System.setProperty(env.getKey(), env.getValue()));
|
||||
if (TestConfiguration.CLEAR_REPORTS_DIR) {
|
||||
clearReports();
|
||||
}
|
||||
setupSelenoid();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void afterAll() {
|
||||
closeWebDriver();
|
||||
selenoid.close();
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private static void setupSelenoid() {
|
||||
String remote = TestConfiguration.SELENOID_URL;
|
||||
if (TestConfiguration.SHOULD_START_SELENOID) {
|
||||
selenoid.start();
|
||||
remote =
|
||||
"http://%s:%s/wd/hub"
|
||||
.formatted(selenoid.getContainerIpAddress(), selenoid.getMappedPort(4444));
|
||||
}
|
||||
|
||||
Configuration.reportsFolder = TestConfiguration.REPORTS_FOLDER;
|
||||
if (!TestConfiguration.USE_LOCAL_BROWSER) {
|
||||
Configuration.remote = remote;
|
||||
TestConfiguration.BASE_URL = TestConfiguration.BASE_URL.replace("localhost", "host.docker.internal");
|
||||
}
|
||||
Configuration.screenshots = TestConfiguration.SCREENSHOTS;
|
||||
Configuration.savePageSource = TestConfiguration.SAVE_PAGE_SOURCE;
|
||||
Configuration.reopenBrowserOnFail = TestConfiguration.REOPEN_BROWSER_ON_FAIL;
|
||||
Configuration.browser = TestConfiguration.BROWSER;
|
||||
Configuration.baseUrl = TestConfiguration.BASE_URL;
|
||||
Configuration.browserSize = TestConfiguration.BROWSER_SIZE;
|
||||
var capabilities = new DesiredCapabilities();
|
||||
capabilities.setCapability("enableVNC", TestConfiguration.ENABLE_VNC);
|
||||
Configuration.browserCapabilities = capabilities;
|
||||
|
||||
SelenideLogger.addListener("allure", new AllureSelenide().savePageSource(false));
|
||||
}
|
||||
|
||||
public static void clearReports() {
|
||||
log.info("Clearing reports dir [%s]...".formatted(TestConfiguration.REPORTS_FOLDER));
|
||||
File allureResults = new File(TestConfiguration.REPORTS_FOLDER);
|
||||
if (allureResults.isDirectory()) {
|
||||
File[] list = allureResults.listFiles();
|
||||
if (list != null)
|
||||
Arrays.stream(list)
|
||||
.sequential()
|
||||
.filter(e -> !e.getName().equals("categories.json"))
|
||||
.forEach(File::delete);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.provectus.kafka.ui.base;
|
||||
|
||||
import org.junit.jupiter.api.DisplayNameGenerator;
|
||||
import org.junit.platform.commons.util.ClassUtils;
|
||||
import org.junit.platform.commons.util.Preconditions;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class CamelCaseToSpacedDisplayNameGenerator implements DisplayNameGenerator {
|
||||
@Override
|
||||
public String generateDisplayNameForClass(Class<?> testClass) {
|
||||
String name = testClass.getName();
|
||||
int lastDot = name.lastIndexOf('.');
|
||||
return name.substring(lastDot + 1).replaceAll("([A-Z])", " $1").toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateDisplayNameForNestedClass(Class<?> nestedClass) {
|
||||
return nestedClass.getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateDisplayNameForMethod(Class<?> testClass, Method testMethod) {
|
||||
return testMethod.getName().replaceAll("([A-Z])", " $1").toLowerCase()
|
||||
+ parameterTypesAsString(testMethod);
|
||||
}
|
||||
|
||||
static String parameterTypesAsString(Method method) {
|
||||
Preconditions.notNull(method, "Method must not be null");
|
||||
return method.getParameterTypes().length == 0
|
||||
? ""
|
||||
: '(' + ClassUtils.nullSafeToString(Class::getSimpleName, method.getParameterTypes()) + ')';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.provectus.kafka.ui.base;
|
||||
|
||||
public class TestConfiguration {
|
||||
public static boolean CLEAR_REPORTS_DIR =
|
||||
Boolean.parseBoolean(System.getProperty("CLEAR_REPORTS_DIR", "true"));
|
||||
|
||||
public static boolean SHOULD_START_SELENOID =
|
||||
Boolean.parseBoolean(System.getProperty("SHOULD_START_SELENOID", "false"));
|
||||
|
||||
public static String BASE_URL = System.getProperty("BASE_URL", "http://localhost:8080/");
|
||||
|
||||
public static boolean USE_LOCAL_BROWSER =
|
||||
Boolean.parseBoolean(System.getProperty("USE_LOCAL_BROWSER", "true"));
|
||||
|
||||
public static String SELENOID_URL =
|
||||
System.getProperty("SELENOID_URL", "http://localhost:4444/wd/hub");
|
||||
public static String REPORTS_FOLDER = System.getProperty("REPORTS_FOLDER", "allure-results");
|
||||
public static Boolean SCREENSHOTS =
|
||||
Boolean.parseBoolean(System.getProperty("SCREENSHOTS", "false"));
|
||||
public static Boolean SAVE_PAGE_SOURCE =
|
||||
Boolean.parseBoolean(System.getProperty("SAVE_PAGE_SOURCE", "false"));
|
||||
public static Boolean REOPEN_BROWSER_ON_FAIL =
|
||||
Boolean.parseBoolean(System.getProperty("REOPEN_BROWSER_ON_FAIL", "true"));
|
||||
public static String BROWSER = System.getProperty("BROWSER", "chrome");
|
||||
public static String BROWSER_SIZE = System.getProperty("BROWSER_SIZE", "1920x1080");
|
||||
public static Boolean ENABLE_VNC = Boolean.parseBoolean(System.getProperty("ENABLE_VNC", "true"));
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.provectus.kafka.ui.pages;
|
||||
|
||||
import com.codeborne.selenide.Condition;
|
||||
import io.qameta.allure.Step;
|
||||
import org.openqa.selenium.By;
|
||||
|
||||
import static com.codeborne.selenide.Selenide.$;
|
||||
|
||||
public class MainPage {
|
||||
|
||||
@Step
|
||||
public void shouldBeOnPage(){
|
||||
$(By.xpath("//*[contains(text(),'Loading')]")).shouldBe(Condition.disappear);
|
||||
$(By.xpath("//h5[text()='Clusters']")).shouldBe(Condition.visible);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.provectus.kafka.ui.pages;
|
||||
|
||||
import com.codeborne.selenide.Selenide;
|
||||
import com.provectus.kafka.ui.base.TestConfiguration;
|
||||
|
||||
public class Pages {
|
||||
|
||||
public static Pages INSTANCE = new Pages();
|
||||
|
||||
public MainPage mainPage = new MainPage();
|
||||
|
||||
public Pages goTo(String path) {
|
||||
Selenide.open(TestConfiguration.BASE_URL+path);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
package com.provectus.kafka.ui.screenshots;
|
||||
|
||||
import io.qameta.allure.Allure;
|
||||
import io.qameta.allure.Attachment;
|
||||
import lombok.SneakyThrows;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ru.yandex.qatools.ashot.AShot;
|
||||
import ru.yandex.qatools.ashot.Screenshot;
|
||||
import ru.yandex.qatools.ashot.comparison.ImageDiff;
|
||||
import ru.yandex.qatools.ashot.comparison.ImageDiffer;
|
||||
import ru.yandex.qatools.ashot.coordinates.WebDriverCoordsProvider;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.util.List;
|
||||
|
||||
import static com.codeborne.selenide.WebDriverRunner.getWebDriver;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class Screenshooter {
|
||||
|
||||
public static Logger log = LoggerFactory.getLogger(Screenshooter.class);
|
||||
|
||||
private static int PIXELS_THRESHOLD =
|
||||
Integer.parseInt(System.getProperty("PIXELS_THRESHOLD", "200"));
|
||||
private static String SCREENSHOTS_FOLDER =
|
||||
System.getProperty("SCREENSHOTS_FOLDER", "screenshots/");
|
||||
private static String DIFF_SCREENSHOTS_FOLDER =
|
||||
System.getProperty("DIFF_SCREENSHOTS_FOLDER", "build/__diff__/");
|
||||
private static String ACTUAL_SCREENSHOTS_FOLDER =
|
||||
System.getProperty("ACTUAL_SCREENSHOTS_FOLDER", "build/__actual__/");
|
||||
private static boolean SHOULD_SAVE_SCREENSHOTS_IF_NOT_EXIST =
|
||||
Boolean.parseBoolean(System.getProperty("SHOULD_SAVE_SCREENSHOTS_IF_NOT_EXIST", "true"));
|
||||
private static boolean TURN_OFF_SCREENSHOTS =
|
||||
Boolean.parseBoolean(System.getProperty("TURN_OFF_SCREENSHOTS", "false"));
|
||||
|
||||
private File newFile(String name) {
|
||||
var file = new File(name);
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
public Screenshooter() {
|
||||
List.of(SCREENSHOTS_FOLDER, DIFF_SCREENSHOTS_FOLDER, ACTUAL_SCREENSHOTS_FOLDER)
|
||||
.forEach(this::newFile);
|
||||
}
|
||||
|
||||
public void compareScreenshots(String name) {
|
||||
compareScreenshots(name, false);
|
||||
}
|
||||
|
||||
public void compareScreenshots(String name, boolean shouldUpdateScreenshotIfDiffer) {
|
||||
if (TURN_OFF_SCREENSHOTS) {
|
||||
return;
|
||||
}
|
||||
if (!doesScreenshotExist(name)) {
|
||||
if (SHOULD_SAVE_SCREENSHOTS_IF_NOT_EXIST) {
|
||||
updateActualScreenshot(name);
|
||||
} else {
|
||||
fail("no reference screenshot found for %s".formatted(name));
|
||||
}
|
||||
} else {
|
||||
makeImageDiff(name, shouldUpdateScreenshotIfDiffer);
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private void updateActualScreenshot(String name) {
|
||||
Screenshot actual =
|
||||
new AShot().coordsProvider(new WebDriverCoordsProvider()).takeScreenshot(getWebDriver());
|
||||
File file= newFile(SCREENSHOTS_FOLDER + name + ".png");
|
||||
ImageIO.write(actual.getImage(), "png", file);
|
||||
log.debug("created screenshot: %s \n at $s".formatted(name,file.getAbsolutePath()));
|
||||
}
|
||||
|
||||
private static boolean doesScreenshotExist(String name) {
|
||||
return new File(SCREENSHOTS_FOLDER + name + ".png").exists();
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private void makeImageDiff(String expectedName, boolean shouldUpdateScreenshotIfDiffer) {
|
||||
String fullPathNameExpected = SCREENSHOTS_FOLDER + expectedName + ".png";
|
||||
String fullPathNameActual = ACTUAL_SCREENSHOTS_FOLDER + expectedName + ".png";
|
||||
String fullPathNameDiff = DIFF_SCREENSHOTS_FOLDER + expectedName + ".png";
|
||||
|
||||
// activating allure plugin for showing diffs in report
|
||||
Allure.label("testType", "screenshotDiff");
|
||||
|
||||
Screenshot actual =
|
||||
new AShot().coordsProvider(new WebDriverCoordsProvider()).takeScreenshot(getWebDriver());
|
||||
ImageIO.write(actual.getImage(), "png", newFile(fullPathNameActual));
|
||||
|
||||
Screenshot expected = new Screenshot(ImageIO.read(newFile(fullPathNameExpected)));
|
||||
ImageDiff diff = new ImageDiffer().makeDiff(actual, expected);
|
||||
BufferedImage diffImage = diff.getMarkedImage();
|
||||
ImageIO.write(diffImage, "png", newFile(fullPathNameDiff));
|
||||
// adding to report
|
||||
diff(fullPathNameDiff);
|
||||
// adding to report
|
||||
actual(fullPathNameActual);
|
||||
// adding to report
|
||||
expected(fullPathNameExpected);
|
||||
|
||||
if (shouldUpdateScreenshotIfDiffer) {
|
||||
if (diff.getDiffSize() > PIXELS_THRESHOLD) {
|
||||
updateActualScreenshot(expectedName);
|
||||
}
|
||||
} else {
|
||||
Assertions.assertTrue(
|
||||
PIXELS_THRESHOLD >= diff.getDiffSize(),
|
||||
("""
|
||||
Amount of differing pixels should be less or equals than %s, actual %s
|
||||
diff file: %s
|
||||
""")
|
||||
.formatted(PIXELS_THRESHOLD, diff.getDiffSize(), FileSystems.getDefault().getPath(fullPathNameDiff).normalize().toAbsolutePath().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private byte[] imgToBytes(String filename) {
|
||||
BufferedImage bImage2 = ImageIO.read(new File(filename));
|
||||
ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
|
||||
ImageIO.write(bImage2, "png", bos2);
|
||||
return bos2.toByteArray();
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Attachment
|
||||
private byte[] actual(String actualFileName) {
|
||||
return imgToBytes(actualFileName);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Attachment
|
||||
private byte[] expected(String expectedFileName) {
|
||||
return imgToBytes(expectedFileName);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Attachment
|
||||
private byte[] diff(String diffFileName) {
|
||||
return imgToBytes(diffFileName);
|
||||
}
|
||||
}
|
2
kafka-ui-e2e-checks/src/main/resources/allure.properties
Normal file
2
kafka-ui-e2e-checks/src/main/resources/allure.properties
Normal file
|
@ -0,0 +1,2 @@
|
|||
allure.results.directory=allure-results
|
||||
allure.link.issue.pattern=https://github.com/provectus/kafka-ui/issues/{}
|
|
@ -0,0 +1,20 @@
|
|||
package com.provectus.kafka.ui;
|
||||
|
||||
import com.provectus.kafka.ui.base.BaseTest;
|
||||
import io.qameta.allure.Issue;
|
||||
import lombok.SneakyThrows;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SmokeTests extends BaseTest {
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
@DisplayName("main page should load")
|
||||
@Issue("380")
|
||||
void mainPageLoads() {
|
||||
pages.goTo("")
|
||||
.mainPage.shouldBeOnPage();
|
||||
compareScreenshots("main");
|
||||
}
|
||||
}
|
1
pom.xml
1
pom.xml
|
@ -6,6 +6,7 @@
|
|||
<modules>
|
||||
<module>kafka-ui-contract</module>
|
||||
<module>kafka-ui-api</module>
|
||||
<module>kafka-ui-e2e-checks</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
|
Loading…
Add table
Reference in a new issue