From e3b7b6a76d148d56d354ca54f14e96307868f400 Mon Sep 17 00:00:00 2001 From: latlon team <info@lat-lon.de> Date: Mon, 5 Feb 2024 07:48:55 +0000 Subject: [PATCH] Code drop - XPLANBOX-2327 - added arguments (edd757940) - XPLANBOX-2327 - set TZ=Europe/Berlin (5d397604c) - XPLANBOX-2327 - set default values of baseUrlValidatorWeb/BASE_URL_Validator_WEB (5e480940c) - XPLANBOX-2327 - set maven.install.skip=true, maven.deploy.skip=true, enforcer.skip=true (d03ec5e18) - XPLANBOX-2327 - fixed version of parent (726fd20d3) - XPLANBOX-2327 ignore certificate errors (903950171) - XPLANBOX-2327 first selenium test (cleaned) (cac5cbbab) Co-authored-by: Lyn Elisa Goltz <goltz@lat-lon.de> Co-authored-by: Marc Guillemot <guillemot@lat-lon.de> Dropped from commit: d1cd6d515a6757d88a38a6f89c2a1120f04b09f3 --- jenkinsfiles/test/Jenkinsfile | 21 +- xplan-tests/pom.xml | 1 + .../xplan-tests-selenium/.dockerignore | 3 + xplan-tests/xplan-tests-selenium/Dockerfile | 34 ++++ xplan-tests/xplan-tests-selenium/README.md | 43 ++++ xplan-tests/xplan-tests-selenium/pom.xml | 122 +++++++++++ .../runAllSeleniumTests.sh | 49 +++++ .../validatorweb/XPlanValidatorWebIT.java | 189 ++++++++++++++++++ .../src/test/resources/BPlan001_5-4.zip | Bin 0 -> 2935 bytes 9 files changed, 457 insertions(+), 5 deletions(-) create mode 100644 xplan-tests/xplan-tests-selenium/.dockerignore create mode 100644 xplan-tests/xplan-tests-selenium/Dockerfile create mode 100644 xplan-tests/xplan-tests-selenium/README.md create mode 100644 xplan-tests/xplan-tests-selenium/pom.xml create mode 100755 xplan-tests/xplan-tests-selenium/runAllSeleniumTests.sh create mode 100644 xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/selenium/validatorweb/XPlanValidatorWebIT.java create mode 100644 xplan-tests/xplan-tests-selenium/src/test/resources/BPlan001_5-4.zip diff --git a/jenkinsfiles/test/Jenkinsfile b/jenkinsfiles/test/Jenkinsfile index 09a3939c37..c227917d2e 100644 --- a/jenkinsfiles/test/Jenkinsfile +++ b/jenkinsfiles/test/Jenkinsfile @@ -13,6 +13,7 @@ pipeline { string(name: 'BASE_URL_DIENSTE', defaultValue: "https://xplanbox.lat-lon.de", description: 'Set base URL of XPlanDienste') string(name: 'BASE_URL_INSPIRE_PLU', defaultValue: "https://xplanbox.lat-lon.de", description: 'Set base URL of INSPIRE PLU') string(name: 'BASE_URL_MANAGER_API', defaultValue: "https://xplanbox.lat-lon.de", description: 'Set base URL of XPlanManagerAPI') + string(name: 'BASE_URL_Validator_WEB', defaultValue: "https://xplanbox.lat-lon.de/xplan-validator-web", description: 'Set base URL of XPlanValidatorWeb') string(name: 'BASE_URL_DOKUMENTEN_API', defaultValue: "https://xplanbox.lat-lon.de", description: 'Set base URL of XPlanDokumentenAPI') string(name: 'BASE_URL_MAPSERVER', defaultValue: "https://xplanbox.lat-lon.de", description: 'Set base URL of MapServer') string(name: 'BASE_URL_MAPPROXY', defaultValue: "https://xplanbox.lat-lon.de", description: 'Set base URL of MapProxy') @@ -22,7 +23,7 @@ pipeline { string(name: 'SLACK_TOKEN_CREDENTIAL_ID', defaultValue: "slack-integration-id", description: 'Set slack token credential id') } stages { - stage('Test XPlanManagerAPI') { + stage('SoapUI-Test XPlanManagerAPI') { steps { withCredentials([ usernamePassword(credentialsId:"${CREDENTIALS_ID}", passwordVariable: 'Password', usernameVariable: 'Username') @@ -31,7 +32,7 @@ pipeline { } } } - stage('Test XPlanValidatorAPI') { + stage('SoapUI-Test XPlanValidatorAPI') { steps { withCredentials([ usernamePassword(credentialsId:"${CREDENTIALS_ID}", passwordVariable: 'Password', usernameVariable: 'Username') @@ -40,7 +41,7 @@ pipeline { } } } - stage('Test XPlanDokumentenAPI') { + stage('SoapUI-Test XPlanDokumentenAPI') { steps { withCredentials([ usernamePassword(credentialsId:"${CREDENTIALS_ID}", passwordVariable: 'Password', usernameVariable: 'Username') @@ -49,7 +50,7 @@ pipeline { } } } - stage('Test XPlanManagerWeb') { + stage('SoapUI-Test XPlanManagerWeb') { steps { withCredentials([ usernamePassword(credentialsId:"${CREDENTIALS_ID}", passwordVariable: 'Password', usernameVariable: 'Username') @@ -58,7 +59,7 @@ pipeline { } } } - stage('Test XPlanDienste') { + stage('SoapUI-Test XPlanDienste') { steps { withCredentials([ usernamePassword(credentialsId:"${CREDENTIALS_ID}", passwordVariable: 'Password', usernameVariable: 'Username') @@ -67,9 +68,19 @@ pipeline { } } } + stage('Selenium-Test XPlanValidatorWeb') { + steps { + withCredentials([ + usernamePassword(credentialsId:"${CREDENTIALS_ID}", passwordVariable: 'Password', usernameVariable: 'Username') + ]) { + sh 'mvn integration-test -pl :xplan-tests-selenium -Psystem-tests -DbaseUrlValidatorWeb=${BASE_URL_Validator_WEB} -Dusername=$Username -Dpassword=$Password' + } + } + } stage('Results') { steps{ junit '**/**/target/soapui/TEST-*.xml' + junit '**/**/target/failsafe-reports/TEST-*.xml' } } } diff --git a/xplan-tests/pom.xml b/xplan-tests/pom.xml index 0035579bb1..97e51a3824 100644 --- a/xplan-tests/pom.xml +++ b/xplan-tests/pom.xml @@ -19,6 +19,7 @@ <modules> <module>xplan-tests-soapui</module> <module>xplan-tests-manual</module> + <module>xplan-tests-selenium</module> </modules> </project> \ No newline at end of file diff --git a/xplan-tests/xplan-tests-selenium/.dockerignore b/xplan-tests/xplan-tests-selenium/.dockerignore new file mode 100644 index 0000000000..425b773149 --- /dev/null +++ b/xplan-tests/xplan-tests-selenium/.dockerignore @@ -0,0 +1,3 @@ +target/** +Dockerfile +.settings/* \ No newline at end of file diff --git a/xplan-tests/xplan-tests-selenium/Dockerfile b/xplan-tests/xplan-tests-selenium/Dockerfile new file mode 100644 index 0000000000..69d2336b13 --- /dev/null +++ b/xplan-tests/xplan-tests-selenium/Dockerfile @@ -0,0 +1,34 @@ +FROM maven:3.9-eclipse-temurin-11-alpine +ARG BUILD_DATE=? +ARG DOCKER_IMAGE_NAME=? +ARG GIT_REVISION=? +ARG XPLANBOX_VERSION=latest + +# see https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys +LABEL "org.opencontainers.image.created"="$BUILD_DATE" \ + "org.opencontainers.image.description"="ozgxplanung xPlanBox component" \ + "org.opencontainers.image.licenses"="GNU Affero General Public License & others" \ + "org.opencontainers.image.ref.name"="$DOCKER_IMAGE_NAME" \ + "org.opencontainers.image.revision"="$GIT_REVISION" \ + "org.opencontainers.image.title"="ozgxplanung - $DOCKER_IMAGE_NAME" \ + "org.opencontainers.image.url"="https://gitlab.opencode.de/diplanung/ozgxplanung" \ + "org.opencontainers.image.vendor"="lat/lon GmbH" \ + "org.opencontainers.image.version"="$XPLANBOX_VERSION" + +RUN apk add py3-pip py3-pillow py3-cffi py3-brotli gcc musl-dev python3-dev pango pango-tools aws-cli chromium chromium-chromedriver xvfb +RUN pip install weasyprint + +ADD . /xplanbox/xplan-tests/xplan-tests-selenium +ADD maven/xplanbox-pom.xml /xplanbox/pom.xml +ADD maven/xplan-tests-pom.xml /xplanbox/xplan-tests/pom.xml + +WORKDIR /xplanbox/xplan-tests/xplan-tests-selenium + +ENV TZ=Europe/Berlin + +# pre-fill local maven repo (including plugins) +RUN mvn -B integration-test -Psystem-tests -Dtest=NotExistingOne -Dsurefire.failIfNoSpecifiedTests=false > /dev/null \ + && mvn -B surefire-report:report-only \ + && rm -rf target + +ENTRYPOINT ["/xplanbox/xplan-tests/xplan-tests-selenium/runAllSeleniumTests.sh"] \ No newline at end of file diff --git a/xplan-tests/xplan-tests-selenium/README.md b/xplan-tests/xplan-tests-selenium/README.md new file mode 100644 index 0000000000..00054be033 --- /dev/null +++ b/xplan-tests/xplan-tests-selenium/README.md @@ -0,0 +1,43 @@ +# Selenium Tests + +Die Tests in diesem Projekt sind nicht gedacht, um direkt als Teil vom Build ausgeführt zu werden sondern eher zu einem späteren Zeitpunkt, wenn die Anwendungen schon deployt worden sind. + +## Ausführung mit Maven + +``` +mvn clean integration-test -Psystem-tests -DbaseUrlValidatorWeb=https://xplanbox.lat-lon.de/xplan-validator-web -Dpassword='PWD' -Dusername=xplanbox +``` + +## Ausführung im Docker Container + +Die Selenium Tests können in einem Docker Container ausgeführt werden + +``` +docker run --env XPLAN_WEB_VALIDATOR_BASE_URL=... xplanbox/xplan-tests-selenium +``` + +### Umgebungsvariablen + +- `XPLAN_WEB_VALIDATOR_BASE_URL` +- `XPLAN_WEB_VALIDATOR_USERNAME` +- `XPLAN_WEB_VALIDATOR_PASSWORD` + +Der Report im PDF Format kann zu einem S3 Bucket hochgeladen werden, dafür müssen folgende Umgebungsvariablen gesetzt werden: + +- `XPLAN_UPLOAD_TEST_REPORT`: muss auf `true` gesetzt werden +- `XPLAN_S3_ENDPOINT`: die S3 Url +- `XPLAN_S3_REPORT_ID` (optional): ein Id, dass im S3-Objektname verwendet werden soll +- `XPLAN_S3_REPORT_PATH`(optional): der Pfad im S3 Bucket (default: `test-reports`) +- `XPLAN_S3_ACCESS_KEY`: der S3-Zugangschlüssel +- `XPLAN_S3_SECRET_ACCESS_KEY`: der S3-Geheimzugangschlüssel +- `XPLAN_S3_REGION`: die S3 Region +- `XPLAN_S3_BUCKET_NAME`: der Name des Buckets + +Der Report kann aus S3 lokal kopiert werden, z,B. mit: + + aws s3 cp s3://my-bucket/test-reports/report-2023-05-26T08:57:15.pdf report.pdf --endpoint-url https://the.s3.url + +Eine Notification kann nach der Ausführung der Tests zu einem Slack Chanel geschickt werden. Dafür müssen folgende Umgebungsvariablen gesetzt werden: + +- `XPLAN_NOTIFY_SLACK_CHANNEL`: der Slack Kanal +- `XPLAN_NOTIFY_SLACK_TOKEN`: das Slack Authorisierungstoken diff --git a/xplan-tests/xplan-tests-selenium/pom.xml b/xplan-tests/xplan-tests-selenium/pom.xml new file mode 100644 index 0000000000..ea05632a98 --- /dev/null +++ b/xplan-tests/xplan-tests-selenium/pom.xml @@ -0,0 +1,122 @@ +<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <artifactId>xplan-tests-selenium</artifactId> + + <parent> + <groupId>de.latlon.product.xplanbox</groupId> + <artifactId>xplan-tests</artifactId> + <version>7.2-SNAPSHOT</version> + </parent> + + <properties> + <maven.test.skip>true</maven.test.skip> + <maven.install.skip>true</maven.install.skip> + <maven.deploy.skip>true</maven.deploy.skip> + <enforcer.skip>true</enforcer.skip> + </properties> + + <dependencies> + <dependency> + <groupId>org.seleniumhq.selenium</groupId> + <artifactId>selenium-remote-driver</artifactId> + <version>4.12.1</version> + </dependency> + <dependency> + <groupId>org.seleniumhq.selenium</groupId> + <artifactId>selenium-chrome-driver</artifactId> + <version>4.12.1</version> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <skipIfEmpty>true</skipIfEmpty> + </configuration> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>system-tests</id> + <properties> + <baseUrlValidatorWeb/> + <maven.test.skip>false</maven.test.skip> + <password/> + <username/> + </properties> + <build> + <plugins> + <plugin> + <groupId>io.github.git-commit-id</groupId> + <artifactId>git-commit-id-maven-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <configuration> + <systemPropertyVariables> + <baseUrlValidatorWeb>${baseUrlValidatorWeb}</baseUrlValidatorWeb> + <username>${username}</username> + <password>${password}</password> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>docker</id> + <properties> + <docker-image.skip>false</docker-image.skip> + </properties> + <build> + <plugins> + <plugin> + <groupId>io.fabric8</groupId> + <artifactId>docker-maven-plugin</artifactId> + <configuration> + <images> + <image> + <build> + <assembly> + <inline> + <files> + <file> + <source>../pom.xml</source> + <destName>xplan-tests-pom.xml</destName> + </file> + <file> + <source>../../pom.xml</source> + <destName>xplanbox-pom.xml</destName> + </file> + </files> + </inline> + </assembly> + </build> + </image> + </images> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> \ No newline at end of file diff --git a/xplan-tests/xplan-tests-selenium/runAllSeleniumTests.sh b/xplan-tests/xplan-tests-selenium/runAllSeleniumTests.sh new file mode 100755 index 0000000000..ea36420295 --- /dev/null +++ b/xplan-tests/xplan-tests-selenium/runAllSeleniumTests.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# start virtual buffer +Xvfb :0 -screen 0 1024x768x24 & +xvfbPid=$! + +echo "Executing tests..." +DISPLAY=:0 mvn integration-test -Psystem-tests -DbaseUrlValidatorWeb=$XPLAN_WEB_VALIDATOR_BASE_URL -Dusername=$XPLAN_WEB_VALIDATOR_USERNAME -Dpassword=$XPLAN_WEB_VALIDATOR_PASSWORD -Dwebdriver.chrome.driver=/usr/bin/chromedriver +kill -9 $xvfbPid + +echo "Generating html report..." +mvn surefire-report:failsafe-report-only -q + +REPORT_PATH_PDF=target/test-report.pdf +echo "Transforming to PDF $REPORT_PATH_PDF..." +sed -i 's/display:none;//' target/site/failsafe-report.html +weasyprint file://$PWD/target/site/failsafe-report.html $REPORT_PATH_PDF +REPORT_PATH_TAR=target/test-report.tar.gz +tar czf $REPORT_PATH_TAR -C target/site . + +if [ "$XPLAN_UPLOAD_TEST_REPORT" = "true" ]; +then + export AWS_ACCESS_KEY_ID="$XPLAN_S3_ACCESS_KEY" + export AWS_SECRET_ACCESS_KEY="$XPLAN_S3_SECRET_ACCESS_KEY" + export AWS_DEFAULT_REGION="$XPLAN_S3_REGION" + XPLAN_S3_REPORT_ID="${XPLAN_S3_REPORT_ID:-`date +%y-%m-%dT%H:%m:%S`}" + XPLAN_S3_REPORT_PATH="${XPLAN_S3_REPORT_PATH:-test-reports}" + + S3_PATH_REPORT_PATH_TAR="s3://$XPLAN_S3_BUCKET_NAME/$XPLAN_S3_REPORT_PATH/report_selenium-$XPLAN_S3_REPORT_ID.tar.gz" + S3_PATH_PDF="s3://$XPLAN_S3_BUCKET_NAME/$XPLAN_S3_REPORT_PATH/report_selenium-$XPLAN_S3_REPORT_ID.pdf" + echo "Uploading report to $S3_PATH..." + aws --endpoint-url $XPLAN_S3_ENDPOINT s3 cp $REPORT_PATH_TAR $S3_PATH_REPORT_PATH_TAR + aws --endpoint-url $XPLAN_S3_ENDPOINT s3 cp $REPORT_PATH_PDF $S3_PATH_PDF +else + echo "No upload to S3 configured" +fi + + +if [ -n "$XPLAN_NOTIFY_SLACK_CHANNEL" ] && [ -n "$XPLAN_NOTIFY_SLACK_TOKEN" ]; then + echo "Sending slack notification to $XPLAN_NOTIFY_SLACK_CHANNEL" + message="Finished Selenium tests for $XPLAN_WEB_VALIDATOR_BASE_URL and Co." + if [ -n "$S3_PATH" ]; then + echo "s3" + message="$message%0A%0ATest Report available at $S3_PATH" + fi + curl -d "text=$message" -d "channel=$XPLAN_NOTIFY_SLACK_CHANNEL" -H "Authorization: Bearer $XPLAN_NOTIFY_SLACK_TOKEN" -X POST https://slack.com/api/chat.postMessage +fi + +echo "Ready" diff --git a/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/selenium/validatorweb/XPlanValidatorWebIT.java b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/selenium/validatorweb/XPlanValidatorWebIT.java new file mode 100644 index 0000000000..26fe9f80d7 --- /dev/null +++ b/xplan-tests/xplan-tests-selenium/src/test/java/de/latlon/xplanbox/tests/selenium/validatorweb/XPlanValidatorWebIT.java @@ -0,0 +1,189 @@ +package de.latlon.xplanbox.tests.selenium.validatorweb; + +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.CleanupMode; +import org.junit.jupiter.api.io.TempDir; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class XPlanValidatorWebIT { + + private static final String NAMEBPLAN_TEST = "Selenium_Test"; + + private static final String NAMEBPLAN_ORIGINAL = "BPlan001_5-4"; + + private static String connectUrl; + + @BeforeAll + static void readSystemProperties() { + String url = System.getProperty("baseUrlValidatorWeb", "https://xplanbox.lat-lon.de/xplan-validator-web"); + String username = System.getProperty("username", null); + String password = System.getProperty("password", null); + connectUrl = createConnectUrl(url, username, password); + } + + @Test + void test_XPlanValidatorWeb_withValidPlan(@TempDir(cleanup = CleanupMode.ON_SUCCESS) final Path tmpDir) + throws Exception { + + Map<String, Object> chromePrefs = new HashMap<String, Object>(); + // chromePrefs.put("profile.default_content_settings.popups", 0); + chromePrefs.put("download.default_directory", tmpDir.toString()); + ChromeOptions options = new ChromeOptions(); + options.setExperimentalOption("prefs", chromePrefs); + + options.addArguments("--no-sandbox", "--ignore-certificate-errors", "--headless", "--disable-dev-shm-usage", + "--disable-gpu", "--disable-software-rasterizer"); + + // options.addArguments("--headless"); + WebDriver driver = new ChromeDriver(options); + String myZIPFile = getClass().getResource("/" + NAMEBPLAN_ORIGINAL + ".zip").getFile().toString(); + + try { + driver.get(connectUrl); + assertEquals("XPlanValidatorWeb", driver.getTitle()); + + WebElement elemAdd = driver.findElement(By.name("uploadPlanItem")); + elemAdd.sendKeys(myZIPFile); + + driver.findElement(By.xpath("//button[text()='Hochladen und Validierungsoptionen einstellen']")).click(); + verifyByXPath(driver, "//*[@class='gwt-DialogBox']//*[@class='Caption']", "Plan hochgeladen"); + + // einmal abbrechen und neu validieren + driver.findElement(By.xpath("//button[text()='abbrechen']")).click(); + + driver.findElement(By.xpath("//button[text()='Hochladen und Validierungsoptionen einstellen']")).click(); + verifyByXPath(driver, "//*[@class='gwt-DialogBox']//*[@class='Caption']", "Plan hochgeladen"); + + driver.findElement(By.xpath("//button[text()='zur Validierung']")).click(); + verifyByXPath(driver, "//*[@class='valOptionTitle']", "Validierungsoptionen"); + + WebElement elemName = driver.findElement(By.xpath( + "//tr[td/div[@class='valOptionLabel']/text() = 'Bezeichnung für den Report']/following-sibling::tr[1]//input")); + elemName.clear(); + elemName.sendKeys(NAMEBPLAN_TEST); + + driver.findElement(By.xpath("//label[text() = 'semantisch']")).click(); + + // Hier kann theoretisch noch ein Schema ausgewählt werden + // try { + // driver.findElement(By.xpath("//tr[12]/td/span/input")).click(); + // sleep(); + // } + // catch (NoSuchElementException nSEE_Ex) { + // nSEE_Ex.printStackTrace(); + // } + + driver.findElement(By.xpath("//button[text()='Validierung starten']")).click(); + + verifyByXPath(driver, "//*[@class='gwt-DialogBox']//*[@class='Caption']", "Ergebnisse der Validierung", 30); + + WebElement iframe = driver.findElement( + By.xpath("//html/body/div[4]/div/table/tbody/tr[2]/td[2]/div/table/tbody/tr/td[1]/iframe")); // Hier + // iframeName + // durch + // den + // tatsächlichen + // Namen + // des + // iframes + // ersetzen + driver.switchTo().frame(iframe); + + String name = driver.findElement(By.xpath("//body/p[1]/b")).getText(); + String valide = driver.findElement(By.xpath("//body/p[4]/b/font")).getText(); + String planname = driver.findElement(By.xpath("//body/ul[1]/b/li[1]")).getText(); + + SoftAssertions softly = new SoftAssertions(); + softly.assertThat(name).isEqualTo(NAMEBPLAN_TEST); + softly.assertThat(valide).isEqualTo("valide"); + softly.assertThat(planname).isEqualTo(NAMEBPLAN_ORIGINAL); + softly.assertAll(); + + driver.switchTo().defaultContent(); + + driver.findElement(By.xpath("//label[text() = 'HTML Report']")).click(); + driver.findElement(By.xpath("//label[text() = 'PDF Report']")).click(); + driver.findElement(By.xpath("//label[text() = 'XML Report']")).click(); + driver.findElement(By.xpath("//button[text() = 'Download']")).click(); + + String zipFileName = NAMEBPLAN_TEST + "-Report.zip"; + withinSeconds(10, () -> assertThat(listFiles(tmpDir)).containsExactly(zipFileName)); + + Path zipFile = tmpDir.resolve(zipFileName); + try (FileSystem zipfs = FileSystems.newFileSystem(zipFile, null)) { + Path rootInZip = zipfs.getRootDirectories().iterator().next(); + + assertThat(listFiles(rootInZip)).describedAs("Content of " + zipFile) + .containsExactlyInAnyOrder(NAMEBPLAN_TEST + ".html", NAMEBPLAN_TEST + ".pdf", + NAMEBPLAN_TEST + ".xml"); + } + } + finally { + // System.out.println("url: " + driver.getCurrentUrl()); + driver.close(); + } + } + + private void withinSeconds(int nbSeconds, Callable<?> callable) throws Exception { + Instant timeout = Instant.now().plusSeconds(nbSeconds); + + while (Instant.now().isBefore(timeout)) { + try { + callable.call(); + return; + } + catch (Exception | org.opentest4j.AssertionFailedError e) { + Thread.sleep(1000); + } + } + callable.call(); + } + + private List<String> listFiles(Path tmpDir) throws IOException { + return Files.list(tmpDir).map((it) -> it.getFileName().toString()).collect(Collectors.toList()); + } + + private void verifyByXPath(WebDriver driver, String xpath, String expectedText) throws Exception { + verifyByXPath(driver, xpath, expectedText, 5); + } + + private void verifyByXPath(WebDriver driver, String xpath, String expectedText, int maxWaitInSeconds) + throws Exception { + Callable<?> c = () -> { + WebElement elt = driver.findElement(By.xpath(xpath)); + assertEquals(expectedText, elt.getText()); + return null; + }; + withinSeconds(maxWaitInSeconds, c); + } + + private static String createConnectUrl(String url, String username, String password) { + if (username != null && !username.isEmpty()) { + String authentication = username + ":" + password + "@"; + return url.replace("://", "://" + authentication); + } + return url; + } + +} diff --git a/xplan-tests/xplan-tests-selenium/src/test/resources/BPlan001_5-4.zip b/xplan-tests/xplan-tests-selenium/src/test/resources/BPlan001_5-4.zip new file mode 100644 index 0000000000000000000000000000000000000000..db9c96803f87ae159467ec89fbd9db8b548d46f7 GIT binary patch literal 2935 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 literal 0 HcmV?d00001 -- GitLab