com.codacy.scoobydoo.utils.WebUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scooby-doo-fwk Show documentation
Show all versions of scooby-doo-fwk Show documentation
Automated testing framework
package com.codacy.scoobydoo.utils;
import com.codacy.scoobydoo.Constant.Key;
import com.codacy.scoobydoo.LoggingHelper;
import com.codacy.scoobydoo.configuration.Configuration;
import io.restassured.specification.RequestSpecification;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.remote.RemoteExecuteMethod;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.html5.RemoteWebStorage;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.asserts.SoftAssert;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Function;
import static io.restassured.RestAssured.given;
// Utils that are used by web and e2e tests but that don't interact with web pages directly.
//
// For methods that don't depend on neither configuration and driver, check if they could be moved to Utils instead.
// For methods that depend on locators and such, consider moving them to WebFragment or WebElementWrapper.
public class WebUtils {
protected final Configuration config;
protected final RemoteWebDriver driver;
public WebUtils(RemoteWebDriver driver, Configuration configuration) {
config = configuration;
this.driver = driver;
}
public void deleteAllCookies() {
LoggingHelper.info("Delete all cookies.");
waitForFunction(x -> {
driver.manage().deleteAllCookies();
return driver.manage().getCookies().isEmpty();
},
config.getTimeout().DEFAULT_TIMEOUT,
config.getTimeout().DEFAULT_POLLING);
}
public void deleteAllCookiesAndCache() {
deleteAllCookies();
deleteCache();
}
public void deleteCache() {
if(!driver.getCurrentUrl().equals("data:,")) {
LoggingHelper.info("Deleting cache.");
RemoteExecuteMethod remoteExecuteMethod = new RemoteExecuteMethod(driver);
RemoteWebStorage storage = new RemoteWebStorage(remoteExecuteMethod);
storage.getSessionStorage().clear();
}
}
// Use this to run test steps that can fail with an open popup.
// If one of the steps fails, this will refresh the browser, hence closing the popup and falling back to a retryable state.
public void executeCodeThatOpensPopUps(Runnable runnable) {
executeCodeThatOpensPopUps(runnable, Optional.empty());
}
// Use this to run test steps that can fail with an open popup.
// If one of the steps fails, this will run the resetBrowserInstruction, hence closing the popup and falling back to a retryable state.
public void executeCodeThatOpensPopUps(Runnable runnable, Runnable resetBrowserInstruction) {
executeCodeThatOpensPopUps(runnable, Optional.of(resetBrowserInstruction));
}
public void assertJSBrowserLogs() {
// flushes the browser logs, so the next time they're retrieved they'll be only related to the refreshed page.
driver.manage().logs().get(LogType.BROWSER);
refreshBrowser();
waitForPageToLoad();
LogEntries logs = driver.manage().logs().get(LogType.BROWSER);
// Workaround, since sometimes the waitForPageToLoad can be called too soon.
// We can't use a "wait" because it would throw a IllegalMonitorStateException.
if(logs.getAll().isEmpty()) {
waitForPageToLoad();
logs = driver.manage().logs().get(LogType.BROWSER);
}
SoftAssert softAssertions = new SoftAssert();
for (LogEntry logEntry : logs) {
if (logEntry.getLevel().getName().contains("SEVERE")) {
softAssertions.fail("Error Message in Console: " + logEntry.getMessage());
} else if (logEntry.getLevel().getName().contains("WARNING")) {
LoggingHelper.warn("Warning Message in Console: " + logEntry.getMessage());
} else {
LoggingHelper.info("Information Message in Console: " + logEntry.getMessage());
}
}
softAssertions.assertAll();
}
// Can be used as a workaround to sometimes the toaster not appearing on screen.
// For some reason, user interaction (pressing keys, moving the mouse...) seems to "unblock" the toaster.
//
// Maybe this method should move to a class 'WebActions' in the future if more actions are created.
public void jiggleMouse() {
final int offset = 25;
new Actions(driver)
.moveByOffset(offset, offset)
.pause(Duration.ofMillis(500))
.moveByOffset(Math.negateExact(offset), Math.negateExact(offset))
.perform();
}
// Tries to keep the current webdriver session alive, to avoid losing it due to long waits, waiting for test methods to end.
public void keepSessionAlive() {
LoggingHelper.info("Try to keep the session alive.");
driver.getCurrentUrl(); // just ping the browser and ignore the response.
}
public void navigateBack() {
LoggingHelper.info("Navigate to the previous page.");
driver.navigate().back();
}
public void navigateTo(String url) {
LoggingHelper.info("Open page [" + url + "].");
driver.navigate().to(url);
}
public void refreshBrowser() {
LoggingHelper.info("Refresh the browser.");
driver.navigate().refresh();
}
public int requestLinkHeadStatusCode(String urlLink) {
RequestSpecification requestSpecification = given();
// only codacy domain URLs should have the cookie rate limit.
if(urlLink.contains(".codacy.")) {
String cookieRateLimit = config.getProperty("cookieRateLimit");
if (cookieRateLimit != null) {
requestSpecification.header("cookie", cookieRateLimit);
}
}
return requestSpecification
.head(urlLink)
.statusCode();
}
public void runConfigMethodWithRetries(Runnable runnable) {
int maxRetries = Integer.parseInt(config.getData(Key.MAX_RETRIES_FOR_SETUP_AND_TEARDOWN_METHODS));
Utils.runMethodWithRetries(runnable, maxRetries);
}
public void scrollIntoView(By locator) {
WebElement targetElement = driver.findElement(locator);
// The false value on scrollIntoView means that the bottom of the element will be aligned to the bottom of the
// visible area of the scrollable ancestor. True would mean top instead of bottom.
String script = "arguments[0].scrollIntoView(false);";
driver.executeScript(script, targetElement);
}
public void waitForCondition(ExpectedCondition condition) {
waitForCondition(config.getTimeout().DEFAULT_TIMEOUT, condition);
}
public void waitForCondition(Duration timeout, ExpectedCondition condition) {
waitForCondition(timeout, config.getTimeout().LONG_POLLING, condition);
}
public void waitForCondition(Duration timeout, Duration polling, ExpectedCondition condition) {
LoggingHelper.info("Wait for condition [" + condition.toString() + "] with a timeout of [" + timeout.toSeconds() + "] seconds.");
new WebDriverWait(driver, timeout)
.pollingEvery(polling)
.ignoreAll(Arrays.asList(StaleElementReferenceException.class, NoSuchElementException.class))
.until(condition);
}
public void waitForFunction(Function