package aquality.selenium.browser; import aquality.selenium.configuration.IBrowserProfile; import aquality.selenium.configuration.ITimeoutConfiguration; import aquality.selenium.core.applications.IApplication; import aquality.selenium.core.localization.ILocalizationManager; import aquality.selenium.core.localization.ILocalizedLogger; import aquality.selenium.core.waitings.IConditionalWait; import org.apache.commons.io.IOUtils; import org.openqa.selenium.Alert; import org.openqa.selenium.Dimension; import org.openqa.selenium.NoAlertPresentException; import org.openqa.selenium.OutputType; import org.openqa.selenium.WebDriver.Navigation; import org.openqa.selenium.logging.LogEntries; import org.openqa.selenium.remote.RemoteWebDriver; import org.openqa.selenium.support.ui.ExpectedCondition; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; public class Browser implements IApplication { private final RemoteWebDriver webDriver; private final ITimeoutConfiguration timeouts; private final IBrowserProfile browserProfile; private final IConditionalWait conditionalWait; private final ILocalizationManager localizationManager; private final ILocalizedLogger localizedLogger; private Duration implicitTimeout; public Browser(RemoteWebDriver remoteWebDriver) { conditionalWait = AqualityServices.getConditionalWait(); localizationManager = AqualityServices.get(ILocalizationManager.class); localizedLogger = AqualityServices.getLocalizedLogger(); this.browserProfile = AqualityServices.getBrowserProfile(); this.timeouts = AqualityServices.get(ITimeoutConfiguration.class); webDriver = remoteWebDriver; this.implicitTimeout = timeouts.getImplicit(); getDriver().manage().timeouts().implicitlyWait(implicitTimeout.getSeconds(), TimeUnit.SECONDS); setPageLoadTimeout(timeouts.getPageLoad()); setScriptTimeout(timeouts.getScript()); } /** * Executes browser quit, closes all windows and dispose session */ public void quit() { localizedLogger.info("loc.browser.driver.quit"); if (getDriver() != null) { getDriver().quit(); } } /** * Provides Selenium WebDriver instance for current browser session * * @return web driver instance */ public RemoteWebDriver getDriver() { return webDriver; } @Override public boolean isStarted() { return webDriver.getSessionId() != null; } /** * Executes navigating by passed URL * * @param url URL where you wish to navigate */ public void goTo(String url) { navigate().to(url); } /** * Executes navigating back */ public void goBack() { navigate().back(); } /** * Executes navigating forward */ public void goForward() { navigate().forward(); } /** * Executes browser window maximizing */ public void maximize() { localizedLogger.info("loc.browser.maximize"); getDriver().manage().window().maximize(); } /** * Returns current page's URL * * @return current page's URL */ public String getCurrentUrl() { localizedLogger.info("loc.browser.getUrl"); return getDriver().getCurrentUrl(); } /** * Executes refreshing of current page */ public void refresh() { navigate().refresh(); } /** * Refreshes the page and process alert that apears after refreshing * * @param alertAction accept or decline alert */ public void refreshPageWithAlert(AlertActions alertAction) { refresh(); handleAlert(alertAction); } private Navigation navigate() { return new BrowserNavigation(getDriver()); } /** * Provides interface to manage of browser tabs. * @return Instance of IBrowserTabNavigation. */ public IBrowserTabNavigation tabs() { return new BrowserTabNavigation(getDriver()); } /** * Sets page load timeout (Will be ignored for Safari https://github.com/SeleniumHQ/selenium-google-code-issue-archive/issues/687) * * @param timeout seconds to wait */ public void setPageLoadTimeout(Duration timeout) { localizedLogger.debug("loc.browser.page.load.timeout", timeout.getSeconds()); if (!getBrowserName().equals(BrowserName.SAFARI)) { getDriver().manage().timeouts().pageLoadTimeout(timeout.getSeconds(), TimeUnit.SECONDS); } } /** * Sets web driver implicit wait timeout * Be careful with using this method. Implicit timeout can affect to duration of driver operations * * @param timeout duration of time to wait */ public void setImplicitWaitTimeout(Duration timeout) { localizedLogger.debug("loc.browser.implicit.timeout", timeout.getSeconds()); if (!timeout.equals(getImplicitWaitTimeout())) { getDriver().manage().timeouts().implicitlyWait(timeout.getSeconds(), TimeUnit.SECONDS); implicitTimeout = timeout; } } /** * Sets timeout to async javascript executions * * @param timeout timeout in seconds */ public void setScriptTimeout(Duration timeout) { localizedLogger.debug("loc.browser.script.timeout", timeout.getSeconds()); getDriver().manage().timeouts().setScriptTimeout(timeout.getSeconds(), TimeUnit.SECONDS); } /** * Waits until page is loaded * TimeoutException will be thrown if page is not loaded during timeout * Default timeout is fetched from settings file. * Use setPageLoadTimeout to configure your own timeout from code if it is necessary */ public void waitForPageToLoad() { ExpectedCondition<Boolean> condition = d -> { Object result = executeScript(JavaScript.IS_PAGE_LOADED.getScript()); return result instanceof Boolean && (Boolean) result; }; conditionalWait.waitFor(condition, timeouts.getPageLoad(), timeouts.getPollingInterval(), localizationManager.getLocalizedMessage("loc.browser.page.timeout")); } /** * Makes screenshot of the current page * * @return screenshot as array of bytes */ public byte[] getScreenshot() { return getDriver().getScreenshotAs(OutputType.BYTES); } /** * Gets logs from WebDriver. * @param logKind Type of logs {@link org.openqa.selenium.logging.LogType} * @return Storage of LogEntries. */ public LogEntries getLogs(final String logKind) { return getDriver().manage().logs().get(logKind); } /** * Executes JS (jQuery) script asynchronous. * * @param script Java Script * @param arguments Arguments for the script (web elements, values etc. * @return Result object of script execution */ public Object executeAsyncScript(final String script, Object... arguments) { return executeJavaScript(() -> getDriver().executeAsyncScript(script, arguments)); } /** * Executes JS (jQuery) script from the resource file asynchronous. * To see the list of scripts see {@link JavaScript} * JS files can be found in ~/resources/js/ * * @param scriptName {@link JavaScript} * @param args List of script arguments. This list is unique for each script. * @return Result object of script execution */ public Object executeAsyncScript(JavaScript scriptName, Object... args) { return executeAsyncScript(scriptName.getScript(), args); } /** * Executes JS (jQuery) script from the File asynchronous. * * @param file Java Script file * @param arguments Arguments for the script (web elements, values etc. * @return Result object of script execution * @throws IOException in case of problems with the File */ public Object executeAsyncScript(final File file, Object... arguments) throws IOException { return executeAsyncScript(IOUtils.toString(file.toURI(), StandardCharsets.UTF_8.name()), arguments); } /** * Executes JS (jQuery) script. * * @param script Java Script * @param arguments Arguments for the script (web elements, values etc. * @return Result object of script execution */ public Object executeScript(final String script, Object... arguments) { return executeJavaScript(() -> getDriver().executeScript(script, arguments)); } private Object executeJavaScript(Supplier<Object> executeScriptFunc) { Object result = executeScriptFunc.get(); return result instanceof Boolean ? Boolean.parseBoolean(result.toString()) : result; } /** * Executes JS (jQuery) script from the resource file. * To see the list of scripts see {@link JavaScript} * JS files can be found in ~/resources/js/ * * @param scriptName {@link JavaScript} * @param args List of script arguments. This list is unique for each script. * @return Result object of script execution */ public Object executeScript(JavaScript scriptName, Object... args) { return executeScript(scriptName.getScript(), args); } /** * Executes JS (jQuery) script from the File. * * @param file Java Script file * @param arguments Arguments for the script (web elements, values etc. * @return Result object of script execution * @throws IOException in case of problems with the File */ public Object executeScript(final File file, Object... arguments) throws IOException { return executeScript(IOUtils.toString(file.toURI(), StandardCharsets.UTF_8.name()), arguments); } /** * Accepts or declines appeared alert * * @param alertAction accept or decline */ public void handleAlert(AlertActions alertAction) { handlePromptAlert(alertAction, null); } /** * Accepts or declines prompt with sending message * * @param alertAction accept or decline * @param text message to send */ public void handlePromptAlert(AlertActions alertAction, String text) { try { Alert alert = getDriver().switchTo().alert(); if (text != null && !text.isEmpty()) { getDriver().switchTo().alert().sendKeys(text); } if (alertAction.equals(AlertActions.ACCEPT)) { alert.accept(); } else { alert.dismiss(); } } catch (NoAlertPresentException exception) { localizedLogger.fatal("loc.browser.alert.fail", exception); throw exception; } } /** * Executes scrolling of the page to given coordinates x and y * * @param x coordinate x * @param y coordinate y */ public void scrollWindowBy(int x, int y) { executeScript(JavaScript.SCROLL_WINDOW_BY.getScript(), x, y); } /** * Sets given window size * * @param width desired window width * @param height desired window height */ public void setWindowSize(int width, int height) { getDriver().manage().window().setSize(new Dimension(width, height)); } /** * Returns path to download directory * Path is configured during web driver setup by value from settings.json * * @return path to download directory */ public String getDownloadDirectory() { return browserProfile.getDriverSettings().getDownloadDir(); } /** * Returns name of current browser * * @return name */ public final BrowserName getBrowserName() { return browserProfile.getBrowserName(); } private Duration getImplicitWaitTimeout() { return implicitTimeout; } }