All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.primefaces.selenium.AbstractPrimePageTest Maven / Gradle / Ivy

The newest version!
/*
 * The MIT License
 *
 * Copyright (c) 2009-2024 PrimeTek Informatics
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.primefaces.selenium;

import org.primefaces.selenium.internal.junit.BootstrapExtension;
import org.primefaces.selenium.internal.junit.PageInjectionExtension;
import org.primefaces.selenium.internal.junit.ScreenshotOnFailureExtension;
import org.primefaces.selenium.internal.junit.WebDriverExtension;
import org.primefaces.selenium.spi.WebDriverProvider;

import java.lang.reflect.InvocationTargetException;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.logging.Logs;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@ExtendWith(BootstrapExtension.class)
@ExtendWith(WebDriverExtension.class)
@ExtendWith(PageInjectionExtension.class)
@ExtendWith(ScreenshotOnFailureExtension.class)
public abstract class AbstractPrimePageTest {

    @BeforeEach
    public void beforeEach() {
        clearConsole();
    }

    protected void assertPresent(WebElement element) {
        if (!PrimeSelenium.isElementPresent(element)) {
            Assertions.fail("Element should be present!");
        }
    }

    protected void assertPresent(By by) {
        if (!PrimeSelenium.isElementPresent(by)) {
            Assertions.fail("Element should be present!");
        }
    }

    protected void assertNotPresent(WebElement element) {
        if (PrimeSelenium.isElementPresent(element)) {
            Assertions.fail("Element should not be present!");
        }
    }

    protected void assertNotPresent(By by) {
        if (PrimeSelenium.isElementPresent(by)) {
            Assertions.fail("Element should not be present!");
        }
    }

    protected void assertDisplayed(WebElement element) {
        if (!PrimeSelenium.isElementDisplayed(element)) {
            Assertions.fail("Element should be displayed!");
        }
    }

    protected void assertDisplayed(By by) {
        if (!PrimeSelenium.isElementDisplayed(by)) {
            Assertions.fail("Element should be displayed!");
        }
    }

    protected void assertNotDisplayed(WebElement element) {
        if (PrimeSelenium.isElementDisplayed(element)) {
            Assertions.fail("Element should not be displayed!");
        }
    }

    protected void assertNotDisplayed(By by) {
        if (PrimeSelenium.isElementDisplayed(by)) {
            Assertions.fail("Element should not be displayed!");
        }
    }

    protected void assertEnabled(WebElement element) {
        if (!PrimeSelenium.isElementEnabled(element)) {
            Assertions.fail("Element should be enabled!");
        }
    }

    protected void assertEnabled(By by) {
        if (!PrimeSelenium.isElementEnabled(by)) {
            Assertions.fail("Element should be enabled!");
        }
    }

    protected void assertNotEnabled(WebElement element) {
        if (PrimeSelenium.isElementEnabled(element)) {
            Assertions.fail("Element should not be enabled!");
        }
    }

    protected void assertNotEnabled(By by) {
        if (PrimeSelenium.isElementEnabled(by)) {
            Assertions.fail("Element should not be enabled!");
        }
    }

    protected void assertDisabled(WebElement element) {
        if (PrimeSelenium.isElementEnabled(element)) {
            Assertions.fail("Element should be disabled!");
        }
    }

    protected void assertDisabled(By by) {
        if (PrimeSelenium.isElementEnabled(by)) {
            Assertions.fail("Element should be disabled!");
        }
    }

    protected void assertNotDisabled(WebElement element) {
        if (!PrimeSelenium.isElementEnabled(element)) {
            Assertions.fail("Element should not be disabled!");
        }
    }

    protected void assertNotDisabled(By by) {
        if (!PrimeSelenium.isElementEnabled(by)) {
            Assertions.fail("Element should not be disabled!");
        }
    }

    protected void assertIsAt(AbstractPrimePage page) {
        assertIsAt(page.getLocation());
    }

    protected void assertClickable(WebElement element) {
        if (!PrimeSelenium.isElementClickable(element)) {
            Assertions.fail("Element should be clickable!");
        }
    }

    protected void assertClickableOrLoading(WebElement element) {
        if (!PrimeSelenium.hasCssClass(element, "ui-state-loading") && !PrimeSelenium.isElementClickable(element)) {
            Assertions.fail("Element should be clickable or loading!");
        }
    }

    protected void assertNotClickable(WebElement element) {
        if (PrimeSelenium.isElementClickable(element)) {
            Assertions.fail("Element should not be clickable!");
        }
    }

    protected void assertIsAt(Class pageClass) {
        String location;
        try {
            location = PrimeSelenium.getUrl(pageClass.getDeclaredConstructor().newInstance());
        }
        catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }

        assertIsAt(location);
    }

    /**
     * Checks the browse console and asserts there are no SEVERE level messages.
     */
    protected void assertNoJavascriptErrors() {
        LogEntries logEntries = getLogsForType(LogType.BROWSER);
        if (logEntries == null) {
            return;
        }
        List severe = logEntries.getAll().stream()
                    .filter(l -> l.getLevel() == Level.SEVERE)
                    .collect(Collectors.toList());
        Assertions.assertTrue(severe.isEmpty(), "Javascript errors were detected in the browser console.\r\n" + severe.toString());
    }

    /**
     * Clears the browser console.
     */
    protected void clearConsole() {
        // https://stackoverflow.com/questions/51404360/how-to-clear-console-errors-using-selenium
        PrimeSelenium.executeScript("console.clear();");
        getLogsForType(LogType.BROWSER);
    }

    /**
     * Dumps to System.out or System.err any messages found in the browser console.
     */
    protected void printConsole() {
        LogEntries logEntries = getLogsForType(LogType.BROWSER);
        if (logEntries == null) {
            return;
        }
        for (LogEntry log : logEntries) {
            if (log.getLevel() == Level.SEVERE) {
                System.err.println(log.getMessage());
            }
            else {
                System.out.println(log.getMessage());
            }
        }
    }

    /**
     * Utility method for checking the browser console for a specific type of message.
     *
     * @param type the {@link LogType} you are searching for
     * @return either NULL if not available or the {@link LogEntries}
     */
    protected LogEntries getLogsForType(String type) {
        if (!isConsoleSupported()) {
            return null;
        }

        Logs logs = getWebDriver().manage().logs();
        if (logs == null) {
            return null;
        }
        Set types = logs.getAvailableLogTypes();
        if (!types.contains(LogType.BROWSER)) {
            return null;
        }
        return logs.get(type);
    }

    private boolean isConsoleSupported() {
        // Firefox does not yet support https://github.com/mozilla/geckodriver/issues/284 - may change in 2022
        // Safari does not support https://github.com/SeleniumHQ/selenium/issues/7580
        return !PrimeSelenium.isFirefox() && !PrimeSelenium.isSafari();
    }

    protected void assertIsAt(String relativePath) {
        Assertions.assertTrue(getWebDriver().getCurrentUrl().contains(relativePath));
    }

    protected  T goTo(Class pageClass) {
        return PrimeSelenium.goTo(pageClass);
    }

    protected void goTo(String partialUrl) {
        PrimeSelenium.goTo(partialUrl);
    }

    protected WebDriver getWebDriver() {
        return WebDriverProvider.get();
    }

    /**
     * Asserts text of a web element and cleanses it of whitespace issues due to different WebDriver results.
     *
     * @param element the element to check its text
     * @param text the text expected in the element
     */
    protected void assertText(WebElement element, String text) {
        String actual = normalizeSpace(element.getText()).trim();
        String expected = normalizeSpace(text).trim();
        Assertions.assertEquals(expected, actual);
    }

    /**
     * Checks a WebElement if it has a CSS class or classes. If more than one is listed then ALL must be found on the element.
     *
     * @param element the element to check
     * @param cssClasses the CSS class or classes to look for
     */
    protected void assertCss(WebElement element, String... cssClasses) {
        String elementClass = element.getAttribute("class");
        if (elementClass == null) {
            Assertions.fail("Element did not have CSS 'class' attribute.");
            return;
        }

        String[] elementClasses = elementClass.split(" ");

        for (String expectedClass : cssClasses) {
            for (String expected : expectedClass.split(" ")) {
                boolean found = false;
                for (String actual : elementClasses) {
                    if (actual.equalsIgnoreCase(expected)) {
                        found = true;
                        break;
                    }
                }

                if (!found) {
                    Assertions.fail("Element expected CSS class '" + expected + "' but was not found in '" + elementClass + "'.");
                    break;
                }
            }
        }

        // success
    }

    protected void noAjaxMinLoadAnimation() {
        setAjaxMinLoadAnimation(0);
    }

    protected void setAjaxMinLoadAnimation(int milliseconds) {
        if (milliseconds < 0) {
            throw new IllegalArgumentException("milliseconds cannot be negative");
        }
        PrimeSelenium.executeScript("PrimeFaces.ajax.minLoadAnimation = " + milliseconds + ";");
    }

    /**
     * Waits for the default minimal Ajax load animation duration.
     */
    protected void waitAjaxMinLoadAnimation() {
        getWebDriver().manage().timeouts().implicitlyWait(Duration.of(500, ChronoUnit.MILLIS));
    }

    /**
     * 

* Similar to http://www.w3.org/TR/xpath/#function-normalize -space *

*

* The function returns the argument string with whitespace normalized by using to remove leading and trailing whitespace and then replacing sequences of * whitespace characters by a single space. *

* In XML Whitespace characters are the same as those allowed by the S production, which is S ::= (#x20 | * #x9 | #xD | #xA)+ *

* Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r] *

* For reference: *

*
    *
  • \x0B = vertical tab
  • *
  • \f = #xC = form feed
  • *
  • #x20 = space
  • *
  • #x9 = \t
  • *
  • #xA = \n
  • *
  • #xD = \r
  • *
*

* The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also normalize. Additionally removes control * characters (char <= 32) from both ends of this String. *

* * @param str the source String to normalize whitespaces from, may be null * @return the modified string with whitespace normalized, {@code null} if null String input * @see Pattern * @see http://www.w3.org/TR/xpath/#function-normalize-space * @since 3.0 */ public static String normalizeSpace(final String str) { // LANG-1020: Improved performance significantly by normalizing manually instead of using regex // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test if (str == null || str.length() == 0) { return str; } final int size = str.length(); final char[] newChars = new char[size]; int count = 0; int whitespacesCount = 0; boolean startWhitespaces = true; for (int i = 0; i < size; i++) { final char actualChar = str.charAt(i); final boolean isWhitespace = Character.isWhitespace(actualChar); if (isWhitespace) { if (whitespacesCount == 0 && !startWhitespaces) { newChars[count++] = " ".charAt(0); } whitespacesCount++; } else { startWhitespaces = false; newChars[count++] = (actualChar == 160 ? 32 : actualChar); whitespacesCount = 0; } } if (startWhitespaces) { return ""; } return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy