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

com.applitools.eyes.selenium.rendering.VisualGridEyes Maven / Gradle / Ivy

package com.applitools.eyes.selenium.rendering;

import com.applitools.ICheckSettings;
import com.applitools.ICheckSettingsInternal;
import com.applitools.connectivity.ServerConnector;
import com.applitools.eyes.*;
import com.applitools.eyes.config.Configuration;
import com.applitools.eyes.fluent.CheckSettings;
import com.applitools.eyes.fluent.GetFloatingRegion;
import com.applitools.eyes.fluent.GetSimpleRegion;
import com.applitools.eyes.selenium.*;
import com.applitools.eyes.config.ConfigurationProvider;
import com.applitools.eyes.selenium.fluent.*;
import com.applitools.eyes.selenium.frames.Frame;
import com.applitools.eyes.selenium.frames.FrameChain;
import com.applitools.eyes.selenium.wrappers.EyesTargetLocator;
import com.applitools.eyes.selenium.wrappers.EyesSeleniumDriver;
import com.applitools.eyes.visualgrid.model.*;
import com.applitools.eyes.visualgrid.services.*;
import com.applitools.utils.ArgumentGuard;
import com.applitools.utils.ClassVersionGetter;
import com.applitools.utils.GeneralUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.RemoteWebDriver;

import java.io.IOException;
import java.net.URI;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicBoolean;

public class VisualGridEyes implements ISeleniumEyes, IRenderingEyes {

    private static final long DOM_EXTRACTION_TIMEOUT = 5 * 60 * 1000;
    private final Logger logger;

    private String apiKey;
    private String serverUrl;

    private final VisualGridRunner renderingGridRunner;
    private final List testList = Collections.synchronizedList(new ArrayList());
    private final List testsInCloseProcess = Collections.synchronizedList(new ArrayList());
    List allTestResults = new ArrayList<>();

    private String PROCESS_PAGE;
    private String PROCESS_PAGE_FOR_IE;
    private EyesSeleniumDriver webDriver;
    private RenderingInfo renderingInfo;
    private IEyesConnector VGEyesConnector;
    private IDebugResourceWriter debugResourceWriter;
    private String url;
    private Set> closeFuturesSet = new HashSet<>();
    private Boolean isDisabled = Boolean.FALSE;
    private ServerConnector serverConnector = null;
    private final ConfigurationProvider configurationProvider;
    private UserAgent userAgent = null;
    private RectangleSize viewportSize;
    private final AtomicBoolean isCheckTimerTimedOut = new AtomicBoolean(false);
    private Timer timer = null;
    private final List properties = new ArrayList<>();

    private static final String GET_ELEMENT_XPATH_JS =
            "var el = arguments[0];" +
                    "var xpath = '';" +
                    "do {" +
                    " var parent = el.parentElement;" +
                    " var index = 1;" +
                    " if (parent !== null) {" +
                    "  var children = parent.children;" +
                    "  for (var childIdx in children) {" +
                    "    var child = children[childIdx];" +
                    "    if (child === el) break;" +
                    "    if (child.tagName === el.tagName) index++;" +
                    "  }" +
                    "}" +
                    "xpath = '/' + el.tagName + '[' + index + ']' + xpath;" +
                    " el = parent;" +
                    "} while (el !== null);" +
                    "return '/' + xpath;";


    {
        try {
            PROCESS_PAGE = GeneralUtils.readToEnd(VisualGridEyes.class.getResourceAsStream("/processPageAndSerializePoll.js"));
            PROCESS_PAGE +=  "return __processPageAndSerializePoll();";
            PROCESS_PAGE_FOR_IE = GeneralUtils.readToEnd(VisualGridEyes.class.getResourceAsStream("/processPageAndSerializePollForIE.js"));
            PROCESS_PAGE_FOR_IE += "return __processPageAndSerializePollForIE();";
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public VisualGridEyes(VisualGridRunner renderingGridManager, ConfigurationProvider configurationProvider) {
        this.configurationProvider = configurationProvider;
        ArgumentGuard.notNull(renderingGridManager, "renderingGridRunner");
        this.renderingGridRunner = renderingGridManager;
        this.logger = renderingGridManager.getLogger();
    }

    /**
     * Sets a handler of log messages generated by this API.
     * @param logHandler Handles log messages generated by this API.
     */
    public void setLogHandler(LogHandler logHandler) {
        if (getIsDisabled()) return;
        LogHandler currentLogHandler = logger.getLogHandler();
        this.logger.setLogHandler(new MultiLogHandler(currentLogHandler, logHandler));

        if (currentLogHandler.isOpen() && !logHandler.isOpen()) {
            logHandler.open();
        }
    }

    public LogHandler getLogHandler() {
        if (getIsDisabled()) return NullLogHandler.instance;
        return this.logger.getLogHandler();
    }

    public void apiKey(String apiKey) {
        setApiKey(apiKey);
    }

    public void serverUrl(String serverUrl) {
        setServerUrl(serverUrl);
    }

    public void serverUrl(URI serverUrl) {
        setServerUrl(serverUrl.toString());
    }

    @Override
    public WebDriver open(WebDriver driver, String appName, String testName, RectangleSize viewportSize) throws EyesException {
        getConfiguration().setAppName(appName).setTestName(testName);
        if (viewportSize != null && !viewportSize.isEmpty()) {
            getConfiguration().setViewportSize(new RectangleSize(viewportSize));
        }
        return open(driver);
    }

    public WebDriver open(WebDriver webDriver) {
        logger.verbose("enter");

        if (!validateEyes()) return webDriver;

        ArgumentGuard.notNull(webDriver, "webDriver");
        ArgumentGuard.notNullOrEmpty(getConfiguration().getAppName(), "appIdOrName");
        ArgumentGuard.notNullOrEmpty(getConfiguration().getTestName(), "scenarioIdOrName");

        initDriver(webDriver);

        String uaString = this.webDriver.getUserAgent();
        if (uaString != null) {
            logger.verbose(String.format("User-Agent: %s", uaString));
            userAgent = UserAgent.parseUserAgentString(uaString, true);
        }

        setViewportSize(this.webDriver);

        ensureBrowsers();

        if (getConfiguration().getBatch() == null) {
            getConfiguration().setBatch(new BatchInfo(null));
        }
        logger.verbose("getting all browsers info...");
        List browserInfoList = getConfiguration().getBrowsersInfo();
        logger.verbose("creating test descriptors for each browser info...");
        getConfiguration().setViewportSize(viewportSize);
        if (getConfiguration().getBrowsersInfo() == null) {
            RectangleSize viewportSize = getConfiguration().getViewportSize();
            getConfiguration().addBrowser(new RenderBrowserInfo(viewportSize.getWidth(), viewportSize.getHeight(), BrowserType.CHROME, getConfiguration().getBaselineEnvName()));
        }

        for (RenderBrowserInfo browserInfo : browserInfoList) {
            logger.verbose("creating test descriptor");
            RunningTest test = new RunningTest(this, createVGEyesConnector(browserInfo), configurationProvider, browserInfo, logger);
            this.testList.add(test);
        }

        logger.verbose(String.format("opening %d tests...", testList.size()));
        this.renderingGridRunner.open(this, renderingInfo);
        logger.verbose("done");
        return this.webDriver != null ? this.webDriver : webDriver;
    }

    private void ensureBrowsers() {
        if (this.getConfiguration().getBrowsersInfo().isEmpty()) {
            getConfiguration().getBrowsersInfo().add(new RenderBrowserInfo(viewportSize, BrowserType.CHROME));
        }
    }

    private void setViewportSize(EyesSeleniumDriver webDriver) {
        viewportSize = getConfiguration().getViewportSize();

        if (viewportSize == null) {
            List browserInfoList = getConfiguration().getBrowsersInfo();
            if (browserInfoList != null && !browserInfoList.isEmpty()) {
                for (RenderBrowserInfo deviceInfo : browserInfoList) {
                    if (deviceInfo.getEmulationInfo() != null) {
                        continue;
                    }
                    viewportSize = new RectangleSize(deviceInfo.getWidth(), deviceInfo.getHeight());
                }
            }
        }

        if (viewportSize == null) {
            viewportSize = EyesDriverUtils.getViewportSize(webDriver);

        }

        try {

            EyesDriverUtils.setViewportSize(logger, webDriver, viewportSize);

        } catch (Exception e) {
            GeneralUtils.logExceptionStackTrace(logger, e);
        }
    }

    private IEyesConnector createVGEyesConnector(RenderBrowserInfo browserInfo) {
        logger.verbose("creating VisualGridEyes server connector");
        EyesConnector VGEyesConnector = new EyesConnector(getConfiguration(), this.properties, browserInfo);
        if (browserInfo.getEmulationInfo() != null) {
            VGEyesConnector.setDevice(browserInfo.getEmulationInfo().getDeviceName() + " (Chrome emulation)");
        } else if (browserInfo.getIosDeviceInfo() != null) {
            VGEyesConnector.setDevice(browserInfo.getIosDeviceInfo().getDeviceName());
        }

        VGEyesConnector.setLogHandler(this.logger.getLogHandler());
        VGEyesConnector.setProxy(this.getConfiguration().getProxy());
        if (serverConnector != null) {
            VGEyesConnector.setServerConnector(serverConnector);
        }

        URI serverUri = this.getServerUrl();
        if (serverUri != null) {
            VGEyesConnector.setServerUrl(serverUri.toString());
        }

        String apiKey = this.getApiKey();
        if (apiKey != null) {
            VGEyesConnector.setApiKey(apiKey);
        } else {
            throw new EyesException("Missing API key");
        }

        if (this.renderingInfo == null) {
            logger.verbose("initializing rendering info...");
            this.renderingInfo = VGEyesConnector.getRenderingInfo();
        }
        VGEyesConnector.setRenderInfo(this.renderingInfo);

        this.VGEyesConnector = VGEyesConnector;
        return VGEyesConnector;
    }

    private void initDriver(WebDriver webDriver) {
        if (webDriver instanceof RemoteWebDriver) {
            SeleniumEyes seleniumEyes = new SeleniumEyes(configurationProvider, new ClassicRunner());
            this.webDriver = new EyesSeleniumDriver(logger, seleniumEyes, (RemoteWebDriver) webDriver);
        }
        @SuppressWarnings("UnnecessaryLocalVariable") String currentUrl = webDriver.getCurrentUrl();
        this.url = currentUrl;
    }

    public RunningTest getNextTestToClose() {
        synchronized (testsInCloseProcess) {
            synchronized (testList) {
                for (RunningTest runningTest : testList) {
                    if (!runningTest.isTestClose() && runningTest.isTestReadyToClose() &&
                            !this.testsInCloseProcess.contains(runningTest)) {
                        return runningTest;
                    }
                }
            }
        }
        return null;
    }

    public Collection> close() {
        logger.verbose("enter");
        if (!validateEyes()) {
            return new ArrayList<>();
        }
        return closeAndReturnResults(false);
    }

    public TestResults close(boolean throwException) {
        Collection> close = close();
        return parseCloseFutures(close, throwException);
    }

    private TestResults parseCloseFutures(Collection> close, boolean shouldThrowException) {
        if (close != null && !close.isEmpty()) {
            TestResultContainer errorResult = null;
            TestResultContainer firstResult = null;
            try {
                for (Future closeFuture : close) {
                    TestResultContainer testResultContainer = closeFuture.get();
                    if (firstResult == null) {
                        firstResult = testResultContainer;
                    }
                    Throwable error = testResultContainer.getException();
                    if (error != null && errorResult == null) {
                        errorResult = testResultContainer;
                    }

                }
//                    return firstCloseFuture.get().getTestResults();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }

            if (errorResult != null) {
                if (shouldThrowException) {
                    throw new Error(errorResult.getException());
                } else {
                    return errorResult.getTestResults();
                }
            } else { // returning the first result
                if (firstResult != null) {
                    return firstResult.getTestResults();
                }
            }

        }
        return null;
    }

    public TestResults abortIfNotClosed() {
        List> futures = abortAndCollectTasks();
        return parseCloseFutures(futures, false);
    }

    public boolean getIsOpen() {
        return !isEyesClosed();
    }

    public String getApiKey() {
        return this.apiKey == null ? this.renderingGridRunner.getApiKey() : this.apiKey;
    }

    public void setApiKey(String apiKey) {
        this.apiKey = apiKey;
    }

    public void setIsDisabled(Boolean disabled) {
        this.isDisabled = disabled;
    }

    public boolean getIsDisabled() {
        return this.isDisabled == null ? this.renderingGridRunner.getIsDisabled() : this.isDisabled;
    }

    public URI getServerUrl() {
        if (this.VGEyesConnector != null) {
            URI uri = this.VGEyesConnector.getServerUrl();
            if (uri != null) return uri;
        }
        String str = this.serverUrl == null ? this.renderingGridRunner.getServerUrl() : this.serverUrl;
        return str == null ? null : URI.create(str);
    }

    private Collection> closeAndReturnResults(boolean throwException) {
        logger.verbose("enter " + getConfiguration().getBatch());
        if (!validateEyes()) {
            return new ArrayList<>();
        }

        if (this.closeFuturesSet == null) {
            closeFuturesSet = new HashSet<>();
        }
        Throwable exception = null;
        try {
            Collection> futureList = closeAsync();
            this.renderingGridRunner.close(this);
            for (Future future : futureList) {
                try {
                    TestResultContainer testResultContainer = future.get();
                    if (exception == null && testResultContainer.getException() != null) {
                        exception = testResultContainer.getException();
                    }
                } catch (Throwable e) {
                    GeneralUtils.logExceptionStackTrace(logger, e);
                    if (exception == null) {
                        exception = e;
                    }
                }


            }
        } catch (Throwable e) {
            GeneralUtils.logExceptionStackTrace(logger, e);
        }
        if (throwException && exception != null) {
            throw new Error(exception);
        }
        return closeFuturesSet;
    }

    public Collection> closeAsync() {
        logger.verbose("enter");
        if (!validateEyes()) {
            return new ArrayList<>();
        }
        List> futureList = null;
        try {
            futureList = new ArrayList<>();
            logger.verbose(String.format("closing %d running tests", testList.size()));
            for (RunningTest runningTest : testList) {
                logger.verbose("running test name: " + getConfiguration().getTestName());
                logger.verbose("running test device info: " + runningTest.getBrowserInfo());
                logger.verbose("is current running test open: " + runningTest.isTestOpen());
                logger.verbose("is current running test ready to close: " + runningTest.isTestReadyToClose());
                logger.verbose("is current running test closed: " + runningTest.isTestClose());
                logger.verbose("closing current running test");
                FutureTask closeFuture = runningTest.close();
                if (closeFuture == null) {
                    continue;
                }
                futureList.addAll(Collections.singleton(closeFuture));
                logger.verbose("adding closeFuture to futureList");
            }
            closeFuturesSet.addAll(futureList);
        } catch (Throwable e) {
            GeneralUtils.logExceptionStackTrace(logger, e);
        }

        logger.verbose("exit");
        return futureList;
    }

    @Override
    public synchronized ScoreTask getBestScoreTaskForCheck() {

        int bestScore = -1;

        ScoreTask currentBest = null;
        for (RunningTest runningTest : testList) {

            List visualGridTaskList = runningTest.getVisualGridTaskList();

            VisualGridTask visualGridTask;
            //noinspection SynchronizationOnLocalVariableOrMethodParameter
            synchronized (visualGridTaskList) {
                if (visualGridTaskList.isEmpty()) continue;

                visualGridTask = visualGridTaskList.get(0);
                if (!runningTest.isTestOpen() || visualGridTask.getType() != VisualGridTask.TaskType.CHECK || !visualGridTask.isTaskReadyToCheck())
                    continue;
            }


            ScoreTask scoreTask = runningTest.getScoreTaskObjectByType(VisualGridTask.TaskType.CHECK);

            if (scoreTask == null) continue;

            if (bestScore < scoreTask.getScore()) {
                currentBest = scoreTask;
                bestScore = scoreTask.getScore();
            }
        }
        return currentBest;
    }

    @Override
    public ScoreTask getBestScoreTaskForOpen() {
        int bestMark = -1;
        ScoreTask currentBest = null;
        synchronized (testList) {
            for (RunningTest runningTest : testList) {

                ScoreTask currentScoreTask = runningTest.getScoreTaskObjectByType(VisualGridTask.TaskType.OPEN);
                if (currentScoreTask == null) continue;

                if (bestMark < currentScoreTask.getScore()) {
                    bestMark = currentScoreTask.getScore();
                    currentBest = currentScoreTask;

                }
            }
        }
        return currentBest;
    }

    public void setServerUrl(String serverUrl) {
        this.serverUrl = serverUrl;
    }

    @Override
    public boolean isEyesClosed() {
        boolean isVGEyesClosed = true;
        for (RunningTest runningTest : testList) {
            isVGEyesClosed = isVGEyesClosed && runningTest.isTestClose();
        }
        return isVGEyesClosed;
    }

    public void setListener(EyesListener listener) {
        for (RunningTest test : testList) {
            test.setListener(listener);
        }
    }


    public void check(ICheckSettings... checkSettings) {
        if (!validateEyes()) return;
        for (ICheckSettings checkSetting : checkSettings) {
            this.check(checkSetting);
        }
    }

    public void check(String name, ICheckSettings checkSettings) {
        if (!validateEyes()) return;
        ArgumentGuard.notNull(checkSettings, "checkSettings");
        if (name != null) {
            checkSettings = checkSettings.withName(name);
        }
        this.check(checkSettings);
    }

    public void check(ICheckSettings checkSettings) {
        logger.verbose("enter");

        if (!validateEyes()) {
            return;
        }

        ArgumentGuard.notOfType(checkSettings, ICheckSettings.class, "checkSettings");
        if (checkSettings instanceof ISeleniumCheckTarget) {
            ((ISeleniumCheckTarget) checkSettings).init(logger, webDriver);
        }

        waitBeforeDomSnapshot();

        try {
            FrameChain originalFC = webDriver.getFrameChain().clone();
            EyesTargetLocator switchTo = ((EyesTargetLocator) webDriver.switchTo());
            checkSettings = switchFramesAsNeeded(checkSettings, switchTo);
            ICheckSettingsInternal checkSettingsInternal = (ICheckSettingsInternal) checkSettings;

            isCheckTimerTimedOut.set(false);

            List openVisualGridTasks = addOpenTaskToAllRunningTest();
            List visualGridTaskList = new ArrayList<>();

            FrameData scriptResult = captureDomSnapshot(originalFC, switchTo, checkSettingsInternal);

            List regionsXPaths = getRegionsXPaths(checkSettingsInternal);
            logger.verbose("regionXPaths : " + regionsXPaths);

            trySetTargetSelector((SeleniumCheckSettings) checkSettings);

            checkSettingsInternal = updateCheckSettings(checkSettings);

            List filteredTests = collectTestsForCheck(testList);

            String source = webDriver.getCurrentUrl();
            for (RunningTest runningTest : filteredTests) {
                VisualGridTask checkVisualGridTask = runningTest.check((ICheckSettings) checkSettingsInternal, regionsXPaths, source);
                visualGridTaskList.add(checkVisualGridTask);
            }

            logger.verbose("added check tasks  (" + checkSettingsInternal.toString() + ")");

            this.renderingGridRunner.check((ICheckSettings) checkSettingsInternal, debugResourceWriter, scriptResult,
                    this.VGEyesConnector, visualGridTaskList, openVisualGridTasks,
                    new VisualGridRunner.RenderListener() {
                        @Override
                        public void onRenderSuccess() {

                        }

                        @Override
                        public void onRenderFailed(Exception e) {
                            GeneralUtils.logExceptionStackTrace(logger, e);
                        }
                    }, regionsXPaths, userAgent);
            logger.verbose("created renderTask  (" + checkSettings.toString() + ")");
            switchTo.frames(originalFC);
        } catch (Throwable e) {
            Error error = new Error(e);
            abort(e);
            for (RunningTest runningTest : testList) {
                runningTest.setTestInExceptionMode(error);
            }
            GeneralUtils.logExceptionStackTrace(logger, e);
        } finally {
            if (timer != null) {
                timer.cancel();
            }
        }
    }

    /******** BEGIN - PUBLIC FOR TESTING PURPOSES ONLY ********/
    public static List collectTestsForCheck(List tests) {
        List filteredTests = new ArrayList<>();
        for (final RunningTest test : tests) {
            List taskList = test.getVisualGridTaskList();
            VisualGridTask visualGridTask = null;
            if (!taskList.isEmpty()) {
                visualGridTask = taskList.get(taskList.size() - 1);
            }

            VisualGridTask.TaskType lastTaskType = null;
            if (visualGridTask != null) {
                lastTaskType = visualGridTask.getType();
            }

            boolean testIsOpenAndNotClosed = lastTaskType == null && test.isOpenTaskIssued() && !test.isCloseTaskIssued();
            boolean lastTaskIsNotAClosingTask = lastTaskType != null && lastTaskType != VisualGridTask.TaskType.CLOSE && lastTaskType != VisualGridTask.TaskType.ABORT;

            // We are interested in tests which should be opened or are open.
            if (testIsOpenAndNotClosed || lastTaskIsNotAClosingTask) {
                filteredTests.add(test);
            }
        }
        return filteredTests;
    }
    /******** END - PUBLIC FOR TESTING PURPOSES ONLY ********/

    private ICheckSettings switchFramesAsNeeded(ICheckSettings checkSettings, EyesTargetLocator switchTo) {
        int switchedToCount = switchToFrame((ISeleniumCheckTarget) checkSettings);
        boolean isFullPage = isFullPage((ICheckSettingsInternal) checkSettings);
        if (switchedToCount > 0 && isFullPage) {
            FrameChain frameChain = webDriver.getFrameChain().clone();
            Frame frame = frameChain.pop();
            checkSettings = ((SeleniumCheckSettings) checkSettings).region(frame.getReference());
            switchTo.parentFrame();
        }
        return checkSettings;
    }

    private boolean isFullPage(ICheckSettingsInternal checkSettingsInternal) {
        boolean isFullPage = true;
        Boolean b;
        if ((b = checkSettingsInternal.isStitchContent()) != null) {
            isFullPage = b;
        } else if ((b = getConfiguration().isForceFullPageScreenshot()) != null) {
            isFullPage = b;
        }
        return isFullPage;
    }

    private FrameData captureDomSnapshot(FrameChain originalFC, EyesTargetLocator switchTo, ICheckSettingsInternal checkSettingsInternal) throws InterruptedException {
        logger.verbose("Dom extraction starting   (" + checkSettingsInternal.toString() + ")");
        timer = new Timer("VG_Check_StopWatch", true);
        timer.schedule(new TimeoutTask(), DOM_EXTRACTION_TIMEOUT);
        String resultAsString;
        ScriptResponse.Status status = null;
        ScriptResponse scriptResponse = null;
        do {
            if (userAgent.isInternetExplorer()) {
                resultAsString = (String) this.webDriver.executeScript(PROCESS_PAGE_FOR_IE);
            } else {
                resultAsString = (String) this.webDriver.executeScript(PROCESS_PAGE);
            }

            try {
                scriptResponse = GeneralUtils.parseJsonToObject(resultAsString, ScriptResponse.class);
                logger.verbose("Dom extraction polling...");
                status = scriptResponse.getStatus();
            } catch (IOException e) {
                GeneralUtils.logExceptionStackTrace(logger, e);
            }
            Thread.sleep(200);
        } while (status == ScriptResponse.Status.WIP && !isCheckTimerTimedOut.get());
        timer.cancel();

        if (status == ScriptResponse.Status.ERROR) {
            switchTo.frames(originalFC);
            throw new EyesException("DomSnapshot Error: " + scriptResponse.getError());
        }

        if (isCheckTimerTimedOut.get()) {
            switchTo.frames(originalFC);
            throw new EyesException("Domsnapshot Timed out");
        }
        FrameData scriptResult = scriptResponse != null ? scriptResponse.getValue() : null;

        logger.verbose("Dom extracted  (" + checkSettingsInternal.toString() + ")");
        return scriptResult;
    }

    private void waitBeforeDomSnapshot() {
        int waitBeforeScreenshots = this.getConfiguration().getWaitBeforeScreenshots();
        try {
            Thread.sleep(waitBeforeScreenshots);
        } catch (InterruptedException e) {
            GeneralUtils.logExceptionStackTrace(logger, e);
        }
    }

    private ICheckSettingsInternal updateCheckSettings(ICheckSettings checkSettings) {
        ICheckSettingsInternal checkSettingsInternal = (ICheckSettingsInternal) checkSettings;

        MatchLevel matchLevel = checkSettingsInternal.getMatchLevel();

        Boolean fully = checkSettingsInternal.isStitchContent();
        Boolean sendDom = checkSettingsInternal.isSendDom();
        Boolean ignoreDisplacements = checkSettingsInternal.isIgnoreDisplacements();

        Boolean b;

        if (matchLevel == null) {
            checkSettings = checkSettings.matchLevel(getConfiguration().getMatchLevel());
        }

        if (fully == null) {
            checkSettings = checkSettings.fully((b = getConfiguration().isForceFullPageScreenshot()) == null || b);
        }

        if (sendDom == null) {
            checkSettings = checkSettings.sendDom((b = getConfiguration().isSendDom()) == null || b);
        }

        if (ignoreDisplacements == null) {
            checkSettings = checkSettings.ignoreDisplacements(getConfiguration().getIgnoreDisplacements());
        }

        List options = new ArrayList<>();
        options.addAll(getConfiguration().getVisualGridOptions());
        options.addAll(checkSettingsInternal.getVisualGridOptions());
        checkSettings = checkSettings.visualGridOptions(options.size() > 0 ? options.toArray(new VisualGridOption[]{}) : null);
        return (ICheckSettingsInternal) checkSettings;
    }

    private void trySetTargetSelector(SeleniumCheckSettings checkSettings) {
        WebElement element = checkSettings.getTargetElement();
        FrameChain frameChain = webDriver.getFrameChain().clone();
        EyesTargetLocator switchTo = (EyesTargetLocator) webDriver.switchTo();
        switchToFrame(checkSettings);
        if (element == null) {
            By targetSelector = checkSettings.getTargetSelector();
            if (targetSelector != null) {
                element = webDriver.findElement(targetSelector);
            }
        }
        if (element != null) {
            String xpath = (String) webDriver.executeScript(GET_ELEMENT_XPATH_JS, element);
            VisualGridSelector vgs = new VisualGridSelector(xpath, "target");
            checkSettings.setTargetSelector(vgs);
        }
        switchTo.frames(frameChain);
    }

    @SuppressWarnings("UnusedReturnValue")
    private int switchToFrame(ISeleniumCheckTarget checkTarget) {
        if (checkTarget == null) {
            return 0;
        }

        List frameChain = checkTarget.getFrameChain();
        int switchedToFrameCount = 0;
        for (FrameLocator frameLocator : frameChain) {
            if (switchToFrame(frameLocator)) {
                switchedToFrameCount++;
            }
        }
        return switchedToFrameCount;
    }

    private boolean switchToFrame(ISeleniumFrameCheckTarget frameTarget) {
        WebDriver.TargetLocator switchTo = this.webDriver.switchTo();

        if (frameTarget.getFrameIndex() != null) {
            switchTo.frame(frameTarget.getFrameIndex());
            updateFrameScrollRoot(frameTarget);
            return true;
        }

        if (frameTarget.getFrameNameOrId() != null) {
            switchTo.frame(frameTarget.getFrameNameOrId());
            updateFrameScrollRoot(frameTarget);
            return true;
        }

        if (frameTarget.getFrameReference() != null) {
            switchTo.frame(frameTarget.getFrameReference());
            updateFrameScrollRoot(frameTarget);
            return true;
        }

        if (frameTarget.getFrameSelector() != null) {
            WebElement frameElement = this.webDriver.findElement(frameTarget.getFrameSelector());
            if (frameElement != null) {
                switchTo.frame(frameElement);
                updateFrameScrollRoot(frameTarget);
                return true;
            }
        }

        return false;
    }

    private void updateFrameScrollRoot(IScrollRootElementContainer frameTarget) {
        WebElement rootElement = EyesSeleniumUtils.getScrollRootElement(logger, webDriver, frameTarget);
        Frame frame = webDriver.getFrameChain().peek();
        frame.setScrollRootElement(rootElement);
    }

    private synchronized List addOpenTaskToAllRunningTest() {
        logger.verbose("enter");
        List visualGridTasks = new ArrayList<>();
        for (RunningTest runningTest : testList) {
            if (!runningTest.isOpenTaskIssued()) {
                VisualGridTask visualGridTask = runningTest.open();
                visualGridTasks.add(visualGridTask);
            }
        }
        logger.verbose("calling addOpenTaskToAllRunningTest.open");
        logger.verbose("exit");
        return visualGridTasks;
    }

    public Logger getLogger() {
        return logger;
    }

    public List getAllRunningTests() {
        return testList;
    }

    public void setDebugResourceWriter(IDebugResourceWriter debugResourceWriter) {
        this.debugResourceWriter = debugResourceWriter;
    }

    @Override
    public String toString() {
        return "SeleniumVGEyes - url: " + url;
    }

    public void setServerConnector(ServerConnector serverConnector) {
        this.serverConnector = serverConnector;
    }


    /**
     * @return The full agent id composed of both the base agent id and the
     * user given agent id.
     */
    public String getFullAgentId() {
        String agentId = getConfiguration().getAgentId();
        if (agentId == null) {
            return getBaseAgentId();
        }
        return String.format("%s [%s]", agentId, getBaseAgentId());
    }

    private Configuration getConfiguration() {
        return configurationProvider.get();
    }

    @SuppressWarnings("WeakerAccess")
    public String getBaseAgentId() {
        //noinspection SpellCheckingInspection
        return "eyes.selenium.visualgrid.java/" + ClassVersionGetter.CURRENT_VERSION;
    }

    /**
     * Sets the batch in which context future tests will run or {@code null}
     * if tests are to run standalone.
     * @param batch The batch info to set.
     */
    public void setBatch(BatchInfo batch) {
        if (isDisabled) {
            logger.verbose("Ignored");
            return;
        }

        logger.verbose("setBatch(" + batch + ")");

        this.getConfiguration().setBatch(batch);
    }

    private List getRegionsXPaths(ICheckSettingsInternal csInternal) {
        List result = new ArrayList<>();
        List[] elementLists = collectSeleniumRegions(csInternal);
        for (List elementList : elementLists) {
            //noinspection SpellCheckingInspection
            List xpaths = new ArrayList<>();
            for (WebElementRegion webElementRegion : elementList) {
                if (webElementRegion.getElement() == null) continue;
                String xpath = (String) webDriver.executeScript(GET_ELEMENT_XPATH_JS, webElementRegion.getElement());
                xpaths.add(new VisualGridSelector(xpath, webElementRegion.getRegion()));
            }
            result.add(xpaths.toArray(new VisualGridSelector[0]));
        }
        return result;
    }

    private List[] collectSeleniumRegions(ICheckSettingsInternal csInternal) {
        CheckSettings settings = (CheckSettings) csInternal;
        GetSimpleRegion[] ignoreRegions = settings.getIgnoreRegions();
        GetSimpleRegion[] layoutRegions = settings.getLayoutRegions();
        GetSimpleRegion[] strictRegions = settings.getStrictRegions();
        GetSimpleRegion[] contentRegions = settings.getContentRegions();
        GetFloatingRegion[] floatingRegions = settings.getFloatingRegions();
        GetAccessibilityRegion[] accessibilityRegions = settings.getAccessibilityRegions();

        List ignoreElements = getElementsFromRegions(Arrays.asList(ignoreRegions));
        List layoutElements = getElementsFromRegions(Arrays.asList(layoutRegions));
        List strictElements = getElementsFromRegions(Arrays.asList(strictRegions));
        List contentElements = getElementsFromRegions(Arrays.asList(contentRegions));
        List floatingElements = getElementsFromRegions(Arrays.asList(floatingRegions));
        List accessibilityElements = getElementsFromRegions(Arrays.asList(accessibilityRegions));


        ISeleniumCheckTarget iSeleniumCheckTarget = (ISeleniumCheckTarget) csInternal;
        WebElement targetElement = iSeleniumCheckTarget.getTargetElement();

        if (targetElement == null) {
            By targetSelector = iSeleniumCheckTarget.getTargetSelector();
            if (targetSelector != null) {
                targetElement = webDriver.findElement(targetSelector);
            }
        }

        WebElementRegion target = new WebElementRegion(targetElement, "target");
        List targetElementList = new ArrayList<>();
        targetElementList.add(target);
        //noinspection UnnecessaryLocalVariable,unchecked
        List[] lists = new List[]{ignoreElements, layoutElements, strictElements, contentElements, floatingElements, accessibilityElements, targetElementList};
        return lists;
    }


    private List getElementsFromRegions(List regionsProvider) {
        List elements = new ArrayList<>();
        for (Object getRegion : regionsProvider) {
            if (getRegion instanceof IGetSeleniumRegion) {
                IGetSeleniumRegion getSeleniumRegion = (IGetSeleniumRegion) getRegion;
                List webElements = getSeleniumRegion.getElements();
                for (WebElement webElement : webElements) {
                    elements.add(new WebElementRegion(webElement, getRegion));
                }
            }
        }
        return elements;
    }

    /**
     * Adds a property to be sent to the server.
     * @param name  The property name.
     * @param value The property value.
     */
    public void addProperty(String name, String value) {
        PropertyData pd = new PropertyData(name, value);
        properties.add(pd);
    }

    /**
     * Clears the list of custom properties.
     */
    public void clearProperties() {
        properties.clear();
    }

    private class TimeoutTask extends TimerTask {
        @Override
        public void run() {
            logger.verbose("Check Timer timeout.");
            isCheckTimerTimedOut.set(true);
        }
    }

    @SuppressWarnings("BooleanMethodIsAlwaysInverted")
    private boolean validateEyes() {
        if (isDisabled) {
            logger.verbose("WARNING! Invalid Operation - Eyes Disabled!");
            return false;
        }
        if (!renderingGridRunner.isServicesOn()) {
            logger.verbose("WARNING! Invalid Operation - visualGridRunner.getAllTestResults already called!");
            return false;
        }
        return true;
    }

    @Override
    public List getAllTestResults() {
        return allTestResults;
    }

    public EyesSeleniumDriver getDriver() {
        return webDriver;
    }

    @Override
    public IBatchCloser getBatchCloser() {
        return this.testList.get(0).getBatchCloser();
    }

    @Override
    public String getBatchId() {
        return this.getConfiguration().getBatch().getId();
    }

    private void abort(Throwable e) {
        for (RunningTest runningTest : testList) {
            runningTest.abort(true, e);
        }
    }

    public void abortAsync() {
        abortAndCollectTasks();
    }

    public TestResults abort() {
        List> tasks = abortAndCollectTasks();
        return parseCloseFutures(tasks, false);
    }

    private List> abortAndCollectTasks() {
        List> tasks = new ArrayList<>();
        for (RunningTest runningTest : testList) {
            Future task = runningTest.abort(false, null);
            tasks.add(task);
        }

        return tasks;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy