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

au.com.agic.apptesting.utils.impl.SimpleWebElementInteractionImpl Maven / Gradle / Ivy

package au.com.agic.apptesting.utils.impl;

import static com.google.common.base.Preconditions.checkNotNull;

import au.com.agic.apptesting.constants.Constants;
import au.com.agic.apptesting.exception.WebElementException;
import au.com.agic.apptesting.utils.GetBy;
import au.com.agic.apptesting.utils.SimpleWebElementInteraction;
import au.com.agic.apptesting.utils.ThreadDetails;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Implementation of the SimpleWebElementInteraction service
 */
public class SimpleWebElementInteractionImpl implements SimpleWebElementInteraction {
	private static final Logger LOGGER = LoggerFactory.getLogger(SimpleWebElementInteractionImpl.class);
	private static final GetBy GET_BY = new GetByImpl();

	@Override
	public CompletableFuture getClickableElementFoundBy(
			final boolean valueAlias,
			final String value,
			final ThreadDetails threadDetails) {

		return getClickableElementFoundBy(valueAlias, value, threadDetails, Constants.WAIT);
	}

	@Override
	public CompletableFuture getClickableElementFoundBy(
			final boolean valueAlias,
			final String value,
			final ThreadDetails threadDetails,
			final long wait) {

		final CompletableFuture retValue = new CompletableFuture<>();
		final AtomicInteger failures = new AtomicInteger(0);
		final List threads = new CopyOnWriteArrayList<>();

		final By by = GET_BY.getBy(GetBy.ID, valueAlias, value, threadDetails);
		final WebDriverWait waitId = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionId =
			ExpectedConditions.elementToBeClickable(by);
		final Thread byIDThread = new Thread(
			new GetElement(waitId, conditionId, failures, retValue, threads));
		threads.add(byIDThread);

		final By byXpath = GET_BY.getBy(GetBy.XPATH, valueAlias, value, threadDetails);
		final WebDriverWait waitXpath = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionXpath =
			ExpectedConditions.elementToBeClickable(byXpath);
		final Thread byXpathThread = new Thread(
			new GetElement(waitXpath, conditionXpath, failures, retValue, threads));
		threads.add(byXpathThread);

		final By byName = GET_BY.getBy(GetBy.NAME, valueAlias, value, threadDetails);
		final WebDriverWait waitName = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionName =
			ExpectedConditions.elementToBeClickable(byName);
		final Thread byNameThread = new Thread(
			new GetElement(waitName, conditionName, failures, retValue, threads));
		threads.add(byNameThread);

		final By byValue = GET_BY.getBy(GetBy.VALUE, valueAlias, value, threadDetails);
		final WebDriverWait waitValue = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionValue =
			ExpectedConditions.elementToBeClickable(byValue);
		final Thread byValueThread = new Thread(
			new GetElement(waitValue, conditionValue, failures, retValue, threads));
		threads.add(byValueThread);

		final By byText = GET_BY.getBy(GetBy.TEXT, valueAlias, value, threadDetails);
		final WebDriverWait waitText = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionText =
			ExpectedConditions.elementToBeClickable(byText);
		final Thread byTextThread = new Thread(
			new GetElement(waitText, conditionText, failures, retValue, threads));
		threads.add(byTextThread);

		final By byClass = GET_BY.getBy(GetBy.CLASS, valueAlias, value, threadDetails);
		final WebDriverWait waitClass = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionClass =
			ExpectedConditions.elementToBeClickable(byClass);
		final Thread byClassThread = new Thread(
			new GetElement(waitClass, conditionClass, failures, retValue, threads));
		threads.add(byClassThread);

		final By bySelector = GET_BY.getBy(GetBy.CSS_SELECTOR, valueAlias, value, threadDetails);
		final WebDriverWait waitSelector = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionSelector =
			ExpectedConditions.elementToBeClickable(bySelector);
		final Thread bySelectorThread = new Thread(
			new GetElement(waitSelector, conditionSelector, failures, retValue, threads));
		threads.add(bySelectorThread);

		threads.stream().forEach(Thread::start);

		return retValue;
	}

	@Override
	public CompletableFuture getVisibleElementFoundBy(
			final boolean valueAlias,
			final String value,
			final ThreadDetails threadDetails) {

		return getVisibleElementFoundBy(valueAlias, value, threadDetails, Constants.WAIT);
	}

	@Override
	public CompletableFuture getVisibleElementFoundBy(
			final boolean valueAlias,
			final String value,
			final ThreadDetails threadDetails,
			final long wait) {

		final CompletableFuture retValue = new CompletableFuture<>();
		final AtomicInteger failures = new AtomicInteger(0);
		final List threads = new CopyOnWriteArrayList<>();

		final By by = GET_BY.getBy(GetBy.ID, valueAlias, value, threadDetails);
		final WebDriverWait waitId = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionId =
			ExpectedConditions.visibilityOfElementLocated(by);
		final Thread byIDThread = new Thread(
			new GetElement(waitId, conditionId, failures, retValue, threads));
		threads.add(byIDThread);

		final By byXpath = GET_BY.getBy(GetBy.XPATH, valueAlias, value, threadDetails);
		final WebDriverWait waitXpath = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionXpath =
			ExpectedConditions.visibilityOfElementLocated(byXpath);
		final Thread byXpathThread = new Thread(
			new GetElement(waitXpath, conditionXpath, failures, retValue, threads));
		threads.add(byXpathThread);

		final By byName = GET_BY.getBy(GetBy.NAME, valueAlias, value, threadDetails);
		final WebDriverWait waitName = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionName =
			ExpectedConditions.visibilityOfElementLocated(byName);
		final Thread byNameThread = new Thread(
			new GetElement(waitName, conditionName, failures, retValue, threads));
		threads.add(byNameThread);

		final By byValue = GET_BY.getBy(GetBy.VALUE, valueAlias, value, threadDetails);
		final WebDriverWait waitValue = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionValue =
			ExpectedConditions.visibilityOfElementLocated(byValue);
		final Thread byValueThread = new Thread(
			new GetElement(waitValue, conditionValue, failures, retValue, threads));
		threads.add(byValueThread);

		final By byText = GET_BY.getBy(GetBy.TEXT, valueAlias, value, threadDetails);
		final WebDriverWait waitText = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionText =
			ExpectedConditions.visibilityOfElementLocated(byText);
		final Thread byTextThread = new Thread(
			new GetElement(waitText, conditionText, failures, retValue, threads));
		threads.add(byTextThread);

		final By byClass = GET_BY.getBy(GetBy.CLASS, valueAlias, value, threadDetails);
		final WebDriverWait waitClass = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionClass =
			ExpectedConditions.visibilityOfElementLocated(byClass);
		final Thread byClassThread = new Thread(
			new GetElement(waitClass, conditionClass, failures, retValue, threads));
		threads.add(byClassThread);

		final By bySelector = GET_BY.getBy(GetBy.CSS_SELECTOR, valueAlias, value, threadDetails);
		final WebDriverWait waitSelector = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionSelector =
			ExpectedConditions.visibilityOfElementLocated(bySelector);
		final Thread bySelectorThread = new Thread(
			new GetElement(waitSelector, conditionSelector, failures, retValue, threads));
		threads.add(bySelectorThread);


		threads.stream().forEach(Thread::start);

		return retValue;
	}

	@Override
	public CompletableFuture getPresenceElementFoundBy(
			final boolean valueAlias,
			final String value,
			final ThreadDetails threadDetails) {
		return getPresenceElementFoundBy(valueAlias, value, threadDetails, Constants.WAIT);
	}

	@Override
	public CompletableFuture getPresenceElementFoundBy(
			final boolean valueAlias,
			final String value,
			final ThreadDetails threadDetails,
			final long wait) {
		final CompletableFuture retValue = new CompletableFuture<>();
		final AtomicInteger failures = new AtomicInteger(0);
		final List threads = new CopyOnWriteArrayList<>();

		final By by = GET_BY.getBy(GetBy.ID, valueAlias, value, threadDetails);
		final WebDriverWait waitId = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionId =
			ExpectedConditions.presenceOfElementLocated(by);
		final Thread byIDThread = new Thread(
			new GetElement(waitId, conditionId, failures, retValue, threads));
		threads.add(byIDThread);

		final By byXpath = GET_BY.getBy(GetBy.XPATH, valueAlias, value, threadDetails);
		final WebDriverWait waitXpath = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionXpath =
			ExpectedConditions.presenceOfElementLocated(byXpath);
		final Thread byXpathThread = new Thread(
			new GetElement(waitXpath, conditionXpath, failures, retValue, threads));
		threads.add(byXpathThread);

		final By byName = GET_BY.getBy(GetBy.NAME, valueAlias, value, threadDetails);
		final WebDriverWait waitName = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionName =
			ExpectedConditions.presenceOfElementLocated(byName);
		final Thread byNameThread = new Thread(
			new GetElement(waitName, conditionName, failures, retValue, threads));
		threads.add(byNameThread);

		final By byValue = GET_BY.getBy(GetBy.VALUE, valueAlias, value, threadDetails);
		final WebDriverWait waitValue = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionValue =
			ExpectedConditions.presenceOfElementLocated(byValue);
		final Thread byValueThread = new Thread(
			new GetElement(waitValue, conditionValue, failures, retValue, threads));
		threads.add(byValueThread);

		final By byText = GET_BY.getBy(GetBy.TEXT, valueAlias, value, threadDetails);
		final WebDriverWait waitText = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionText =
			ExpectedConditions.presenceOfElementLocated(byText);
		final Thread byTextThread = new Thread(
			new GetElement(waitText, conditionText, failures, retValue, threads));
		threads.add(byTextThread);

		final By byClass = GET_BY.getBy(GetBy.CLASS, valueAlias, value, threadDetails);
		final WebDriverWait waitClass = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionClass =
			ExpectedConditions.presenceOfElementLocated(byClass);
		final Thread byClassThread = new Thread(
			new GetElement(waitClass, conditionClass, failures, retValue, threads));
		threads.add(byClassThread);

		final By bySelector = GET_BY.getBy(GetBy.CSS_SELECTOR, valueAlias, value, threadDetails);
		final WebDriverWait waitSelector = new WebDriverWait(threadDetails.getWebDriver(), wait);
		final ExpectedCondition conditionSelector =
			ExpectedConditions.presenceOfElementLocated(bySelector);
		final Thread bySelectorThread = new Thread(
			new GetElement(waitSelector, conditionSelector, failures, retValue, threads));
		threads.add(bySelectorThread);


		threads.stream().forEach(Thread::start);

		return retValue;
	}

	/**
	 * Represents a thread that is running trying to find an element. The first one to succeed
	 * will set the value of a CompletableFuture, while the last one to fail after all others
	 * have failed will set the CompletableFuture to throw an exception.
	 */
	private static class GetElement implements Runnable {
		private final WebDriverWait wait;
		private final AtomicInteger failures;
		private final CompletableFuture returnValue;
		private final List threads;
		private final ExpectedCondition expectedCondition;

		GetElement(
			final WebDriverWait wait,
			final ExpectedCondition expectedCondition,
			final AtomicInteger failures,
			final CompletableFuture returnValue,
			final List threads) {

			checkNotNull(wait);
			checkNotNull(expectedCondition);
			checkNotNull(failures);
			checkNotNull(returnValue);
			checkNotNull(threads);

			this.wait = wait;
			this.expectedCondition = expectedCondition;
			this.failures = failures;
			this.returnValue = returnValue;
			this.threads = new ArrayList<>(threads);
		}

		@Override
		public void run() {
			try {
				final WebElement element = wait.until(expectedCondition);
				/*
					The first thread to succeed will be the value that is returned
				 */
				synchronized (returnValue) {
					if (returnValue.isDone()) {
						LOGGER.error(
							"WEBAPPTESTER-INFO-0005: "
							+ "More than one simple selection method returned an element. "
							+ "You may need to use a step that defines how an element is "
							+ "selected instead of using the simple selection "
							+ "\"found by\" steps.");

					} else {
						/*
							Return the element
						 */
						returnValue.complete(element);

						/*
							All of the other threads no longer need to keep running
						 */
						threads.stream()
							.filter(x -> x != Thread.currentThread())
							.forEach(Thread::interrupt);
					}
				}
			} catch (final Exception ex) {
				/*
					If all threads failed, throw an exception
				 */
				final int failureCount = failures.incrementAndGet();
				if (failureCount >= threads.size()) {
					synchronized (returnValue) {
						if (!returnValue.isDone()) {
							returnValue.completeExceptionally(
								new WebElementException(
									"All attempts to find element failed"));
						}
					}
				}
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy