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

com.xlrit.gears.runner.runnertarget.selenide.AbstractSelenideFacade Maven / Gradle / Ivy

The newest version!
package com.xlrit.gears.runner.runnertarget.selenide;

import java.io.File;
import java.time.Duration;

import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.Driver;
import com.codeborne.selenide.SelenideElement;
import com.codeborne.selenide.WebDriverRunner;
import com.fasterxml.jackson.databind.JsonNode;
import com.xlrit.gears.runner.graphql.GraphQLClient;
import com.xlrit.gears.runner.graphql.Operation;
import com.xlrit.gears.runner.driver.RunConfig;
import com.xlrit.gears.runner.runnertarget.RunnerContext;
import com.xlrit.gears.runner.runnertarget.TaskExpression;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.codeborne.selenide.Condition.*;
import static com.codeborne.selenide.Selectors.*;
import static com.codeborne.selenide.Selenide.*;
import static com.xlrit.gears.runner.utils.SelenideUtils.*;

public abstract class AbstractSelenideFacade implements SelenideFacade {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractSelenideFacade.class);

    protected final RunnerContext context;
    protected final GraphQLClient client;
    private final FormSubmitter formSubmitter = new FormSubmitter(this);

    private final int waitMillis;
    private final int timeoutMillis;
    private final boolean submitScreenshots;
    private ProcessIcons processIcons = ProcessIcons.UNKNOWN;

    public AbstractSelenideFacade(RunConfig config, RunnerContext context, GraphQLClient client) {
        this.context = context;
        this.waitMillis = config.waitMillis;
        this.timeoutMillis = config.timeoutMillis;
        this.submitScreenshots = config.submitScreenshots;
        this.client = client;
    }

    @Override
    public void login(String username) {
        open("/#/login");
        type(username, $(byName("username")));
        type(username, $(byName("password")));
        pressButton($("#login-submit-button"));
        $(byName("username")).should(disappear);
        $(byName("password")).should(disappear);
    }

    @Override
    public void logout() {
        LOG.debug("Logging out");
        pressButton($("#account-button"));
        // TODO: this should have a sensible id
        pressButton($(byAttribute("data-testid", "LogoutIcon")));
    }

    @Override
    public void startProcess(String key, JsonNode values) {
        open("/#/gears/processes/start");
        if (processIcons == ProcessIcons.UNKNOWN) detectProcessIcons();
        SelenideElement processButton = switch (processIcons) {
            case YES -> $(byAttribute("gears-id", key));
            case NO -> $(cssId(key));
            case UNKNOWN -> throw new IllegalStateException("Unknown process icon");
        };
        pressButton(processButton);
        if (values != null) submitForm(values);
    }

    @Override
    public void claimTask(String key, TaskExpression taskExpression) {
        waitFor(waitMillis);
        if (urlMatch(".*/#/gears/tasks/.*")) return;
        open("/#/gears/tasks/group");
        pressButton($("#row_0"));
    }

    @Override
    public void submitTask(String processKey, TaskExpression taskExpression, JsonNode values) {
        waitFor(waitMillis);
        if (!urlMatch(".*/#/gears/tasks/.*")) {
            open("/#/gears/tasks/assigned");
            $("#row_0").click();
        }
        submitForm(values);
    }

    @Override
    public String valueToLabel(String value, String fieldId) {
        String choicesId = getFormId();
        JsonNode result = client.invoke(Operation.choiceByValue(choicesId, fieldId, value, urlMatch(".*/#/gears/tasks/.*")));
        if (result.get("choice").isNull()) {
            throw new RuntimeException(String.format("Value %s not found for input %s", value, fieldId));
        }
        return result.get("choice").get("label").asText();
    }

    private void submitForm(JsonNode input) {
        String url = WebDriverRunner.url();
        LOG.debug(String.format("Entering input from %s", input));
        formSubmitter.enterFields(input);
        if (submitScreenshots) fullsizeScreenshot();
        formSubmitter.submit();
        new WebDriverWait(WebDriverRunner.getWebDriver(), Duration.ofMillis(timeoutMillis))
                .until(ExpectedConditions.not(ExpectedConditions.urlToBe(url)));
        new WebDriverWait(WebDriverRunner.getWebDriver(), Duration.ofMillis(timeoutMillis))
                .until(ExpectedConditions.not(ExpectedConditions.urlMatches(".*/#/gears/status/.*")));
        waitFor(waitMillis);
    }

    protected void waitFor(int milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            LOG.error("Wait was interrupted: {}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    private void fullsizeScreenshot() {
        String title = String.format("%s-%03d", context.scenario, context.lineNumber);
        File screenshotFile = new File(String.format("%s/%s.png", Configuration.reportsFolder, title));
        if (screenshotFile.exists() && !screenshotFile.delete()) {
            throw new RuntimeException("Failed to delete already existing screenshot file: " + screenshotFile.getAbsolutePath());
        }
        Driver driver = webdriver().driver();
        long width = driver.executeJavaScript("return window.outerWidth");
        long height = driver.executeJavaScript(JS_GET_HEIGHT);
        driver.getWebDriver().manage().window().setSize(new Dimension((int)width, (int)height + 200));
        String fileName = screenshot(title);
        LOG.debug("Saved before-submit screenshot to {}", fileName);
        var size = Configuration.browserSize.split("x");
        int orgWidth = Integer.parseInt(size[0]);
        int orgHeight = Integer.parseInt(size[1]);
        driver.getWebDriver().manage().window().setSize(new Dimension(orgWidth, orgHeight));
    }

    private void detectProcessIcons() {
        waitFor(waitMillis);
        SelenideElement tilesButton = $(byValue("table"));
        if (tilesButton.exists()) {
            processIcons = ProcessIcons.YES;
            if (tilesButton.has(attribute("aria-pressed", "false"))) pressButton(tilesButton);
            SelenideElement groupButton = $(byValue("none")).should(exist);
            if (groupButton.has(attribute("aria-pressed", "false"))) pressButton(groupButton);
        } else {
            processIcons = ProcessIcons.NO;
        }
    }

    private enum ProcessIcons {
        UNKNOWN,
        YES,
        NO
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy