diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4f5da55..d0b4fdb 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,12 +3,12 @@ updates: - package-ecosystem: maven directories: - "/appium-maven" - - "/jdi-light-testng" - "/playwright" - "/selenium-maven" - "/standalone-from-folder-maven" schedule: interval: weekly + open-pull-requests-limit: 5 groups: maven-minor-patch: patterns: @@ -28,10 +28,10 @@ updates: - package-ecosystem: gradle directories: - - "/allure-junit5-gradle-kts" - "/selenide-gradle" schedule: interval: weekly + open-pull-requests-limit: 5 groups: gradle-minor-patch: patterns: @@ -53,6 +53,7 @@ updates: directory: "/.github/vrt" schedule: interval: weekly + open-pull-requests-limit: 5 groups: docker: patterns: @@ -62,6 +63,7 @@ updates: directory: "/" schedule: interval: weekly + open-pull-requests-limit: 5 groups: github-actions: patterns: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f1f31f..ffc6897 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,13 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +env: + VRT_APIURL: http://localhost:4200 + VRT_APIKEY: DEFAULTUSERAPIKEYTOBECHANGED + VRT_PROJECT: Default project + VRT_BRANCHNAME: master + VRT_ENABLESOFTASSERT: "true" + jobs: maven: name: ${{ matrix.example }} @@ -19,7 +26,7 @@ jobs: strategy: fail-fast: false matrix: - example: [jdi-light-testng, playwright, selenium-maven] + example: [playwright, selenium-maven] defaults: run: working-directory: ${{ matrix.example }} @@ -31,7 +38,7 @@ jobs: - uses: actions/setup-java@v6 with: distribution: temurin - java-version: ${{ matrix.example == 'jdi-light-testng' && 21 || 17 }} + java-version: 17 cache: maven cache-dependency-path: ${{ matrix.example }}/pom.xml - run: mvn -B test-compile @@ -45,7 +52,7 @@ jobs: strategy: fail-fast: false matrix: - example: [allure-junit5-gradle-kts, selenide-gradle] + example: [selenide-gradle] defaults: run: working-directory: ${{ matrix.example }} diff --git a/.gitignore b/.gitignore index 62c8935..36649a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.idea/ \ No newline at end of file +.idea/ +vrt.json diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 16a08cc..b3f338a 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,15 @@ # Visual Regression Tracker examples for Java -Each folder is a separate project on [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java) 5.5.0 from JitPack (Java 17; JDI Light needs Java 21): +Each folder is a separate project with its own build, `vrt.json.example` and README, on [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java) 5.5.0 from JitPack and Java 17 or later. The browser examples open https://the-internet.herokuapp.com headless and track screenshots in a [Visual Regression Tracker](https://github.com/Visual-Regression-Tracker/Visual-Regression-Tracker) 6.0 server. -- [Playwright + Maven + JUnit 4](playwright) -- [Selenium 4 + Maven + JUnit 4](selenium-maven) -- [Selenide + Gradle + TestNG](selenide-gradle) -- [Allure + Selenide + Gradle (Kotlin DSL) + JUnit 5](allure-junit5-gradle-kts) -- [Standalone Java: compare PNG and PDF files from a folder + Maven](standalone-from-folder-maven) -- [JDI Light + TestNG + Maven](jdi-light-testng) -- [Appium (iOS) + TestNG + Maven](appium-maven) +| Example | Stack | Client | +| ------------------------------------------------------------ | ---------------------------------------------------- | ----------------------------------------------------------------- | +| [playwright](playwright) | Playwright, Maven, JUnit 4 | [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java) | +| [selenium-maven](selenium-maven) | Selenium 4, Maven, JUnit 4 | [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java) | +| [selenide-gradle](selenide-gradle) | Selenide, Gradle, TestNG | [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java) | +| [appium-maven](appium-maven) | Appium on an iOS simulator, Maven, TestNG | [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java) | +| [standalone-from-folder-maven](standalone-from-folder-maven) | Command line: PNG and PDF files from a folder, Maven | [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java) | -The browser examples open https://the-internet.herokuapp.com headless. They connect to -`http://localhost:4200` with the default API key and project of a fresh -[Visual Regression Tracker](https://github.com/Visual-Regression-Tracker/Visual-Regression-Tracker) -install; change that in each example's `VisualRegressionTrackerConfig`. +The examples connect with `vrt.json` or `VRT_*` environment variables, the way [sdk-java reads its configuration](https://github.com/Visual-Regression-Tracker/sdk-java#configuration). `vrt.json.example` holds the URL, API key and project of a fresh local install; copy it to `vrt.json` and change what differs. -Run a Maven example with `mvn test`, a Gradle one with `./gradlew test`. +CI runs the browser examples against a VRT server started from [.github/vrt/docker-compose.yml](.github/vrt/docker-compose.yml) and compiles the other two. diff --git a/allure-junit5-gradle-kts/.gitignore b/allure-junit5-gradle-kts/.gitignore deleted file mode 100644 index be9f372..0000000 --- a/allure-junit5-gradle-kts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.gradle/ -build/ -.allure/ diff --git a/allure-junit5-gradle-kts/build.gradle.kts b/allure-junit5-gradle-kts/build.gradle.kts deleted file mode 100644 index bb27893..0000000 --- a/allure-junit5-gradle-kts/build.gradle.kts +++ /dev/null @@ -1,25 +0,0 @@ -plugins { - java - id("io.qameta.allure") version "4.3.0" -} - -repositories { - mavenCentral() - maven(url = "https://jitpack.io") -} - -tasks.withType().configureEach { - options.release = 17 -} - -dependencies { - testImplementation("com.github.Visual-Regression-Tracker:sdk-java:5.5.0") - testImplementation("com.codeborne:selenide:7.19.1") - testImplementation(platform("org.junit:junit-bom:6.1.3")) - testImplementation("org.junit.jupiter:junit-jupiter") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") -} - -tasks.test { - useJUnitPlatform() -} diff --git a/allure-junit5-gradle-kts/gradle/wrapper/gradle-wrapper.jar b/allure-junit5-gradle-kts/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 9fa7f28..0000000 Binary files a/allure-junit5-gradle-kts/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/allure-junit5-gradle-kts/gradle/wrapper/gradle-wrapper.properties b/allure-junit5-gradle-kts/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 91c4fc6..0000000 --- a/allure-junit5-gradle-kts/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,9 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip -networkTimeout=10000 -retries=0 -retryBackOffMs=500 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/allure-junit5-gradle-kts/gradlew b/allure-junit5-gradle-kts/gradlew deleted file mode 100755 index 249efbb..0000000 --- a/allure-junit5-gradle-kts/gradlew +++ /dev/null @@ -1,248 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# gradlew start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh gradlew -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/allure-junit5-gradle-kts/gradlew.bat b/allure-junit5-gradle-kts/gradlew.bat deleted file mode 100755 index 03754c4..0000000 --- a/allure-junit5-gradle-kts/gradlew.bat +++ /dev/null @@ -1,112 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem gradlew startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables, and ensure extensions are enabled -setlocal EnableExtensions - -@rem Catch executions from older scripts and ensure they exit cleanly. -@rem This can be removed once we can be reasonably confident that few people -@rem will be migrating directly to this new wrapper. -goto afterSafetyNet -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -goto exitWithErrorLevel -:afterSafetyNet - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -1>&2 echo. -1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -1>&2 echo. -1>&2 echo Please set the JAVA_HOME variable in your environment to match the -1>&2 echo location of your Java installation. - -"%COMSPEC%" /c exit 1 -goto exitWithErrorLevel - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -1>&2 echo. -1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -1>&2 echo. -1>&2 echo Please set the JAVA_HOME variable in your environment to match the -1>&2 echo location of your Java installation. - -"%COMSPEC%" /c exit 1 -goto exitWithErrorLevel - -:execute -@rem Setup the command line - - - -@rem Execute gradlew -@rem endlocal doesn't take effect until after the line is parsed and variables are expanded -@rem which allows us to clear the local environment before executing the java command -endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel & goto exitWithErrorLevel - -@rem This label must not be changed. We rely on old scripts being able to jump to this point. -:exitWithErrorLevel -@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts -"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/allure-junit5-gradle-kts/settings.gradle.kts b/allure-junit5-gradle-kts/settings.gradle.kts deleted file mode 100644 index e63bc8b..0000000 --- a/allure-junit5-gradle-kts/settings.gradle.kts +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "allure-junit5-gradle-kts" diff --git a/allure-junit5-gradle-kts/src/test/java/io/qameta/allure/examples/junit5/AllureImageDiffTest.java b/allure-junit5-gradle-kts/src/test/java/io/qameta/allure/examples/junit5/AllureImageDiffTest.java deleted file mode 100644 index bbee2a7..0000000 --- a/allure-junit5-gradle-kts/src/test/java/io/qameta/allure/examples/junit5/AllureImageDiffTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.qameta.allure.examples.junit5; - -import com.codeborne.selenide.Configuration; -import com.codeborne.selenide.Selenide; -import io.qameta.allure.Allure; -import io.qameta.allure.Attachment; -import io.qameta.allure.Step; -import io.visual_regression_tracker.sdk_java.TestRunResult; -import io.visual_regression_tracker.sdk_java.TestRunStatus; -import io.visual_regression_tracker.sdk_java.VisualRegressionTracker; -import io.visual_regression_tracker.sdk_java.VisualRegressionTrackerConfig; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.openqa.selenium.OutputType; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; - -import static org.junit.jupiter.api.Assertions.assertNotEquals; - -public class AllureImageDiffTest { - - static VisualRegressionTrackerConfig config = VisualRegressionTrackerConfig.builder() - .apiUrl("http://localhost:4200") - .apiKey("DEFAULTUSERAPIKEYTOBECHANGED") - .project("Default project") - .branchName("master") - .enableSoftAssert(true) - .build(); - static VisualRegressionTracker vrt = new VisualRegressionTracker(config); - - @BeforeAll - static void setUp() throws IOException, InterruptedException { - Configuration.baseUrl = "https://the-internet.herokuapp.com"; - Configuration.browser = "chrome"; - Configuration.browserSize = "1280x1024"; - Configuration.headless = true; - - vrt.start(); - } - - @AfterAll - static void tearDown() throws IOException, InterruptedException { - Selenide.closeWebDriver(); - vrt.stop(); - } - - @Step - @Attachment(value = "{filename}", type = "image/png") - public static byte[] attachScreenshotToAllureReport(String href, String filename) { - if (href == null) { - return new byte[0]; - } - try (InputStream image = URI.create(href).toURL().openStream()) { - return image.readAllBytes(); - } catch (IOException e) { - return new byte[0]; - } - } - - @Test - @DisplayName("imageDiffExample displayName") - public void imageDiffExample() throws IOException, InterruptedException { - Selenide.open("/"); - - TestRunResult result = vrt.track("Home page", Selenide.screenshot(OutputType.BASE64)); - - Allure.label("testType", "screenshotDiff"); - attachScreenshotToAllureReport(result.getImageUrl(), "actual"); - attachScreenshotToAllureReport(result.getBaselineUrl(), "expected"); - attachScreenshotToAllureReport(result.getDiffUrl(), "diff"); - assertNotEquals(TestRunStatus.UNRESOLVED, result.getTestRunResponse().getStatus()); - } -} diff --git a/appium-maven/README.md b/appium-maven/README.md new file mode 100644 index 0000000..e07c033 --- /dev/null +++ b/appium-maven/README.md @@ -0,0 +1,31 @@ +# Appium (iOS) + Maven + TestNG + +[IOSBasicInteractionsTest.java](src/test/java/IOSBasicInteractionsTest.java) opens six screens of the sample app in [App.zip](src/main/resources/App.zip) on an iOS simulator with the [Appium Java client](https://github.com/appium/java-client) and tracks each with [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java). A screenshot that comes back `Unresolved` is taken again up to two times. [BaseTest.java](src/test/java/BaseTest.java) starts a local Appium server for the suite. + +CI only compiles this example: it needs macOS with an iOS simulator. + +## Prerequisites + +- macOS with Xcode and the simulator named in the test (`iPhone 12`, iOS 14.5); change `deviceName` and `platformVersion` to one you have +- [Appium](https://appium.io/docs/en/latest/quickstart/) with the XCUITest driver: `npm install -g appium`, then `appium driver install xcuitest` +- JDK 17 or later and Maven +- A running [Visual Regression Tracker](https://github.com/Visual-Regression-Tracker/Visual-Regression-Tracker) 6.0 server and its API key + +## Setup + +- Copy `vrt.json.example` to `vrt.json` and set your connection, or use the [`VRT_*` environment variables](https://github.com/Visual-Regression-Tracker/sdk-java#configuration), which override the file + +## Run + +```sh +mvn test +``` + +## What to expect + +`enableSoftAssert` is on: the SDK logs a failed check through SLF4J instead of throwing, so the test passes. The examples have no SLF4J binding, so the log stays silent; add one, such as `slf4j-simple`, to see it. + +- First run: the VRT UI shows a build with six new test runs, one per screen, from "Home page" to "Drag page". Approve them to make them the baseline for the branch. +- Next runs: the test runs are `Ok` while the screens look the same. When one changes, it is `Unresolved`, and the build shows the diff to approve or reject. + +Set `enableSoftAssert` to `false` to make new and changed screenshots fail the test. diff --git a/appium-maven/pom.xml b/appium-maven/pom.xml index 9854cd5..157a607 100644 --- a/appium-maven/pom.xml +++ b/appium-maven/pom.xml @@ -54,7 +54,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.15.0 + 3.16.0 org.apache.maven.plugins diff --git a/appium-maven/src/test/java/IOSBasicInteractionsTest.java b/appium-maven/src/test/java/IOSBasicInteractionsTest.java index b1ee65f..e100aef 100644 --- a/appium-maven/src/test/java/IOSBasicInteractionsTest.java +++ b/appium-maven/src/test/java/IOSBasicInteractionsTest.java @@ -33,15 +33,7 @@ public void setUp() throws IOException, InterruptedException { driver = new IOSDriver(getServiceUrl(), options); - VisualRegressionTrackerConfig vrtConfig = VisualRegressionTrackerConfig.builder() - .apiUrl("http://localhost:4200") - .apiKey("DEFAULTUSERAPIKEYTOBECHANGED") - .project("Default project") - .branchName("master") - .enableSoftAssert(true) - .build(); - - vrt = new VisualRegressionTracker(vrtConfig); + vrt = new VisualRegressionTracker(); vrt.start(); } diff --git a/appium-maven/vrt.json.example b/appium-maven/vrt.json.example new file mode 100644 index 0000000..c372ab5 --- /dev/null +++ b/appium-maven/vrt.json.example @@ -0,0 +1,7 @@ +{ + "apiUrl": "http://localhost:4200", + "apiKey": "DEFAULTUSERAPIKEYTOBECHANGED", + "project": "Default project", + "branchName": "master", + "enableSoftAssert": true +} diff --git a/jdi-light-testng/.gitignore b/jdi-light-testng/.gitignore deleted file mode 100644 index ac399bb..0000000 --- a/jdi-light-testng/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -*.iml -.idea/ -target/ -*.zip -*.exe -.logs/ -*.xlsx -.allure/ -allure-results/ -.gradle/ -build diff --git a/jdi-light-testng/pom.xml b/jdi-light-testng/pom.xml deleted file mode 100644 index d1eeb1e..0000000 --- a/jdi-light-testng/pom.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - 4.0.0 - - com.epam.jdi - jdi-light-testng-template - 1.0.0 - Template: JDI Light TestNG - - - - jitpack.io - https://jitpack.io - - - - - chrome - - UTF-8 - 21 - 1.9.26 - https://jdi-testing.github.io/jdi-light/ - 2.35.5 - 2.18.0 - - - - - - com.github.Visual-Regression-Tracker - sdk-java - 5.5.0 - - - - - com.epam.jdi - jdi-light-html - 1.6.3 - - - - - io.qameta.allure - allure-testng - ${allure.testng} - - - org.testng - testng - 7.12.0 - test - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.15.0 - - - org.apache.maven.plugins - maven-surefire-plugin - 3.6.1 - - - ${project.build.directory}/allure-results - - - -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar" - - - - - org.aspectj - aspectjweaver - ${aspectj.version} - - - - - io.qameta.allure - allure-maven - ${allure.maven} - - - - - - ${project.basedir}/src/main/resources - - - src/test/resources - true - - - - - \ No newline at end of file diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/TestData.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/TestData.java deleted file mode 100644 index dc9733d..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/TestData.java +++ /dev/null @@ -1,405 +0,0 @@ -package org.mytests.uiobjects.example; - -public class TestData { - public static String TABLE_SNAPSHOOT = "Name Phone Email City" + - " Burke Tucker 076 1971 1687 et.euismod.et@ut.edu GozŽe" + - " Grady Brock (011307) 16843 cursus.et@commodo.org Alcobendas" + - " Harding Lloyd 0800 1111 neque.In.ornare@mauris.co.uk Beauvais" + - " Zachary Hendrix 07624 035724 ipsum.non.arcu@auctorullamcorper.ca Redcliffe" + - " Logan Simmons (01367) 073346 ac.mattis.velit@etmagnisdis.com Gierle" + - " Colby Young 0963 451 3377 In.scelerisque.scelerisque@elitelitfermentum.net Driffield" + - " Peter Mitchell (01256) 43239 ipsum.porta@arcu.edu Duncan" + - " Hamilton Curry (0181) 775 6791 et@dignissimmagnaa.org Chemnitz" + - " Nero Stephens 0845 46 42 pellentesque.Sed@Craseutellus.edu Sachs Harbour" + - " Tanner Bruce 0800 1111 elementum.sem@maurisIntegersem.org Kungälv" + - " Akeem Harrington (0111) 759 1390 ac.arcu.Nunc@enimnislelementum.com Gävle" + - " Benjamin Glenn (016977) 3597 est.mollis@eu.co.uk Chippenham" + - " Zachary Sampson 0800 1111 tempor.erat.neque@consectetueradipiscing.org Kota" + - " Sean Brown 0317 398 0597 nibh.Donec.est@nonquamPellentesque.co.uk Castel San Niccolò" + - " Ferris Mckinney 0800 1111 leo.elementum@sedconsequat.net Langford" + - " Chancellor Cabrera 0383 300 9486 Etiam.vestibulum@Nam.edu Bauchi" + - " Keith Long 0800 364 7432 Integer.mollis.Integer@aliquetlobortisnisi.co.uk The Hague" + - " Dalton Richardson 0395 522 3568 lacus.Quisque.purus@Integeraliquamadipiscing.com Calvera" + - " Clarke Langley 0398 596 6834 porttitor.eros@velitPellentesque.ca Fino Mornasco" + - " Eaton Dyer 055 1441 9535 egestas.lacinia.Sed@Sedeueros.ca Lac-Serent" + - " Tyrone Pena (01329) 37079 nec.ligula@lobortisClassaptent.com Tuscaloosa" + - " Curran Becker 056 1678 9780 nulla@Nunccommodo.org Bruck an der Mur" + - " Damon Bryant 0801 483 9983 est.arcu@est.ca Baton Rouge" + - " Ryan Cline 0845 46 46 euismod.est.arcu@augue.co.uk Cockburn" + - " Judah Wheeler 056 4229 0035 risus.Donec@Quisquefringilla.net Kleinmachnow" + - " Ciaran Dotson (016977) 4778 id@sitamet.edu Rotem" + - " Nash Sharp (016977) 6083 amet@fringillaDonec.org Carovilli" + - " Benedict Bryant 0873 083 9083 non.sapien.molestie@blanditNamnulla.com Gravelbourg" + - " Tarik Hansen (023) 7618 2932 dui.lectus.rutrum@Sedauctor.net Afsnee" + - " Ulric Justice (0115) 392 1246 lacus@Loremipsum.net Matagami" + - " Ray Davis 0800 848169 semper@Phasellusdapibusquam.ca Tongerlo" + - " Beck Smith 07624 185893 nascetur.ridiculus.mus@semvitaealiquam.ca Rancagua" + - " Jelani Stafford 0800 049344 faucibus@nibh.co.uk Leersum" + - " Philip Lopez 0845 46 49 ac@orciadipiscingnon.co.uk Grand Island" + - " Jameson Arnold 0988 427 2322 nisl@blanditviverra.ca Tuscaloosa" + - " Burton Bishop (01025) 570147 semper.dui.lectus@commodoat.org Los Sauces" + - " Preston Monroe 0325 630 0384 neque@sed.com Burnie" + - " Joseph Eaton 0887 569 9679 malesuada@urnaNunc.co.uk La Cruz" + - " Carl Clements 07624 940647 et@mauris.edu Avise" + - " Hoyt Terry (0111) 334 8178 lorem@Phasellusnulla.net Fort St. John" + - " Octavius Espinoza (01629) 05356 Nullam.velit.dui@cursusluctus.edu Logan City" + - " Alexander Villarreal 07624 426932 ornare@neceleifendnon.com Bhuj" + - " Hayden Holmes 0360 901 1201 accumsan.laoreet@utipsumac.ca Weißenfels" + - " Sean Mueller 07638 352622 et.ultrices.posuere@Curabitur.ca Kerkhove" + - " Malcolm Richardson 076 9535 9828 urna.Ut.tincidunt@elitfermentumrisus.co.uk Cleveland" + - " Stewart Spence (023) 6496 7274 et.ultrices.posuere@dolorelit.org Calestano" + - " Quinlan Conrad (016977) 5533 tellus.Aenean@massaIntegervitae.edu Raipur" + - " Conan Blanchard (015246) 18321 dignissim.Maecenas.ornare@tincidunttempus.org Neuruppin" + - " Tate Trujillo 0387 316 9960 mauris.erat@vitaesodales.net Wood Buffalo" + - " Chadwick Bradford (0191) 538 2293 non.quam.Pellentesque@Maurisquis.com Edmundston" + - " Neville Alvarado (010779) 48043 vel.arcu@nuncQuisqueornare.co.uk Bear" + - " Baker Maldonado 0800 380112 sit.amet.luctus@arcuVestibulum.org Pointe-au-Pic" + - " Judah Hardy (011296) 66434 ultrices.posuere.cubilia@rhoncusid.com Orsogna" + - " Keegan Henson 0309 312 4037 eget@tempus.ca Habra" + - " Simon Beard (01306) 069594 In.lorem.Donec@diam.ca Swindon" + - " Hop Santiago 0855 726 9053 tortor.nibh.sit@sodaleselit.net Saint-Mard" + - " Carson Hoover 0320 958 4039 magna.tellus.faucibus@risus.com Patarrá" + - " Jelani Jefferson 07624 127835 metus@Donecsollicitudinadipiscing.co.uk Termes" + - " Dane Clark 076 3329 9156 sit@Integeraliquamadipiscing.ca San Diego" + - " Abraham Bryan 0311 770 4531 velit.in@tellusSuspendisse.ca Chartres" + - " Otto Miller (01009) 642663 orci@ipsumPhasellusvitae.ca Turnhout" + - " Talon Davidson 070 7593 9470 odio.Aliquam@Curabiturdictum.ca Minto" + - " Reed Patel 055 3390 4318 pharetra@Aliquamfringillacursus.co.uk San Cristóbal de la Laguna" + - " Herman Yang 0996 157 4214 elit.pretium@Nulla.edu Berlin" + - " Justin Horton 0800 249 3179 sagittis@lobortisnisinibh.ca Cape Breton Island" + - " Flynn Robertson 056 9705 7346 Lorem@cursus.co.uk Moulins" + - " Baker Lane 055 0842 5343 tincidunt@mi.ca Grosseto" + - " Elliott Neal (0119) 359 1626 non.arcu.Vivamus@cursusdiamat.edu Nueva Imperial" + - " Ray Yang 07624 181309 Nullam.enim@justosit.ca Lacombe County" + - " Ethan Albert (014674) 49440 cursus.luctus.ipsum@Quisquefringillaeuismod.ca Duffel" + - " Daquan Cash 070 0820 0781 Donec@convallisdolor.net Kohima" + - " Marshall Good (0121) 467 5361 Ut.nec.urna@felisadipiscing.ca Morena" + - " Edward Dean 0817 789 5834 eu.metus@Sed.ca West Valley City" + - " Rooney Brooks (0112) 337 7340 ornare.lectus.ante@malesuadamalesuada.com Evansville" + - " Judah Becker (01256) 779536 diam@ut.net Mörfelden-Walldorf" + - " Keaton Hahn 07624 524330 sit.amet@insodaleselit.edu Bollnäs" + - " Craig Mejia 07841 125712 consequat.enim@Vestibulumante.net Paupisi" + - " Kermit Wright 0800 1111 ut.aliquam@Loremipsum.ca Fresno" + - " Vernon Erickson 056 7788 3683 vulputate@quis.edu Cuglieri" + - " Kennedy Wade 0800 1111 auctor.nunc@utdolordapibus.net Radebeul" + - " Sebastian Gibson (0161) 575 6673 odio.auctor.vitae@quis.net Nieuwkerken-Waas" + - " Brennan Klein 056 1403 9853 faucibus@maurisa.edu Exeter" + - " Ryder Morse 0500 343447 nibh@incursuset.edu New Westminster" + - " Ignatius Mullen 0845 46 44 elit.fermentum.risus@utquam.com Tavigny" + - " Malachi Stanton (016969) 67601 interdum.Nunc@Donecporttitortellus.net Koersel" + - " Tanek Sloan 07624 351205 cubilia@laoreetposuere.ca Tiverton" + - " John Meyer 07475 360711 Nunc@duiaugue.net New Westminster" + - " Tarik Hunt (01084) 044437 feugiat@pellentesque.ca Sedgewick" + - " Tate Spears 055 5012 9185 euismod@parturient.com Croydon" + - " Stuart Hopkins 056 1376 7135 pede@semperdui.org Allahabad" + - " Aidan Ray 07624 271603 sem.mollis@anequeNullam.co.uk Valleyview" + - " Griffith Nieves (0121) 592 3029 Vivamus@arcuSed.net Spiere" + - " Jared Kramer 0845 46 45 Proin@mattisvelit.net Haldia" + - " Felix Stevenson (0191) 546 2187 pellentesque.tellus@utpharetrased.co.uk Paisley" + - " Wade Cross 0800 183220 dolor.quam@vehiculaet.com Hugli-Chinsurah" + - " Lee Crane 056 6498 9876 nascetur@risusDonec.org Igboho" + - " Zahir Buchanan (0191) 909 2062 nunc.sed.pede@nec.edu Lac-Serent" + - " Brian Meyer (016977) 0358 mollis.nec@seddictumeleifend.co.uk Houston" + - " Tarik Leach 055 8679 2768 risus@Pellentesqueultricies.net Llaillay" + - " Logan Gamble 0800 1111 ac.arcu.Nunc@fermentum.edu Viggiano" + - " Isabelle Mcdowell (01304) 321760 Nam.nulla.magna@mollisDuissit.ca Kiel" + - " Leila Logan 070 1742 9174 pharetra.sed.hendrerit@lorem.net Fort Laird" + - " Cameran Robertson 0845 46 40 vulputate@estMauriseu.org Laja" + - " Ciara Mcclure 07476 375018 aliquam@eliteratvitae.edu Schagen" + - " Sydnee Williamson (015122) 34852 egestas.a@aliquet.ca Hagen" + - " Fay Cobb (0141) 701 4563 felis.eget@sollicitudincommodo.com Marcedusa" + - " Anika Graham 07624 978050 lacus@augueeutellus.edu Valley East" + - " Callie Mullen 076 6778 6017 egestas@atauctor.co.uk Gallicchio" + - " Illana Fitzgerald 0800 394996 dignissim.Maecenas.ornare@erat.ca Quillón" + - " Kathleen Hughes (0101) 491 2925 odio.Nam.interdum@etnetus.ca Matamata" + - " September Andrews 0827 620 1389 Duis.gravida@orcitinciduntadipiscing.com Sint-Pieters-Leeuw" + - " Martina Davidson (012275) 85154 Donec.vitae.erat@Inmi.co.uk Liverpool" + - " Hedy Phillips 0800 120 9706 risus@netuset.edu Wolfenbüttel" + - " Hilda Hubbard 076 5780 0993 non@lacusNulla.co.uk Henstedt-Ulzburg" + - " Beverly Cameron 07380 723139 ultrices.a.auctor@dignissim.edu Lumaco" + - " Kirsten Drake 07915 777813 tincidunt.tempus@Craspellentesque.org Freiberg" + - " Karleigh Hubbard 0800 593726 Integer.mollis.Integer@Maecenasmalesuadafringilla.net Albiano" + - " Aretha Craft (0131) 721 5375 natoque@id.net Hamme" + - " Kerry Andrews 056 4028 5526 pharetra@eleifendCrassed.net Columbia" + - " Alma Espinoza 0500 215138 montes@Aeneaneuismod.com Giugliano in Campania" + - " Yael Jimenez 070 1654 2995 faucibus@DonecfringillaDonec.com Srinagar" + - " Miriam Holland 070 7849 6859 a@enimgravida.edu Kitscoty" + - " Scarlett Whitley (016552) 76917 cursus.vestibulum@Integeraliquam.net Colombo" + - " Aretha Norris 0845 46 48 Donec@ultriciesligulaNullam.edu Bathurst" + - " Faith Reyes 0349 153 9269 aliquet@consequatauctornunc.org Cunco" + - " Hanna Espinoza (01260) 449000 non.massa.non@cursus.org Ruddervoorde" + - " Yen Gibbs 0800 869684 mattis.Integer@acfeugiat.org Colwood" + - " Regina Obrien 0800 299789 In.lorem.Donec@ligulaAenean.com Osnabrück" + - " Illana Parrish 0800 291 0292 magnis.dis.parturient@elitsedconsequat.co.uk Tumbler Ridge" + - " Sigourney Stein (017821) 17943 rhoncus@purusMaecenas.org Geer" + - " Martha Daugherty 076 4262 4528 mollis.Integer.tincidunt@aliquetdiam.com Slijpe" + - " Piper Figueroa (025) 9423 5980 dis@quispedeSuspendisse.ca Sant'Angelo Limosano" + - " Kylan Schmidt 0886 691 4919 Sed.nunc@nequeNullamnisl.ca Tropea" + - " Zephr Fox 0800 638 9987 a@auguemalesuada.ca Luttre" + - " Clementine Mathews 056 5155 6096 magna.nec.quam@Aliquam.co.uk Sale" + - " Amela Sanders 056 5209 8664 pede@pharetrafeliseget.net Rycroft" + - " Dorothy Sullivan (018212) 78744 sapien.cursus.in@Donecnon.net Kharagpur" + - " Cleo Townsend 070 1931 2864 dolor.dapibus.gravida@Duisvolutpatnunc.net Longchamps" + - " Hope Berry 055 4389 2474 ante.bibendum@Morbiquis.ca La Estrella" + - " Britanney Ferrell 0800 768856 a@dignissimpharetra.co.uk Trollhättan" + - " Kiona Barber (01814) 745705 a@vitaeposuereat.edu Herk-de-Stad" + - " TaShya Sparks 0827 428 9203 dolor.Fusce.mi@aliquetmolestie.net Pali" + - " Wanda Parsons (01931) 351968 Nullam.ut@velitin.ca Rum" + - " Hilda Levy (028) 9688 8144 odio.auctor@accumsaninterdumlibero.co.uk Shawinigan" + - " Camille Little (01934) 41188 erat.eget@magna.co.uk Pointe-du-Lac" + - " Cameran Lamb (013896) 97173 Fusce.aliquet@variusultricesmauris.co.uk Wolfville" + - " Ariana Fowler 0992 295 7191 non@dignissimMaecenas.co.uk San Rafael" + - " Germaine Meyers 055 9407 7364 torquent@ultricies.edu Ponoka" + - " Evelyn Grant (0115) 452 5289 nibh@quislectus.co.uk Hamburg" + - " Alea Shelton (01859) 10515 nulla.Integer.urna@fringillaporttitorvulputate.co.uk Morrinsville" + - " Deanna Best (01925) 749888 ullamcorper.nisl.arcu@Morbi.ca Bosa" + - " Ciara Holland 076 8184 9217 metus.In@Mauris.co.uk Vegreville" + - " Sade Graves 0981 895 3416 quis.tristique@nequeMorbi.edu Hof" + - " Dakota Slater (022) 2809 6060 vel@telluseu.net Gorbea" + - " Cally Conway 056 6442 8976 risus.Donec@massaVestibulumaccumsan.net Kingussie" + - " Ivy Bridges (01390) 362274 cursus.diam.at@Vivamus.org Vitry-sur-Seine" + - " Keiko Vasquez 0800 637578 Vivamus.sit.amet@orci.edu Mesa" + - " Eugenia Mason (01897) 29989 dis@velitAliquamnisl.com Vernon" + - " Pearl Moss (0114) 143 4726 tellus@erosProinultrices.co.uk Cambridge" + - " Xantha Mack 0800 626 7655 felis.Donec@aultriciesadipiscing.ca Edam" + - " Aimee Haley 076 2343 5896 auctor@Mauris.edu Uitkerke" + - " Lucy Stafford 055 7164 6348 et@eumetusIn.net Mayerthorpe" + - " Sierra May 07624 263652 neque.et.nunc@arcu.edu Anchorage" + - " Kalia Hancock (027) 7498 7170 dis@neceuismod.com Mjölby" + - " Cameron Stone 0800 135 8495 pellentesque.eget@dictumeu.ca Castel San Niccolò" + - " Desiree Camacho 0800 1111 In@nisiCumsociis.org Joliet" + - " Jasmine Rosales 056 1299 9850 amet.luctus.vulputate@mus.co.uk Morgex" + - " Maggie Atkinson 07085 619068 magna.nec@nislelementumpurus.ca Gondiya" + - " Sydnee Vang 0894 081 3339 nunc.risus@ultrices.ca Canterano" + - " Alika Garcia (0110) 164 3404 sollicitudin.orci.sem@tellus.edu Solingen" + - " Audrey Kaufman 0804 296 0086 Sed.eget@eros.com Miranda" + - " Riley Valenzuela 0500 723497 accumsan@augueac.org Châlons-en-Champagne" + - " Adrienne Mathews 0800 1111 magna@aliquetmetusurna.com Jumet" + - " Hadassah Lynch 055 6189 0259 neque.venenatis.lacus@gravidaPraesenteu.com Hamilton" + - " Allegra Dixon 0845 46 41 imperdiet.ornare.In@quispedePraesent.org Presles" + - " Gretchen Ball 0800 166 6580 tortor.dictum@malesuadaiderat.com Guntur" + - " Mercedes Garza 056 7478 1990 euismod.mauris@Cras.edu Francavilla Fontana" + - " Kathleen Romero 07388 486341 Cras.vulputate.velit@famesac.net Isola del Gran Sasso d'Italia" + - " Joelle Burton 0500 340113 urna.Ut@Inatpede.ca Jackson" + - " Tashya Barrera (0141) 909 6538 tristique@nuncrisus.edu Dubbo" + - " Nicole Gregory (01010) 02244 aliquet.Phasellus@ante.edu Emden" + - " Minerva Parsons 0971 347 7087 odio@etnetuset.net Rosenheim" + - " Shelley Hale 056 3940 1855 egestas.Duis.ac@magnaPraesent.co.uk Kortrijk" + - " Lael Osborn 07701 189978 non@interdumligula.org Lübeck" + - " Rinah Ross 070 3885 8017 Mauris@malesuadavel.co.uk Mühlheim am Main" + - " Isabelle Erickson 0372 669 1072 sollicitudin@Donecluctusaliquet.net Lincoln" + - " Halee Bernard (016977) 0233 nec@duiSuspendisse.org Mal" + - " Pandora Bell 07624 568917 semper.tellus@eratvitae.co.uk Kalgoorlie-Boulder" + - " Chelsea Vargas (01643) 33412 ante@VivamusnisiMauris.com Imst" + - " Shafira Nixon 07624 087175 in@euismod.ca Driekapellen" + - " Bertha Nelson 0800 415119 In@Curabitursedtortor.net Rio Verde" + - " Helen Carter 07916 049237 hendrerit.id.ante@Duisgravida.org Puerto Montt" + - " Madeline Good (017187) 85467 massa.Suspendisse.eleifend@non.co.uk Terni" + - " Sydney Hughes 076 6334 5393 nunc.ullamcorper@neque.ca Barahanagar" + - " Fiona Noel (016977) 7074 est.Mauris.eu@quamdignissim.co.uk Waiheke Island" + - " Maisie Graham 0800 139993 Sed.id@necante.co.uk Dijon" + - " Germaine Brooks 0302 964 6397 ullamcorper@temporlorem.co.uk Ranst" + - " Gwendolyn Stephenson (0121) 508 7000 libero.Proin@tristique.co.uk Lasne-Chapelle-Saint-Lambert" + - " Minerva Justice 0500 218264 risus@Suspendissenon.edu North Cowichan" + - " Joan Tyler (0191) 405 8266 elit.Curabitur@facilisismagna.ca Sittard" + - " Phyllis Mathews (01622) 238340 ac@Donecfeugiatmetus.com Castelbuono" + - " Lacey Ortega 0370 539 3423 hendrerit.neque.In@lorem.net Jolanda di Savoia" + - " Jeanette Berg 0845 46 45 enim.diam@tincidunt.ca San Martino in Pensilis" + - " Brynne Holt 07304 543587 id.enim@temporeratneque.com Philadelphia" + - " Xandra Little 055 8256 4039 Etiam@parturientmontes.org Bad Nauheim" + - " Quemby Waters 07624 552770 eu.tellus@penatibus.ca Bonnyville" + - " Jessica Richardson (016977) 1368 dictum.magna.Ut@acarcu.edu Williams Lake" + - " Athena Greene 07624 582787 adipiscing.non@etrutrum.org Calera" + - " Alika Palmer (0101) 285 8741 orci.luctus.et@morbitristiquesenectus.co.uk Curitiba" + - " Callie Wall 055 4572 5553 Morbi.metus.Vivamus@Donec.co.uk Turrialba" + - " Ocean Knapp 0800 475 1597 natoque@augueidante.ca Les Bons Villers" + - " Cailin Vance (0110) 915 5385 Lorem.ipsum.dolor@magnis.org Heist-aan-Zee" + - " Delilah Conner 070 5760 4445 Curae.Phasellus.ornare@loremfringilla.com Lossiemouth" + - " Yuri Cochran 0800 1111 sed.dolor.Fusce@vitaediam.org Rockingham" + - " Destiny Hamilton 056 4319 5840 quis@Nullatempor.co.uk Baranello" + - " Ava Nolan 0321 471 2222 quis@ridiculusmus.net Torgnon" + - " Hilary Willis 070 8125 5491 faucibus@nulla.net Sangli" + - " Jenna Owens 07917 564744 nec.tellus@Fusce.co.uk Düsseldorf" + - " Carly Marsh 07015 676248 sagittis@hendreritid.org Parndorf" + - " Quintessa Kirby 070 3296 1629 tristique@et.ca Springfield" + - " Montana Hull (016977) 3710 vel.mauris.Integer@non.org Livo" + - " Catherine Reyes (01089) 452406 molestie@etarcu.com Fontanellato" + - " Summer Rice (01187) 486652 justo@et.org Radom" + - " Christine Mccoy 0800 152 5114 vel.arcu.eu@lobortis.net Rochester" + - " Alexa May 070 1215 1314 ultricies.dignissim@dolorsitamet.edu Pointe-Claire" + - " Myra Rodgers 070 4681 9771 sit@ut.net Drayton Valley" + - " Desirae Matthews (0101) 628 7979 Nulla@egetlaoreet.ca Dieppe" + - " Francesca Knowles (01693) 853716 volutpat.Nulla@magnaetipsum.co.uk Broken Arrow" + - " Quemby Rich 0845 46 42 vestibulum.nec@eunulla.edu Red Deer" + - " Mara Harrison 056 4589 0890 ut.eros.non@maurisIntegersem.org Baton Rouge" + - " Kitra Solis (0114) 741 5753 Quisque@Quisquefringillaeuismod.co.uk Broken Arrow" + - " Sandra Larson 07098 082333 fermentum@vitaenibh.net Nîmes" + - " Iola Cash 07624 092172 tellus.lorem.eu@vehiculaPellentesque.edu Caprino Bergamasco" + - " Kitra Sanchez 0800 674733 Phasellus@ipsumCurabiturconsequat.ca Wollongong" + - " Emily Keith 055 2769 6445 arcu@consectetuerrhoncusNullam.com Kent" + - " Kessie Schroeder 0967 691 5385 auctor.Mauris.vel@acarcuNunc.org Glabais" + - " Kaitlin Fernandez (020) 6003 1394 Donec@erat.edu Parbhani" + - " Doris Vaughn (0118) 591 3483 tincidunt.vehicula.risus@Proinegetodio.ca Sotteville-lès-Rouen" + - " Glenna Witt (017562) 27891 dis@Inmipede.org Soye" + - " Emma Howe (0117) 274 2390 luctus@dictum.net Zonhoven" + - " Blair Banks 070 5106 5627 metus.Vivamus.euismod@sagittis.edu Kingston-on-Thames" + - " Jorden Durham 07624 691948 molestie.in.tempus@tristiquepharetra.com Nampa" + - " Blythe Underwood (028) 0051 0929 iaculis.aliquet@sed.edu St. Thomas" + - " Eleanor Mosley 055 9116 9366 Vivamus.non.lorem@mauris.edu Tresigallo" + - " Clementine West 076 5845 0260 ac.turpis.egestas@Nuncmauris.com Acciano" + - " Eleanor Hudson (013649) 59185 Sed.eget@blanditcongueIn.net Orsara di Puglia" + - " Indigo Shields 0800 744604 ipsum@pharetra.co.uk Dorgali" + - " Galena Hughes 070 5628 7648 ut.erat@neccursus.ca Kampenhout" + - " Cassidy Travis 0845 46 40 est.Mauris@Aliquam.net Gateshead" + - " Virginia Mason 0845 46 46 lorem@nondapibus.ca Istres" + - " Cecilia Ferguson 070 0771 0692 erat.Vivamus.nisi@natoquepenatibuset.ca Böblingen" + - " Eleanor Harris (0114) 633 1360 Proin.nisl.sem@Curabituregestasnunc.com Bazel" + - " Illana Shepherd (01385) 30910 aliquam.eros@adipiscingenim.ca Beerst" + - " Kaitlin Sharpe 0849 458 7485 non@lacinia.com Flin Flon" + - " Beatrice Day 07624 875300 netus.et@arcuvel.com Fort Worth" + - " Naomi Cunningham 055 5974 6779 Morbi.neque@Vestibulumanteipsum.edu Palermo" + - " Ruth Moses (0114) 392 6720 erat@Aliquam.edu Birmingham" + - " Jaime Hopper 07624 169480 libero.est@magnaSedeu.com Aisemont" + - " Bertha Mann 0963 581 1773 placerat@tristiquepharetraQuisque.edu Nerem" + - " Melissa Gomez 056 7293 3021 parturient.montes@In.com Soye" + - " Ainsley Parks 0866 858 0276 mi.fringilla.mi@ut.com Fratta Todina" + - " Virginia Lang 0845 46 44 est.Mauris@enimNuncut.edu Chantemelle" + - " Ila Harper 0845 46 48 molestie.dapibus@seddictum.edu Les Bons Villers" + - " Lee Wilder 07624 189677 sapien.Aenean.massa@etcommodoat.ca Lakeland County" + - " Stacy Webster 0800 1111 Fusce.dolor.quam@velconvallisin.edu Antuco" + - " Isadora Joseph (027) 3824 1305 vulputate.eu@felisNullatempor.org Dorval" + - " Alea Guzman (01571) 95927 Donec@erat.net Pickering" + - " Leandra Shepherd 07624 116495 Nam.nulla@leoin.com Reading" + - " Aiko Donaldson 0303 541 3532 ligula@Innecorci.co.uk Wick" + - " Cathleen Mcdowell (016977) 4272 In.nec.orci@molestiepharetranibh.edu Rossignol" + - " Indigo Cantrell 076 4382 9948 Maecenas.malesuada.fringilla@dolor.org Sint-Martens-Bodegem" + - " Beverly Reilly (0151) 098 3418 pede@erategettincidunt.net Fraserburgh" + - " Leandra Decker 070 3077 7528 fringilla.est.Mauris@neceleifendnon.net Bowling Green" + - " Angela Woodard 07624 305700 fermentum.arcu@nonnisi.ca Zerkegem" + - " Savannah Castro (016977) 8937 Etiam@ligula.org Carleton" + - " Hollee Stark 0800 989 0403 gravida@sociosqu.edu Porretta Terme" + - " Demetria Gonzales 0800 122836 rutrum@dictum.ca Coquitlam" + - " Ina Rivers 0826 825 8806 neque@lobortisClassaptent.com Melilla" + - " Imelda Wilkerson 0800 1111 feugiat.nec@Duisdignissim.org Ribnitz-Damgarten" + - " Mariko Watson (01820) 91473 nec.luctus@facilisisfacilisis.org Fontaine-Valmont" + - " Alfreda Fox (0161) 505 2769 quis.massa@arcuSedet.edu Tongerlo" + - " Laura Boyer 0500 886398 tellus.Nunc@Curabitur.ca Bargagli" + - " Cara Mcleod 0800 950 6544 Suspendisse.eleifend.Cras@scelerisquenequesed.ca Imst" + - " Odette Baird 0800 067654 turpis.nec@pedeNunc.com Monstreux" + - " Hilda Cummings 076 3929 0120 egestas@acnullaIn.com Galzignano Terme" + - " Nerea Wade (016977) 8450 Maecenas.libero@lobortisultrices.com Chelsea" + - " Idola Workman (0114) 121 3175 egestas.a.dui@NullafacilisisSuspendisse.ca Folx-les-Caves" + - " Sonia Hahn (01111) 317928 ut@ultrices.com Altach" + - " Moana Clements (0113) 521 1388 sed@quis.ca Portsmouth" + - " Brittany Lester 056 0424 3586 Integer.vulputate@et.ca Linton" + - " Jenna Espinoza 0500 855288 Maecenas@feugiatplaceratvelit.net Cerchio" + - " Charde Powell 0395 732 6493 Aenean@Proin.net Paradise" + - " Iona Walton (0111) 925 9148 adipiscing.elit@ametdapibus.edu San Cesario di Lecce" + - " Cameron Wilcox 07196 574529 velit.dui@elitpharetraut.net Titagarh" + - " Gwendolyn Walters 0343 081 8534 lobortis@quisdiam.edu Cape Breton Island" + - " Kameko Hewitt (015192) 50969 velit.in@ultricesposuerecubilia.com Angleur" + - " Alice Joyner 055 8960 3696 dui.nec@Uttinciduntorci.co.uk Ponte San Nicolò" + - " Imani Santana 07624 358679 Cum.sociis@velitPellentesque.edu Nelson" + - " Carol Albert (029) 0001 3450 eu.sem@atfringilla.org Opheylissem" + - " Amethyst Ellison (024) 5122 9525 dictum@nibhPhasellus.co.uk Hulste" + - " Sheila Walton 0800 456077 pellentesque@egetvarius.net Harrisburg" + - " Indira Garrison 056 4760 2993 posuere.at@perconubia.edu Cisnes" + - " Tara Bradshaw (011429) 24082 erat.in.consectetuer@Sed.co.uk Embourg" + - " Kevyn Stevenson 07624 702264 eu@lacusQuisque.edu Mainz" + - " Ariel Nielsen (020) 2609 8789 eget.mollis@ridiculusmus.com Paine" + - " Chelsea Clark 076 8209 9598 parturient.montes.nascetur@ligulaDonecluctus.org North Bay" + - " Sonia Buckley (0117) 339 8426 amet@fermentum.ca Fraser-Fort George" + - " Paula Davidson 0800 1111 fringilla.purus@Aeneanegetmetus.co.uk Petacciato" + - " Sylvia Oneil 0500 952754 Phasellus.dapibus@CrasinterdumNunc.net Chandannagar" + - " Giselle Fleming (0110) 075 9118 eu@elita.com Dietzenbach" + - " Aimee Moody (01582) 01208 at.egestas.a@tristique.net Irricana" + - " Gail Rosario (0110) 640 2306 pede.Suspendisse@volutpatNulla.com Namen" + - " Whoopi Sharpe 0863 296 7004 diam@Suspendissetristiqueneque.ca Vedrin" + - " Judith Mack 070 7687 7888 Donec.nibh@rutrumjusto.ca Ternitz" + - " Helen Mckee (023) 3562 7053 vehicula.Pellentesque.tincidunt@temporeratneque.co.uk Canmore" + - " Kirestin Ballard (01343) 604851 Donec.consectetuer@ProindolorNulla.ca Nagpur" + - " Brianna Pitts 070 8440 6981 eu@temporarcuVestibulum.net Chiniot" + - " Daryl Baker 0500 000711 Morbi.non@Quisque.com Seilles" + - " Carla Bryant 070 4282 2093 Mauris.magna@vehiculaaliquetlibero.co.uk Freital" + - " Rina Nixon 076 0303 9562 Cras.vulputate.velit@utcursus.ca Tiel" + - " Ginger Jennings 070 5712 6754 leo@ligula.co.uk Burnpur" + - " Cecilia Yates (0110) 316 7904 sollicitudin.adipiscing.ligula@aliquam.co.uk Asse" + - " Belle Meyer 0800 249 5308 Donec.egestas@blanditcongue.org İmamoğlu" + - " Rebekah Farley (01394) 289332 eget.lacus@convallisante.co.uk Morrinsville" + - " Remedios Hernandez 07624 301755 Donec.est@Fusce.edu Guadalajara" + - " Breanna Beck 076 3963 3445 nunc.sit@enim.com Saint-Prime" + - " Aurelia Miller 070 9147 4394 lorem.ac@ametorciUt.co.uk Matamata" + - " Mara Yang (0118) 405 4779 dui.nec.urna@Namnulla.org Wolfenbüttel" + - " Candace Roberson 0500 874367 non.justo@lacus.net Stony Plain" + - " Adara Le 056 2666 4455 cubilia.Curae.Phasellus@atpretium.edu Sant'Egidio alla Vibrata" + - " Aspen Lawson (021) 3113 7798 consequat.purus@ipsumdolorsit.edu Lexington" + - " Ursula Burgess 07624 179190 ac.eleifend.vitae@orciin.org Rathenow" + - " Dara Meyers (025) 0943 3346 dolor@justo.com Traralgon" + - " Galena Joyce (01080) 558650 id@nonummy.org Huntsville" + - " Jada Reese (0117) 739 3237 nec.mauris.blandit@auctorodioa.ca Conca Casale" + - " Amy Maynard 076 8426 2119 sit@Aliquam.net Geel" + - " Sydney Farmer 055 4135 3834 natoque.penatibus.et@etnetus.edu Pinneberg" + - " Dai Drake (025) 3091 8842 Cras.lorem@Maurisnondui.org Exeter" + - " Janna Sanchez 0800 087282 erat.eget.ipsum@Nullam.org Sart-Eustache" + - " Maite Schwartz 056 8184 8460 pharetra.sed.hendrerit@vitaedolor.org Longvilly" + - " Amity Coffey 0937 570 2428 laoreet.lectus@dolorsitamet.ca Llangefni" + - " Willa Snyder (020) 4175 7353 ullamcorper.eu.euismod@placerat.net Pavone del Mella" + - " Regan Patton 0800 086128 elit.Curabitur.sed@Etiamvestibulum.com Paradise" + - " Karly Keller (018284) 65790 facilisis.vitae@dictumProin.org Orp-Jauche" + - " Ivy Dudley 070 8060 2941 Donec.non@Etiamvestibulummassa.net Borås" + - " Hope Hoffman 0845 46 43 vulputate.lacus.Cras@hendreritaarcu.ca Township of Minden Hills" + - " Alma Cleveland (0112) 149 7083 ante.dictum.cursus@ad.org Warri" + - " Hillary Calhoun (0119) 984 5378 justo.sit.amet@molestiepharetranibh.co.uk Hampstead" + - " Blossom Kim (016977) 3756 pellentesque.eget@egestas.edu Belsele" + - " Judith Graves 0851 556 3717 Curabitur@dolor.ca Vanderhoof" + - " Xerxes Lyons 070 7165 5290 nunc@magnaDuis.co.uk Aurangabad" + - " Dominique Parrish 0800 535186 nonummy.Fusce@ultricesDuisvolutpat.net Scarborough" + - " Yael Weeks (01813) 26044 nulla@Crasvulputate.com Fairbanks" + - " Nicole Summers (01545) 082490 magna@ametdiameu.edu Itapipoca" + - " Jana Young 07996 242955 tristique@iaculisneceleifend.net Tiegem" + - " Hollee Pruitt 0800 313 9810 faucibus.leo@Seddictum.org Bhopal" + - " Kylie Gates 056 2716 8367 luctus.aliquet.odio@utipsum.com San Massimo" + - " Ramona Cochran 07722 213674 purus.accumsan@luctuslobortisClass.com Cerro Navia" + - " Charissa Rosario 070 4770 6703 amet.orci@nonenimcommodo.co.uk Innisfail" + - " Madaline Blanchard (027) 5118 9913 eleifend.nunc@uteros.org Lamont" + - " Jemima Ayers 076 0902 8977 urna.Ut.tincidunt@dis.com Sonnino" + - " Quinn England 0800 080 0584 et.lacinia@torquent.net Brampton" + - " Susan Simon 0800 853 9239 magnis.dis.parturient@milorem.org Marbais" + - " Veda Moreno 055 8837 4859 ligula@inhendrerit.net Madrid" + - " Brielle Buckner 0800 1111 egestas.a.dui@dictumcursus.org Fürstenwalde" + - " Dorothy Brewer (012409) 17477 consequat.purus.Maecenas@convalliserat.net Mansfield-et-Pontefract" + - " Roanna Frank 0500 534552 cursus.vestibulum@atrisusNunc.com Serramonacesca" + - " Quin Barron (01902) 16701 lacus.Nulla.tincidunt@imperdietnon.net Heusden-Zolder" + - " Geraldine Nash (016977) 5728 dui.augue.eu@aodiosemper.co.uk Pessac" + - " Hadley Lambert (0114) 565 6236 sed.facilisis.vitae@Integer.co.uk Jandrain-Jandrenouille" + - " Chelsea Hubbard 056 2585 7846 in.sodales.elit@tempuseuligula.ca Zaltbommel" + - " Yetta Clemons (016977) 1475 et.magnis.dis@quamelementumat.co.uk Knokke" + - " Jenna Humphrey 056 5627 7953 Cras.dictum@dignissimpharetra.edu Maple Creek" + - " Genevieve Rollins (0101) 162 9782 sed.hendrerit@Cumsociis.org Mazzano Romano" + - " Miranda Moon (021) 7795 7957 sagittis.semper@tristiquepellentesque.net Saint John" + - " Willow Castillo 070 7358 9294 felis.Nulla.tempor@musDonecdignissim.com Montalto Uffugo" + - " Anastasia Mueller (016977) 1314 a@lacuspedesagittis.com Morrinsville" + - " Dara Owens 076 6868 7201 tellus.Phasellus@nuncsed.co.uk Waterbury" + - " Hanae Rice 0912 095 9668 nunc@aliquetliberoInteger.co.uk Rum" + - " Rama Wooten 076 0401 2139 feugiat.tellus@estmaurisrhoncus.co.uk Baidyabati" + - " Gisela Solis 070 3439 4629 non@auctorvelit.com Chambord" + - " Jana Robinson 07013 834562 libero.Proin@tinciduntnibhPhasellus.org Roccanova" + - " Claire West 0800 1111 orci.Ut.sagittis@quamelementum.co.uk Ligosullo" + - " Leigh Baldwin 0327 753 1329 quis@euismodenimEtiam.com Teralfene" + - " Chastity Mullen (0112) 945 1682 felis.eget.varius@lacinia.ca Mariquina" + - " Cara Mooney (0113) 735 6895 felis.purus@fermentumvelmauris.com Palagano" + - " Zenia Mcmillan (015652) 02443 eu.turpis.Nulla@nascetur.ca Civitacampomarano" + - " Portia Hill (01983) 17408 a.arcu.Sed@arcuvelquam.org Colobraro" + - " Brynne Brewer 0800 832 1988 amet@vitaerisus.edu Athens" + - " Kiayada Hendricks 07779 546753 interdum@dignissimtemporarcu.co.uk Lachine" + - " Lillith Reese 07624 007787 dolor.tempus@ultriciesdignissim.com Freux" + - " Keelie Gallagher (01586) 42913 dapibus.ligula@sit.net Campbelltown" + - " Ariana Keith 0845 46 40 ipsum.dolor.sit@auctorveliteget.com Karimnagar" + - " Jessica Koch 0845 46 42 nec.ante@Praesenteunulla.ca Osgoode" + - " Aileen Rodriguez 0845 46 46 mattis.velit.justo@Maurismolestie.com Portico e San Benedetto" + - " Germane Brewer 076 5624 2680 malesuada.ut.sem@Lorem.net El Bosque" + - " Willow Park 07196 875331 Vivamus.rhoncus.Donec@ProinvelitSed.org Bever Bievene" + - " Yen Stevenson 07624 310007 in@Sedeu.edu Imphal" + - " Ivana Morse (01207) 692187 eu.metus@quis.edu Pickering" + - " Chanda Donaldson 055 5125 3654 sit.amet.luctus@vellectus.ca Vidisha"; -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/custom/Avatar.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/custom/Avatar.java deleted file mode 100644 index b7cde45..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/custom/Avatar.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.mytests.uiobjects.example.custom; - -import com.epam.jdi.light.elements.composite.Section; -import com.epam.jdi.light.elements.interfaces.base.HasValue; -import com.epam.jdi.light.elements.pageobjects.annotations.locators.UI; -import com.epam.jdi.light.ui.html.elements.common.Checkbox; -import com.epam.jdi.light.ui.html.elements.common.Image; -import com.epam.jdi.light.ui.html.elements.common.Text; - -public class Avatar extends Section implements HasValue { - @UI("img") public Image image; - @UI(".user-descr>span")public Text description; - @UI("input[type=checkbox]")public Checkbox vip; - - @Override - public String getValue() { - return description.getText() + ":" + - (vip.isSelected() ? "VIP" : "Dude"); - } -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/custom/MarvelUser.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/custom/MarvelUser.java deleted file mode 100644 index b442caa..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/custom/MarvelUser.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.mytests.uiobjects.example.custom; - -import com.epam.jdi.light.elements.complex.dropdown.Dropdown; -import com.epam.jdi.light.elements.composite.Section; -import com.epam.jdi.light.ui.html.elements.common.Link; -import com.epam.jdi.light.ui.html.elements.common.Text; - -public class MarvelUser extends Section { - public Text number; - public Dropdown type; - public Link user; - public Avatar description; -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/Contacts.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/Contacts.java deleted file mode 100644 index d5da1eb..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/Contacts.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.mytests.uiobjects.example.entities; - -import com.jdiai.tools.DataClass; - -public class Contacts extends DataClass { - public String firstName, lastName, acceptConditions, position, passportNumber, - passportSeria, description, gender, weather; - public boolean passport; -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/Defaults.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/Defaults.java deleted file mode 100644 index bba6b1a..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/Defaults.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.mytests.uiobjects.example.entities; - - -public class Defaults { - public static User DEFAULT_USER = new User(); - - public static Contacts DEFAULT_CONTACT = new Contacts().set(c-> { - c.firstName = "Roman"; c.lastName = "Iovlev"; c.position = "ChiefQA"; - c.passport = true; c.passportNumber = "4321"; c.passportSeria = "123456"; - c.description = "JDI - awesome UI automation tool"; c.acceptConditions = "true"; - c.gender = "Female"; c.weather = "Sun, Rain"; - }); -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/LeftMenuData.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/LeftMenuData.java deleted file mode 100644 index 09af714..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/LeftMenuData.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.mytests.uiobjects.example.entities; - -/** - * Created by Roman_Iovlev on 3/2/2018. - */ -public enum LeftMenuData { - Home("Home"), - ContactForm("Contact form"), - Support("Support"), - Dates("Dates"), - Service("Service"), - ComplexTable("Complex Table"), - SimpleTable("Simple Table"), - UserTable("User Table"), - TableWithPages("Table with pages"), - DifferentElements("Different elements"), - MetalsColors("Metals & Colors"), - Performance("Performance"), - ElementsPacks("Elements packs"), - HTML5("HTML 5"), - Bootstrap("Bootstrap"); - - public String value; - LeftMenuData(String value) { this.value = value; } -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/MarvelUserInfo.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/MarvelUserInfo.java deleted file mode 100644 index fa5ef43..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/MarvelUserInfo.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.mytests.uiobjects.example.entities; - -import com.jdiai.tools.DataClass; - -public class MarvelUserInfo extends DataClass { - public String number, type, user, description; -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/User.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/User.java deleted file mode 100644 index 901f991..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/entities/User.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.mytests.uiobjects.example.entities; - - -import com.jdiai.tools.DataClass; - -public class User extends DataClass { - public String name = "Roman"; - public String password = "Jdi1234"; -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/SiteJdi.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/SiteJdi.java deleted file mode 100644 index 8f84384..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/SiteJdi.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.mytests.uiobjects.example.site; - -import com.epam.jdi.light.elements.common.UIElement; -import com.epam.jdi.light.elements.complex.JList; -import com.epam.jdi.light.elements.complex.Menu; -import com.epam.jdi.light.elements.composite.Form; -import com.epam.jdi.light.elements.pageobjects.annotations.locators.Css; -import com.epam.jdi.light.elements.pageobjects.annotations.locators.UI; -import org.mytests.uiobjects.example.entities.User; -import org.mytests.uiobjects.example.site.custom.MenuItem; -import org.mytests.uiobjects.example.site.pages.*; -import org.openqa.selenium.WebElement; - -//@JSite("https://jdi-testing.github.io/jdi-light/") -public class SiteJdi { - public static HomePage homePage; - public static JDIPerformancePage performancePage; - public static ContactFormPage contactFormPage; - public static ContactsPage contactsPage; - public static DatesPage datesPage; - public static Html5Page html5Page; - public static UsersPage usersPage; - @Css("form") public static Form loginForm; - - @Css(".profile-photo [ui=label]") public static UIElement userName; - @Css(".logout") public static WebElement logout; - @Css("img#user-icon") public static UIElement userIcon; - @UI(".sidebar-menu li") public static Menu leftMenu; - @UI(".sidebar-menu li") public static JList menu; - -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/custom/MenuItem.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/custom/MenuItem.java deleted file mode 100644 index 4bbf83a..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/custom/MenuItem.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.mytests.uiobjects.example.site.custom; - - -import com.epam.jdi.light.elements.common.UIElement; - -public class MenuItem extends UIElement { - @Override - public boolean isSelected() { - return hasClass("active") && attr("ui").equals("label"); - } -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/custom/MultiDropdown.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/custom/MultiDropdown.java deleted file mode 100644 index fd61e18..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/custom/MultiDropdown.java +++ /dev/null @@ -1,252 +0,0 @@ -package org.mytests.uiobjects.example.site.custom; - -import com.epam.jdi.light.asserts.generic.UISelectAssert; -import com.epam.jdi.light.common.JDIAction; -import com.epam.jdi.light.common.TextTypes; -import com.epam.jdi.light.elements.base.JDIBase; -import com.epam.jdi.light.elements.base.UIListBase; -import com.epam.jdi.light.elements.common.UIElement; -import com.epam.jdi.light.elements.interfaces.base.HasLabel; -import com.epam.jdi.light.elements.interfaces.base.ICoreElement; -import org.openqa.selenium.By; - -import java.util.List; - -import static com.epam.jdi.light.driver.WebDriverByUtils.fillByTemplate; -import static com.epam.jdi.light.elements.init.UIFactory.$; -import static com.epam.jdi.light.elements.init.UIFactory.$$; -import static com.epam.jdi.light.logger.LogLevels.DEBUG; -import static com.jdiai.tools.EnumUtils.getEnumValues; -import static com.jdiai.tools.LinqUtils.*; -import static java.util.Arrays.asList; -import static org.apache.commons.lang3.StringUtils.isBlank; - -public class MultiDropdown extends UIListBase> - implements ICoreElement, HasLabel { - - By expandArrow = By.cssSelector(".caret"); - By values = By.tagName("li"); - By valueTemplate = By.xpath(".//a[label[text()='%s']]"); - By value = By.cssSelector("button"); - By valuesConatiner = By.tagName("ul"); - - UIElement root() { return $(By.xpath(".."),this).setName("root"); } - UIElement expander() { return root().find(expandArrow).setName("expandArrow"); } - UIElement valuesList() { return root().find(valuesConatiner).setName("valuesContainer"); } - UIElement value(String name) { - return root().find(fillByTemplate(valueTemplate, name)).setName("valueTemplate"); - } - UIElement valueText() { return root().find(value).setName("value"); } - List allValues() { - return root().finds(values).indexFromZero(); - } - - @JDIAction(level = DEBUG) - private void expand() { - if (valuesList().setup(JDIBase::noValidation).isHidden()) - expander().click(); - } - - /** - * Selects values from parameters - * @param names String var arg, elements with text to select - */ - @JDIAction("Select '{0}' for '{name}'") - public void select(String... names) { - expand(); - for (String name : names) { - UIElement value = value(name); - if (value.isEnabled()) - value.click(); - } - } - - /** - * Selects only particular elements - * @param indexes String var arg, elements with text to select - */ - @JDIAction("Select '{0}' for '{name}'") - public void select(int... indexes) { - expand(); - for (int i = 1; i <= indexes.length; i++) { - UIElement value = $$(values, this).get(indexes[i]); - if (value.isEnabled()) - value.click(); - } - } - - public void check(String names) { - if (isBlank(names)) return; - check(names.split(",")); - } - - /** - * Selects only particular elements - * @param names String var arg, elements with text to select - */ - @JDIAction("Check '{0}' for '{name}'") - public void check(String... names) { - expand(); - List listNames = map(names, String::trim); - for (String name : values()) { - UIElement value = value(name); - boolean valueSelected = value.find("input").setup(JDIBase::noValidation) - .isSelected(); - if (valueSelected && !listNames.contains(name.trim()) - || !valueSelected && listNames.contains(name.trim())) - value.click(); - } - label().click(); - } - - /** - * Unselects only particular elements - * @param names String var arg, elements with text to unselect - */ - @JDIAction("Uncheck '{0}' for '{name}'") - public void uncheck(String... names) { - expand(); - List listNames = asList(names); - for (String name : values()) { - UIElement value = value(name); - if (value.isDisabled()) continue; - if (value.isSelected() && listNames.contains(value.getText().trim()) - || !value.isSelected() && !listNames.contains(value.getText().trim())) - value.click(); - } - } - public > void check(TEnum... values) { - check(getEnumValues(values)); - } - - public > void uncheck(TEnum... values) { - uncheck(getEnumValues(values)); - } - - /** - * Checks particular elements by index - * @param indexes int var arg, ids to check - */ - @JDIAction("Check '{0}' for '{name}'") - public void check(int... indexes) { - expand(); - List listIndexes = toList(indexes); - for (int i = 1; i <= values().size(); i++) { - UIElement value = allValues().get(i-1); - if (value.isDisabled()) continue; - if (value.isSelected() && !listIndexes.contains(i) - || !value.isSelected() && listIndexes.contains(i)) - value.click(); - } - } - - /** - * Unchecks particular elements by index - * @param indexes int var arg, ids to uncheck - */ - @JDIAction("Uncheck '{0}' for '{name}'") - public void uncheck(int... indexes) { - expand(); - List listIndexes = toList(indexes); - for (int i = 1; i <= values().size(); i++) { - UIElement value = allValues().get(i-1); - if (value.isDisabled()) continue; - if (value.isSelected() && listIndexes.contains(i) - || !value.isSelected() && !listIndexes.contains(i)) - value.click(); - } - } - - /** - * Gets checked values in dropdown - * @return List - */ - @JDIAction("Get '{name}' checked values") - public List checked() { - return ifSelect(allValues(), UIElement::isSelected, UIElement::getText); - } - - /** - * Selects value in dropdown - * @param value String var arg - */ - @JDIAction("Select '{0}' for '{name}'") - public void select(String value) { - select(new String[]{value}); - } - - /** - * Selects value with index in dropdown - * @param index int var arg - */ - @JDIAction("Select '{0}' for '{name}'") - public void select(int index) { - select(new int[]{index}); - } - - /** - * Gets a list of text from each values from dropdown - * @return List - */ - @JDIAction("Get '{name}' list values") - public List values() { - return map(allValues(), UIElement::getText); - } - - /** - * Gets a list of innerText from each values from dropdown - * @return List - */ - @JDIAction("Get '{name}' values") - public List values(TextTypes type) { - return map(allValues(), o -> o.text(type)); - } - - /** - * Gets enabled values from dropdown - * @return List - */ - @JDIAction("Get '{name}' enabled values") - public List listEnabled() { - return ifSelect(allValues(), UIElement::isEnabled, UIElement::getText); - } - - /** - * Gets disabled values from dropdown - * @return List - */ - @JDIAction("Get '{name}' disabled values") - public List listDisabled() { - return ifSelect(allValues(), UIElement::isDisabled, UIElement::getText); - } - - @Override - public void setValue(String value) { - check(value); - } - - /** - * Gets selected value - * @return String - */ - @Override - @JDIAction("Get '{name}' selected value") - public String selected() { - return valueText().getText(); - } - - /** - * Checks if a value is selected in a dropdown - * @param value String to select - * @return boolean - */ - @JDIAction("Is '{0}' selected for '{name}'") - public boolean selected(String value) { - return selected().trim().equalsIgnoreCase(value.trim()); - } - - @Override - public String getValue() { - return selected(); - } -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/custom/MyCheckList.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/custom/MyCheckList.java deleted file mode 100644 index be6109d..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/custom/MyCheckList.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.mytests.uiobjects.example.site.custom; - -import com.epam.jdi.light.elements.common.UIElement; -import com.epam.jdi.light.elements.complex.Checklist; - -public class MyCheckList extends Checklist { - @Override - public boolean selected(UIElement value) { - return value.hasClass("active") - && value.attr("ui").equals("label"); - } -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/ContactFormPage.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/ContactFormPage.java deleted file mode 100644 index 71286f8..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/ContactFormPage.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.mytests.uiobjects.example.site.pages; - -import com.epam.jdi.light.elements.composite.WebPage; -import com.epam.jdi.light.elements.pageobjects.annotations.Title; -import com.epam.jdi.light.elements.pageobjects.annotations.Url; -import com.epam.jdi.light.elements.pageobjects.annotations.locators.UI; -import org.mytests.uiobjects.example.site.sections.ContactForm; - -@Url("/contacts.html") @Title("Contact Form") -public class ContactFormPage extends WebPage { - @UI("form#contact-form") public static ContactForm contactForm; -} \ No newline at end of file diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/ContactsPage.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/ContactsPage.java deleted file mode 100644 index 21bad2b..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/ContactsPage.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.mytests.uiobjects.example.site.pages; - -import com.epam.jdi.light.elements.complex.dropdown.DropdownSelect; -import com.epam.jdi.light.elements.composite.WebPage; -import com.epam.jdi.light.elements.pageobjects.annotations.Title; -import com.epam.jdi.light.elements.pageobjects.annotations.Url; -import com.epam.jdi.light.elements.pageobjects.annotations.locators.UI; -import com.epam.jdi.light.ui.html.elements.common.Button; -import com.epam.jdi.light.ui.html.elements.common.Checkbox; -import com.epam.jdi.light.ui.html.elements.common.TextArea; -import com.epam.jdi.light.ui.html.elements.common.TextField; -import org.mytests.uiobjects.example.site.custom.MultiDropdown; - -@Url("/contacts.html") @Title("Contact Form") -public class ContactsPage extends WebPage { - TextField firstName, lastName, position, passportNumber, passportSeria; - - DropdownSelect gender; - MultiDropdown weather; - - Checkbox passport, acceptConditions; - TextArea description; - - @UI("['Submit']") public Button submit; -} \ No newline at end of file diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/DatesPage.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/DatesPage.java deleted file mode 100644 index 26da321..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/DatesPage.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.mytests.uiobjects.example.site.pages; - -import com.epam.jdi.light.elements.composite.WebPage; -import com.epam.jdi.light.elements.pageobjects.annotations.Title; -import com.epam.jdi.light.elements.pageobjects.annotations.Url; - -@Url("/dates.html") @Title("Dates") -public class DatesPage extends WebPage { - -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/HomePage.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/HomePage.java deleted file mode 100644 index 7c544b6..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/HomePage.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.mytests.uiobjects.example.site.pages; - -import com.epam.jdi.light.elements.composite.WebPage; -import com.epam.jdi.light.elements.pageobjects.annotations.Title; -import com.epam.jdi.light.elements.pageobjects.annotations.Url; - -@Url("/index.html") @Title("Home Page") -public class HomePage extends WebPage { -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/Html5Page.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/Html5Page.java deleted file mode 100644 index 92d53d5..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/Html5Page.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.mytests.uiobjects.example.site.pages; - -import com.epam.jdi.light.elements.composite.WebPage; -import com.epam.jdi.light.elements.pageobjects.annotations.Title; -import com.epam.jdi.light.elements.pageobjects.annotations.Url; - -@Url("/html5.html") @Title("HTML 5") -public class Html5Page extends WebPage { - -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/JDIPerformancePage.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/JDIPerformancePage.java deleted file mode 100644 index 0c3f40d..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/JDIPerformancePage.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.mytests.uiobjects.example.site.pages; - -import com.epam.jdi.light.elements.complex.dropdown.DropdownSelect; -import com.epam.jdi.light.elements.complex.table.Table; -import com.epam.jdi.light.elements.composite.WebPage; -import com.epam.jdi.light.elements.pageobjects.annotations.Url; -import com.epam.jdi.light.ui.html.elements.common.TextArea; - -@Url("/performance.html") -public class JDIPerformancePage extends WebPage { - // @Css("#users-table") - public static Table usersTable; - - // @Css("#user-names") - public static DropdownSelect userNames; - - //@Css("#textarea-performance") - public static TextArea textareaPerformance; -} diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/UsersPage.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/UsersPage.java deleted file mode 100644 index d3a7fd1..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/pages/UsersPage.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.mytests.uiobjects.example.site.pages; - -import com.epam.jdi.light.elements.complex.table.DataTable; -import com.epam.jdi.light.elements.complex.table.Table; -import com.epam.jdi.light.elements.composite.WebPage; -import com.epam.jdi.light.elements.pageobjects.annotations.Title; -import com.epam.jdi.light.elements.pageobjects.annotations.Url; -import com.epam.jdi.light.elements.pageobjects.annotations.WaitTimeout; -import com.epam.jdi.light.elements.pageobjects.annotations.locators.JTable; -import com.epam.jdi.light.elements.pageobjects.annotations.locators.UI; -import org.mytests.uiobjects.example.custom.MarvelUser; -import org.mytests.uiobjects.example.entities.MarvelUserInfo; - -@Url("/user-table.html") @Title("User Table") -public class UsersPage extends WebPage { - @UI("#user-table") public static Table usersTable; - @UI("#user-table") @WaitTimeout(2) - public static DataTable users; - @UI("#user-table") public static DataTable usersRow; - @JTable(root = "#user-table", rowHeader = "User") - public static DataTable usersSetup; - -} \ No newline at end of file diff --git a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/sections/ContactForm.java b/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/sections/ContactForm.java deleted file mode 100644 index 0d2851a..0000000 --- a/jdi-light-testng/src/main/java/org/mytests/uiobjects/example/site/sections/ContactForm.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.mytests.uiobjects.example.site.sections; - -import com.epam.jdi.light.elements.complex.dropdown.DropdownSelect; -import com.epam.jdi.light.elements.composite.Form; -import com.epam.jdi.light.ui.html.elements.common.Checkbox; -import com.epam.jdi.light.ui.html.elements.common.TextArea; -import com.epam.jdi.light.ui.html.elements.common.TextField; -import org.mytests.uiobjects.example.entities.Contacts; -import org.mytests.uiobjects.example.site.custom.MultiDropdown; - -import java.lang.reflect.Field; - -import static com.jdiai.tools.ReflectionUtils.isInterface; - -public class ContactForm extends Form { - TextField firstName, lastName, position, passportNumber, passportSeria; - - DropdownSelect gender; - MultiDropdown weather; - - Checkbox passport, acceptConditions; - TextArea description; - - //jdi will find [type=submit] element in this context automatically - //@UI("['Submit']") public Button submit; - - @Override - public void fillAction(Field field, Object element, Object parent, String setValue) { - if (isInterface(field, TextField.class)) - ((TextField)element).highlight(); - super.fillAction(field, element, parent, setValue); - } -} \ No newline at end of file diff --git a/jdi-light-testng/src/test/java/org/mytests/tests/TestsInit.java b/jdi-light-testng/src/test/java/org/mytests/tests/TestsInit.java deleted file mode 100644 index 0631d64..0000000 --- a/jdi-light-testng/src/test/java/org/mytests/tests/TestsInit.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.mytests.tests; - -import org.mytests.tests.testng.TestNGListener; -import org.mytests.uiobjects.example.site.SiteJdi; -import org.testng.annotations.AfterSuite; -import org.testng.annotations.BeforeSuite; -import org.testng.annotations.Listeners; - -import static com.epam.jdi.light.driver.WebDriverUtils.killAllSeleniumDrivers; -import static com.epam.jdi.light.elements.composite.WebPage.openSite; -import static com.epam.jdi.light.settings.WebSettings.logger; - -@Listeners(TestNGListener.class) -public interface TestsInit { - @BeforeSuite(alwaysRun = true) - static void setUp() { - killAllSeleniumDrivers(); - openSite(SiteJdi.class); - logger.info("Run Tests"); - } - - @AfterSuite(alwaysRun = true) - static void teardown() { - killAllSeleniumDrivers(); - } -} diff --git a/jdi-light-testng/src/test/java/org/mytests/tests/example/DataTableInteractTests.java b/jdi-light-testng/src/test/java/org/mytests/tests/example/DataTableInteractTests.java deleted file mode 100644 index cd9cb4e..0000000 --- a/jdi-light-testng/src/test/java/org/mytests/tests/example/DataTableInteractTests.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.mytests.tests.example; - -import io.visual_regression_tracker.sdk_java.VisualRegressionTracker; -import io.visual_regression_tracker.sdk_java.VisualRegressionTrackerConfig; -import org.mytests.tests.TestsInit; -import org.mytests.tests.testng.TestNGListener; -import org.openqa.selenium.OutputType; -import org.openqa.selenium.TakesScreenshot; -import org.testng.annotations.*; - -import java.io.IOException; - -import static com.epam.jdi.light.driver.WebDriverFactory.getDriver; -import static org.mytests.tests.states.States.shouldBeLoggedIn; -import static org.mytests.uiobjects.example.site.SiteJdi.usersPage; - -@Listeners(TestNGListener.class) -public class DataTableInteractTests implements TestsInit { - static VisualRegressionTracker vrt; - static VisualRegressionTrackerConfig config = VisualRegressionTrackerConfig.builder() - .apiUrl("http://localhost:4200") - .apiKey("DEFAULTUSERAPIKEYTOBECHANGED") - .project("Default project") - .branchName("master") - .enableSoftAssert(true) - .build(); - - @BeforeClass - public static void setUp() throws IOException, InterruptedException { - vrt = new VisualRegressionTracker(config); - vrt.start(); - } - - @AfterClass - public static void tearDown() throws IOException, InterruptedException { - vrt.stop(); - } - - @BeforeMethod - public void before() { - shouldBeLoggedIn(); - usersPage.shouldBeOpened(); - } - - @Test - public void shouldUsersPageLookSame() throws IOException, InterruptedException { - vrt.track("Users page", - ((TakesScreenshot) getDriver()).getScreenshotAs(OutputType.BASE64)); - } -} diff --git a/jdi-light-testng/src/test/java/org/mytests/tests/states/States.java b/jdi-light-testng/src/test/java/org/mytests/tests/states/States.java deleted file mode 100644 index 1c96e1c..0000000 --- a/jdi-light-testng/src/test/java/org/mytests/tests/states/States.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.mytests.tests.states; - -import com.epam.jdi.light.elements.composite.WebPage; -import io.qameta.allure.Step; -import org.mytests.uiobjects.example.entities.User; - -import static org.mytests.uiobjects.example.site.SiteJdi.*; - -/** - * Created by Roman_Iovlev on 3/1/2018. - */ -public class States { - private static void onSite() { - if (!WebPage.getUrl().contains("https://jdi-testing.github.io/jdi-light/")) - homePage.open(); - } - @Step - public static void shouldBeLoggedIn() { - onSite(); - if (!userName.isDisplayed()) - login(); - } - @Step - public static void login() { - userIcon.click(); - loginForm.submit(new User(), "enter"); - } - @Step - public static void shouldBeLoggedOut() { - onSite(); - if (userName.isDisplayed()) - logout(); - if (loginForm.isDisplayed()) - userIcon.click(); - } - @Step - public static void logout() { - if (!logout.isDisplayed()) - userIcon.click(); - logout.click(); - } -} diff --git a/jdi-light-testng/src/test/java/org/mytests/tests/testng/RetryFailedTestCases.java b/jdi-light-testng/src/test/java/org/mytests/tests/testng/RetryFailedTestCases.java deleted file mode 100644 index b832bfc..0000000 --- a/jdi-light-testng/src/test/java/org/mytests/tests/testng/RetryFailedTestCases.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.mytests.tests.testng; - -import org.testng.IRetryAnalyzer; -import org.testng.ITestResult; - -public class RetryFailedTestCases implements IRetryAnalyzer { - private int retryCnt = 0; - - //This method will be called everytime a test fails. It will return TRUE if a test fails and need to be retried, else it returns FALSE - public boolean retry(ITestResult result) { - //You could mentioned maxRetryCnt (Maximiun Retry Count) as per your requirement. Here I took 2, If any failed testcases then it runs two times - int maxRetryCnt = 1; - if (retryCnt < maxRetryCnt) { - System.out.println("Retrying " + result.getName() + " again and the count is " + (retryCnt+1)); - retryCnt++; - return true; - } - return false; - } - -} - diff --git a/jdi-light-testng/src/test/java/org/mytests/tests/testng/RetryListenerClass.java b/jdi-light-testng/src/test/java/org/mytests/tests/testng/RetryListenerClass.java deleted file mode 100644 index f209aee..0000000 --- a/jdi-light-testng/src/test/java/org/mytests/tests/testng/RetryListenerClass.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.mytests.tests.testng; - -import org.testng.IAnnotationTransformer; -import org.testng.annotations.ITestAnnotation; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; - -public class RetryListenerClass implements IAnnotationTransformer { - - @Override - public void transform(ITestAnnotation testannotation, Class testClass, Constructor testConstructor, Method testMethod) { - testannotation.setRetryAnalyzer(RetryFailedTestCases.class); - } -} diff --git a/jdi-light-testng/src/test/java/org/mytests/tests/testng/TestNGListener.java b/jdi-light-testng/src/test/java/org/mytests/tests/testng/TestNGListener.java deleted file mode 100644 index 74e508e..0000000 --- a/jdi-light-testng/src/test/java/org/mytests/tests/testng/TestNGListener.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.mytests.tests.testng; - -/** - * Created by Roman Iovlev on 14.02.2018 - * Email: roman.iovlev.jdi@gmail.com; Skype: roman.iovlev - */ - -import com.jdiai.tools.Safe; -import org.testng.IInvokedMethod; -import org.testng.IInvokedMethodListener; -import org.testng.ITestNGMethod; -import org.testng.ITestResult; -import org.testng.annotations.Test; - -import java.text.SimpleDateFormat; -import java.util.Date; - -import static com.epam.jdi.light.driver.ScreenshotMaker.takeScreen; -import static com.epam.jdi.light.settings.WebSettings.TEST_NAME; -import static com.epam.jdi.light.settings.WebSettings.logger; -import static com.jdiai.tools.LinqUtils.last; -import static java.lang.System.currentTimeMillis; - -public class TestNGListener implements IInvokedMethodListener { private Safe start = new Safe<>(0L); - - @Override - public void beforeInvocation(IInvokedMethod m, ITestResult tr) { - if (m.isTestMethod()) { - ITestNGMethod testMethod = m.getTestMethod(); - if (testMethod.getConstructorOrMethod().getMethod().isAnnotationPresent(Test.class)) { - TEST_NAME.set( last(testMethod.getTestClass().getName().split("\\.")) + - "." + testMethod.getMethodName()); - start.set(currentTimeMillis()); - logger.step("== Test '%s' START ==", TEST_NAME.get()); - } - } - } - - @Override - public void afterInvocation(IInvokedMethod method, ITestResult tr) { - if (method.isTestMethod()) { - String result = getTestResult(tr); - logger.step("=== Test '%s' %s [%s] ===", TEST_NAME.get(), result, - new SimpleDateFormat("mm:ss.SS") - .format(new Date(currentTimeMillis() - start.get()))); - if ("FAILED".equals(result)) { - try { - takeScreen(); - } catch (RuntimeException ignored) { } - if (tr.getThrowable() != null) { - logger.step("ERROR: " + tr.getThrowable().getMessage()); - } else { - logger.step("UNKNOWN ERROR"); - } - } - } - } - - private String getTestResult(ITestResult result) { - switch (result.getStatus()) { - case ITestResult.SUCCESS: - return "PASSED"; - case ITestResult.SKIP: - return "SKIPPED"; - default: - return "FAILED"; - } - } -} \ No newline at end of file diff --git a/jdi-light-testng/src/test/resources/META-INF/services/org.testng.ITestNGListener b/jdi-light-testng/src/test/resources/META-INF/services/org.testng.ITestNGListener deleted file mode 100644 index c9e8f5a..0000000 --- a/jdi-light-testng/src/test/resources/META-INF/services/org.testng.ITestNGListener +++ /dev/null @@ -1 +0,0 @@ -org.mytests.tests.testng.RetryListenerClass diff --git a/jdi-light-testng/src/test/resources/chrome.properties b/jdi-light-testng/src/test/resources/chrome.properties deleted file mode 100644 index b4f7d89..0000000 --- a/jdi-light-testng/src/test/resources/chrome.properties +++ /dev/null @@ -1,2 +0,0 @@ -#arguments=--ignore-certificate-errors --start-maximized --incognito -#enableVNC=true \ No newline at end of file diff --git a/jdi-light-testng/src/test/resources/log4j2.xml b/jdi-light-testng/src/test/resources/log4j2.xml deleted file mode 100644 index 6b7aec5..0000000 --- a/jdi-light-testng/src/test/resources/log4j2.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - jdiEvents - ./target/.logs - - - - - - - - - ${baseDir}/${logFileName}_%d{yyyy-MM-dd__HH-mm}_%i.log - - %d{HH:mm:ss} [%t] %-5level %logger{6} - %msg%n - - - - - - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jdi-light-testng/src/test/resources/test.properties b/jdi-light-testng/src/test/resources/test.properties deleted file mode 100644 index 5fe324f..0000000 --- a/jdi-light-testng/src/test/resources/test.properties +++ /dev/null @@ -1,33 +0,0 @@ -driver=${driver} -#driver.version=2.23 -timeout.wait.element=10 -domain=https://jdi-testing.github.io/jdi-light/ -page.check.after.open=NONE -# NEW_PAGE | EVERY_PAGE -#element.search.strategy=strict | soft | visible, multiple | any, single -element.search.strategy=strict -smart.locator=#%s -#smart.locator.to.name=kebab-case | camelCase | snake_case | PascalCase | UPPER_SNAKE_CASE -log.level=INFO -log.info.details=element -#text.type=SMART_TEXT | TEXT | VALUE | INNER | LABEL -#set.text.type=SET_TEXT | SEND_KEYS | CLEAR_SEND_KEYS -#assert.type=strict | soft - -#page.load.strategy=normal -#browser.size=MAXIMIZE | 1024x762 -#browser.kill=afterAndBefore | after | before -#drivers.folder=C:\\Selenium -#log.message.format=short | full -#demo.mode=false | true -#demo.delay=2 -#remote.type=sauce | browserstack -#driver.remote.url=http://localhost:4444/wd/hub -headless=true -screenshot.strategy=on failure -#element.highlight=off | on failure | on assert | on action | flow -#screenshot.strategy=off | on failure | on assert | new page | flow -#allure.steps=true -#html.code.strategy=off | on failure | on assert | new page -#requests.strategy=off | on failure | on assert | new page -#screenshot.tool=selenium | robot \ No newline at end of file diff --git a/playwright/README.md b/playwright/README.md new file mode 100644 index 0000000..5684c96 --- /dev/null +++ b/playwright/README.md @@ -0,0 +1,29 @@ +# Playwright + Maven + JUnit 4 + +[PlaywrightExampleTest.java](src/test/java/PlaywrightExampleTest.java) opens https://the-internet.herokuapp.com headless with [Playwright for Java](https://playwright.dev/java/) and tracks two screenshots with [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java), the second with test run options and an ignore area. + +## Prerequisites + +- JDK 17 or later and Maven +- A running [Visual Regression Tracker](https://github.com/Visual-Regression-Tracker/Visual-Regression-Tracker) 6.0 server and its API key + +## Setup + +- Copy `vrt.json.example` to `vrt.json` and set your connection, or use the [`VRT_*` environment variables](https://github.com/Visual-Regression-Tracker/sdk-java#configuration), which override the file + +Playwright downloads its browsers on the first run. + +## Run + +```sh +mvn test +``` + +## What to expect + +`enableSoftAssert` is on: the SDK logs a failed check through SLF4J instead of throwing, so the test passes. The examples have no SLF4J binding, so the log stays silent; add one, such as `slf4j-simple`, to see it. + +- First run: the VRT UI shows a build with two new test runs, "Home page" and "Checkboxes page". Approve them to make them the baseline for the branch. +- Next runs: the test runs are `Ok` while the pages look the same. When one changes, it is `Unresolved`, and the build shows the diff to approve or reject. + +Set `enableSoftAssert` to `false` to make new and changed screenshots fail the test. diff --git a/playwright/pom.xml b/playwright/pom.xml index 1d1516e..bca4f75 100644 --- a/playwright/pom.xml +++ b/playwright/pom.xml @@ -44,7 +44,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.15.0 + 3.16.0 org.apache.maven.plugins diff --git a/playwright/src/test/java/PlaywrightExampleTest.java b/playwright/src/test/java/PlaywrightExampleTest.java index 4d7b789..eda6f68 100644 --- a/playwright/src/test/java/PlaywrightExampleTest.java +++ b/playwright/src/test/java/PlaywrightExampleTest.java @@ -4,7 +4,6 @@ import io.visual_regression_tracker.sdk_java.IgnoreAreas; import io.visual_regression_tracker.sdk_java.TestRunOptions; import io.visual_regression_tracker.sdk_java.VisualRegressionTracker; -import io.visual_regression_tracker.sdk_java.VisualRegressionTrackerConfig; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -14,14 +13,7 @@ import java.util.List; public class PlaywrightExampleTest { - static VisualRegressionTracker vrt = new VisualRegressionTracker( - VisualRegressionTrackerConfig.builder() - .apiUrl("http://localhost:4200") - .apiKey("DEFAULTUSERAPIKEYTOBECHANGED") - .project("Default project") - .branchName("master") - .enableSoftAssert(true) - .build()); + static VisualRegressionTracker vrt = new VisualRegressionTracker(); static Playwright playwright; static Browser browser; static Page page; diff --git a/playwright/vrt.json.example b/playwright/vrt.json.example new file mode 100644 index 0000000..c372ab5 --- /dev/null +++ b/playwright/vrt.json.example @@ -0,0 +1,7 @@ +{ + "apiUrl": "http://localhost:4200", + "apiKey": "DEFAULTUSERAPIKEYTOBECHANGED", + "project": "Default project", + "branchName": "master", + "enableSoftAssert": true +} diff --git a/selenide-gradle/README.md b/selenide-gradle/README.md new file mode 100644 index 0000000..da0a587 --- /dev/null +++ b/selenide-gradle/README.md @@ -0,0 +1,28 @@ +# Selenide + Gradle + TestNG + +[SelenideExample.java](src/test/java/SelenideExample.java) opens https://the-internet.herokuapp.com in headless Chrome with [Selenide](https://selenide.org) and tracks two screenshots with [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java), the second with test run options and an ignore area. + +## Prerequisites + +- JDK 17 or later; the Gradle wrapper downloads Gradle +- Google Chrome; Selenium Manager downloads a matching chromedriver +- A running [Visual Regression Tracker](https://github.com/Visual-Regression-Tracker/Visual-Regression-Tracker) 6.0 server and its API key + +## Setup + +- Copy `vrt.json.example` to `vrt.json` and set your connection, or use the [`VRT_*` environment variables](https://github.com/Visual-Regression-Tracker/sdk-java#configuration), which override the file + +## Run + +```sh +./gradlew test +``` + +## What to expect + +`enableSoftAssert` is on: the SDK logs a failed check through SLF4J instead of throwing, so the test passes. The examples have no SLF4J binding, so the log stays silent; add one, such as `slf4j-simple`, to see it. + +- First run: the VRT UI shows a build with two new test runs, "Home page" and "Checkboxes page". Approve them to make them the baseline for the branch. +- Next runs: the test runs are `Ok` while the pages look the same. When one changes, it is `Unresolved`, and the build shows the diff to approve or reject. + +Set `enableSoftAssert` to `false` to make new and changed screenshots fail the test. diff --git a/selenide-gradle/src/test/java/SelenideExample.java b/selenide-gradle/src/test/java/SelenideExample.java index af19f26..b5f167e 100644 --- a/selenide-gradle/src/test/java/SelenideExample.java +++ b/selenide-gradle/src/test/java/SelenideExample.java @@ -3,7 +3,6 @@ import io.visual_regression_tracker.sdk_java.IgnoreAreas; import io.visual_regression_tracker.sdk_java.TestRunOptions; import io.visual_regression_tracker.sdk_java.VisualRegressionTracker; -import io.visual_regression_tracker.sdk_java.VisualRegressionTrackerConfig; import org.openqa.selenium.OutputType; import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeSuite; @@ -15,16 +14,7 @@ import static com.codeborne.selenide.Selenide.$; public class SelenideExample { - VisualRegressionTrackerConfig config = VisualRegressionTrackerConfig.builder() - .apiUrl("http://localhost:4200") - .apiKey("DEFAULTUSERAPIKEYTOBECHANGED") - .project("Default project") - .branchName("master") - .enableSoftAssert(true) - .httpTimeoutInSeconds(15) - .build(); - - VisualRegressionTracker vrt = new VisualRegressionTracker(config); + VisualRegressionTracker vrt = new VisualRegressionTracker(); @BeforeSuite public void setUp() throws IOException, InterruptedException { diff --git a/selenide-gradle/vrt.json.example b/selenide-gradle/vrt.json.example new file mode 100644 index 0000000..c372ab5 --- /dev/null +++ b/selenide-gradle/vrt.json.example @@ -0,0 +1,7 @@ +{ + "apiUrl": "http://localhost:4200", + "apiKey": "DEFAULTUSERAPIKEYTOBECHANGED", + "project": "Default project", + "branchName": "master", + "enableSoftAssert": true +} diff --git a/selenium-maven/README.md b/selenium-maven/README.md new file mode 100644 index 0000000..34ed581 --- /dev/null +++ b/selenium-maven/README.md @@ -0,0 +1,28 @@ +# Selenium 4 + Maven + JUnit 4 + +[SeleniumExampleTest.java](src/test/java/com/example/test/SeleniumExampleTest.java) opens https://the-internet.herokuapp.com in headless Chrome with [Selenium](https://www.selenium.dev/documentation/webdriver/) and tracks two screenshots with [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java), the second with test run options and an ignore area. + +## Prerequisites + +- JDK 17 or later and Maven +- Google Chrome; Selenium Manager downloads a matching chromedriver +- A running [Visual Regression Tracker](https://github.com/Visual-Regression-Tracker/Visual-Regression-Tracker) 6.0 server and its API key + +## Setup + +- Copy `vrt.json.example` to `vrt.json` and set your connection, or use the [`VRT_*` environment variables](https://github.com/Visual-Regression-Tracker/sdk-java#configuration), which override the file + +## Run + +```sh +mvn test +``` + +## What to expect + +`enableSoftAssert` is on: the SDK logs a failed check through SLF4J instead of throwing, so the test passes. The examples have no SLF4J binding, so the log stays silent; add one, such as `slf4j-simple`, to see it. + +- First run: the VRT UI shows a build with two new test runs, "Home page" and "Checkboxes page". Approve them to make them the baseline for the branch. +- Next runs: the test runs are `Ok` while the pages look the same. When one changes, it is `Unresolved`, and the build shows the diff to approve or reject. + +Set `enableSoftAssert` to `false` to make new and changed screenshots fail the test. diff --git a/selenium-maven/pom.xml b/selenium-maven/pom.xml index 53d055a..cfea35d 100644 --- a/selenium-maven/pom.xml +++ b/selenium-maven/pom.xml @@ -44,7 +44,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.15.0 + 3.16.0 org.apache.maven.plugins diff --git a/selenium-maven/src/test/java/com/example/test/SeleniumExampleTest.java b/selenium-maven/src/test/java/com/example/test/SeleniumExampleTest.java index 72e674e..2f5192c 100644 --- a/selenium-maven/src/test/java/com/example/test/SeleniumExampleTest.java +++ b/selenium-maven/src/test/java/com/example/test/SeleniumExampleTest.java @@ -3,7 +3,6 @@ import io.visual_regression_tracker.sdk_java.IgnoreAreas; import io.visual_regression_tracker.sdk_java.TestRunOptions; import io.visual_regression_tracker.sdk_java.VisualRegressionTracker; -import io.visual_regression_tracker.sdk_java.VisualRegressionTrackerConfig; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -20,19 +19,12 @@ public class SeleniumExampleTest { static VisualRegressionTracker vrt; static ChromeDriver driver; - static VisualRegressionTrackerConfig config = VisualRegressionTrackerConfig.builder() - .apiUrl("http://localhost:4200") - .apiKey("DEFAULTUSERAPIKEYTOBECHANGED") - .project("Default project") - .branchName("master") - .enableSoftAssert(true) - .build(); @BeforeClass public static void setUp() throws IOException, InterruptedException { driver = new ChromeDriver(new ChromeOptions().addArguments("--headless=new")); driver.manage().window().setSize(new Dimension(1280, 1024)); - vrt = new VisualRegressionTracker(config); + vrt = new VisualRegressionTracker(); vrt.start(); } diff --git a/selenium-maven/vrt.json.example b/selenium-maven/vrt.json.example new file mode 100644 index 0000000..c372ab5 --- /dev/null +++ b/selenium-maven/vrt.json.example @@ -0,0 +1,7 @@ +{ + "apiUrl": "http://localhost:4200", + "apiKey": "DEFAULTUSERAPIKEYTOBECHANGED", + "project": "Default project", + "branchName": "master", + "enableSoftAssert": true +} diff --git a/standalone-from-folder-maven/.gitignore b/standalone-from-folder-maven/.gitignore index 26a9bfe..9ed3e95 100644 --- a/standalone-from-folder-maven/.gitignore +++ b/standalone-from-folder-maven/.gitignore @@ -1,2 +1,3 @@ *.iml target +vrt_result.html diff --git a/standalone-from-folder-maven/README.md b/standalone-from-folder-maven/README.md index 3b180ba..03a143e 100644 --- a/standalone-from-folder-maven/README.md +++ b/standalone-from-folder-maven/README.md @@ -1,15 +1,32 @@ -# Compare image and pdf files from a folder -This can be used to compare existing PNG and PDF files in a folder. Each page of PDF file is converted to ```BufferedImage``` and then compared in VRT. +# Compare PNG and PDF files from a folder -#### Use it as a standalone executable jar file passing parameters from command line -- Make a fat jar by giving below maven command +[CompareFromFile.java](src/main/java/CompareFromFile.java) is a command-line client: it tracks every PNG file in a folder, and every page of every PDF file as a PNG, with [sdk-java](https://github.com/Visual-Regression-Tracker/sdk-java). Use it to compare images that another tool produced. - ```mvn clean compile assembly:single``` -- Then run the jar file in command line as +CI only compiles this example: it needs a folder of images. - ```java -jar vrt-standalone-client-1.0.1.jar http://localhost:4200 CDJ3HHD5MY45G0PK5M3PBB6NBGC9 c936bfa4-50b3-40c4-b177-94efbeabfbcf null main ``` -- You can see help by running without parameters like below. +## Prerequisites - ```java -jar vrt-standalone-client-1.0.1.jar``` +- JDK 17 or later and Maven +- A running [Visual Regression Tracker](https://github.com/Visual-Regression-Tracker/Visual-Regression-Tracker) 6.0 server and its API key -#### You can also use hardcoded values for the VRT parameters in the code and run from IDE. +## Setup + +- Copy `vrt.json.example` to `vrt.json` in the folder you run the client from and set your connection, or use the [`VRT_*` environment variables](https://github.com/Visual-Regression-Tracker/sdk-java#configuration), which override the file +- Build a jar with its dependencies: `mvn compile assembly:single` + +## Run + +```sh +java -jar target/vrt-standalone-client-1.0.1.jar +``` + +Without ``, the client reads the current folder; `help` prints the usage. You can also run `CompareFromFile` from your IDE. + +## What to expect + +The client prints the build status and a summary: how many files it processed, how many runs of each status, and whether all passed. It also writes the counts as a chart to `vrt_result.html` in the current folder. + +- First run: every image is `New`. The VRT UI shows a build with one test run per PNG file and per PDF page, named after the file (`report_Page1.png` for the first page of `report.pdf`). Approve them to make them the baseline for the branch. +- Next runs: `Ok` while the images are the same. When one changes, it is `Unresolved`, and the build shows the diff to approve or reject. + +`enableSoftAssert` only decides whether the SDK logs or throws; the client handles both, and counts new and changed images as not passed. diff --git a/standalone-from-folder-maven/pom.xml b/standalone-from-folder-maven/pom.xml index 09a1820..b57f8ca 100644 --- a/standalone-from-folder-maven/pom.xml +++ b/standalone-from-folder-maven/pom.xml @@ -43,7 +43,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.15.0 + 3.16.0 org.apache.maven.plugins diff --git a/standalone-from-folder-maven/src/main/java/CompareFromFile.java b/standalone-from-folder-maven/src/main/java/CompareFromFile.java index 1b51a52..059a38e 100644 --- a/standalone-from-folder-maven/src/main/java/CompareFromFile.java +++ b/standalone-from-folder-maven/src/main/java/CompareFromFile.java @@ -18,68 +18,23 @@ public class CompareFromFile { - static final String ANSI_BLACK = "\u001B[30m"; - static final String ANSI_RED = "\u001B[31m"; static final String ANSI_GREEN = "\u001B[32m"; - static final String ANSI_YELLOW = "\u001B[33m"; static final String ANSI_RESET = "\u001B[0m"; - static final String ANSI_PURPLE = "\u001B[35m"; - static final String ANSI_CYAN = "\u001B[36m"; static final String ANSI_BLUE = "\u001B[34m"; - static final String ANSI_WHITE = "\u001B[37m"; static final String BOLD_TEXT = "\033[0;1m"; public static void main(String[] args) { - if (args.length == 0 || args[0].trim().contentEquals("help")) { - System.out.println( - BOLD_TEXT + ANSI_PURPLE + "Pass arguments in the following order" + ANSI_RESET + System.lineSeparator() + - BOLD_TEXT + ANSI_GREEN + "API URL " + ANSI_RESET + ANSI_CYAN + "(mandatory)" + ANSI_RESET + " - This is the url of VRT backend." + System.lineSeparator() + - BOLD_TEXT + ANSI_GREEN + "API Key " + ANSI_RESET + ANSI_CYAN + "(mandatory)" + ANSI_RESET + " - Get it from VRT UI." + System.lineSeparator() + - BOLD_TEXT + ANSI_GREEN + "Project " + ANSI_RESET + ANSI_CYAN + "(mandatory)" + ANSI_RESET + " - Get it from VRT UI." + System.lineSeparator() + - BOLD_TEXT + ANSI_GREEN + "CI Build Id " + ANSI_RESET + ANSI_CYAN + "(optional)" + ANSI_RESET + " - Use it to tag a VRT build with Jenkins build id. Pass null if you want to skip it and use the next parameter." + System.lineSeparator() + - BOLD_TEXT + ANSI_GREEN + "Branch " + ANSI_RESET + ANSI_CYAN + "(optional for VRT higher than 4.19.0)" + ANSI_RESET + " - Will take default branch defined in VRT for the project. Pass null if you want to skip it and use the next parameter." + System.lineSeparator() + - BOLD_TEXT + ANSI_GREEN + "File Path " + ANSI_RESET + ANSI_CYAN + "(optional)" + ANSI_RESET + " - Give full path. It will take current folder if not provided." + System.lineSeparator() + - BOLD_TEXT + ANSI_YELLOW + "Example: " + ANSI_RESET + ANSI_YELLOW + "java -jar vrt-standalone-client-1.0.0.jar http://localhost:4200 CDJ3HHD5MY45G0PK5M3PBB6NBGC9 c936bfa4-50b3-40c4-b177-94efbeabfbcf null main" + ANSI_RESET); - System.exit(0); + if (args.length > 1 || (args.length == 1 && args[0].equals("help"))) { + System.out.println("Usage: java -jar vrt-standalone-client.jar [folder]" + System.lineSeparator() + + "Tracks the PNG and PDF files in the folder (default: the current one)." + System.lineSeparator() + + "The connection comes from vrt.json in the current folder or VRT_* environment variables."); + System.exit(args.length > 1 ? 1 : 0); } - if (args.length < 2) { - System.out.println("You have to pass apiUrl, apiKey and project at a minimum." + System.lineSeparator() + - "Example: java -jar vrt-standalone-client-1.0.0.jar http://localhost:4200 CDJ3HHD5MY45G0PK5M3PBB6NBGC9 c936bfa4-50b3-40c4-b177-94efbeabfbcf null main"); - System.exit(0); - } - - String apiUrl = args[0]; - //String apiUrl = "http://localhost:4200"; - String apiKey = args[1]; - //String apiKey = "CDJ3HHD5MY45G0PK5M3PBB6NBGC9"; //Populate your key - String project = args[2]; - //String project = "c936bfa4-50b3-40c4-b177-94efbeabfbcf"; // Populate your project - String ciBuildId = args.length > 3 ? args[3] : null; - //String ciBuildId = null; - String branch = args.length > 4 ? args[4] : null; - //String branch = "main"; - String filePath = args.length > 5 ? args[5] : null; - //String filePath = ".";//Give complete path of the image files or . for current path. - - filePath = filePath == null ? "." : filePath; - runVRT(apiUrl, apiKey, project, ciBuildId, branch, filePath); + runVRT(args.length > 0 ? args[0] : "."); } - private static void runVRT(String apiUrl, String apiKey, String project, String ciBuildId, String branch, String filePath) { - VisualRegressionTrackerConfig.VisualRegressionTrackerConfigBuilder configBuilder = VisualRegressionTrackerConfig.builder() - .apiUrl(apiUrl) - .apiKey(apiKey) - .project(project); - - if (ciBuildId != null && !ciBuildId.contentEquals("null")) - configBuilder.ciBuildId(ciBuildId); - //If you use VRT version 4.19.0 or lower, then branch is mandatory - //For higher versions, branch name will default to the main branch if not provided here. - if (branch != null && !branch.contentEquals("null")) - configBuilder.branchName(branch); - VisualRegressionTrackerConfig config = configBuilder.build(); - - VisualRegressionTracker visualRegressionTracker = new VisualRegressionTracker(config); + private static void runVRT(String filePath) { + VisualRegressionTracker visualRegressionTracker = new VisualRegressionTracker(); Map results = new HashMap<>(); results.put("allImageVerified", true); results.put("allPassed", true); @@ -92,14 +47,11 @@ private static void runVRT(String apiUrl, String apiKey, String project, String System.exit(1); } visualRegressionTracker.start(); - //Use the default options builder or custom options builder. TestRunOptions.TestRunOptionsBuilder testRunOptionsBuilder = TestRunOptions.builder(); - //TestRunOptions.TestRunOptionsBuilder testRunOptionsBuilder = getTestRunOptionsBuilder(); File[] fileList = file.listFiles(); for (File eachFile : fileList) { String[] imageExtensions = {"png", "pdf"}; if (Arrays.asList(imageExtensions).contains(FilenameUtils.getExtension(eachFile.getName()))) { - //If the folder has pdf files, they will be converted to png to be able to compare. if (FilenameUtils.getExtension(eachFile.getName()).equalsIgnoreCase("pdf")) { List bufferedImageList = getPDFPagesAsImages(eachFile); for (int index = 0; index < bufferedImageList.size(); index++) { @@ -169,42 +121,11 @@ private static List getPDFPagesAsImages(File eachFile) throws Exc for (int pageNumber = 0; pageNumber < pdDocument.getNumberOfPages(); ++pageNumber) { BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(pageNumber, 300); bufferedImageList.add(bufferedImage); - //ImageIO.write(bufferedImage, "PNG", new File(eachFile.getPath().replace(".pdf", "_Page") + (pageNumber + 1) + ".png")); } } return bufferedImageList; } - private static TestRunOptions.TestRunOptionsBuilder getTestRunOptionsBuilder() { - //Use only the options you need in below line. - String maskData_x = "0"; - String maskData_y = "0"; - String maskData_width = "200"; - String maskData_height = "20"; - String browser = ""; - String device = "Sample"; - String os = ""; - String viewport = ""; - - TestRunOptions.TestRunOptionsBuilder testRunOptionsBuilder = TestRunOptions.builder() - .diffTollerancePercent(0.0f) - .os(os) - .browser(browser) - .device(device) - .viewport(viewport); - if (maskData_height != null && maskData_width != null) { - testRunOptionsBuilder.ignoreAreas(Collections.singletonList( - IgnoreAreas.builder() - .x(Long.valueOf(maskData_x)) - .y(Long.valueOf(maskData_y)) - .width(Long.valueOf(maskData_width)) - .height(Long.valueOf(maskData_height)) - .build() - )); - } - return testRunOptionsBuilder; - } - public static void writeHTMLFile(int passed, int failed, int unresolved) throws IOException { String content = "\n" + " \n" + diff --git a/standalone-from-folder-maven/vrt.json.example b/standalone-from-folder-maven/vrt.json.example new file mode 100644 index 0000000..c372ab5 --- /dev/null +++ b/standalone-from-folder-maven/vrt.json.example @@ -0,0 +1,7 @@ +{ + "apiUrl": "http://localhost:4200", + "apiKey": "DEFAULTUSERAPIKEYTOBECHANGED", + "project": "Default project", + "branchName": "master", + "enableSoftAssert": true +}