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

com.qmetry.qaf.automation.ui.util.DynamicWait Maven / Gradle / Ivy

Go to download

Functional test automation framework for web, mobile-web, mobile native and web-service

There is a newer version: 4.0.0-RC3
Show newest version
/*******************************************************************************
 * Copyright (c) 2019 Infostretch Corporation
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 ******************************************************************************/
package com.qmetry.qaf.automation.ui.util;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.qmetry.qaf.automation.core.ConfigurationManager.getBundle;
import static com.qmetry.qaf.automation.core.QAFTestBase.pause;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.TimeoutException;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.qmetry.qaf.automation.keys.ApplicationProperties;

/**
 * @author chirag.jayswal
 *
 */
public class DynamicWait{ //implements Wait {
	private T input;
	private long timeout = getDefaultTimeout();
	private long interval = getDefaultTimeout();
	private Supplier messageSupplier = new StringSupplier(null);
	private List> ignoredExceptions = Lists.newLinkedList();

	public DynamicWait(T input) {
		this.input = checkNotNull(input);
	}

	/**
	 * Sets the message to be displayed when time expires.
	 *
	 * @param message
	 *            to be appended to default.
	 * @return A self reference.
	 */
	public DynamicWait withMessage(final String message) {
		this.messageSupplier = new StringSupplier(message);
		return this;
	}

	/**
	 * Sets the message to be evaluated and displayed when time expires.
	 *
	 * @param messageSupplier
	 *            to be evaluated on failure and appended to default.
	 * @return A self reference.
	 */
	public DynamicWait withMessage(Supplier messageSupplier) {
		this.messageSupplier = messageSupplier;
		return this;
	}

	/**
	 * Sets how often the condition should be evaluated.
	 *
	 * 

* In reality, the interval may be greater as the cost of actually * evaluating a condition function is not factored in. The default polling * interval is {@link #FIVE_HUNDRED_MILLIS}. * * @param duration * The timeout duration. * @param unit * The unit of time. * @return A self reference. */ public DynamicWait pollingEvery(long duration, TimeUnit unit) { this.interval = duration(duration, unit); return this; } /** * Repeatedly applies this instance's input value to the given predicate * until the timeout expires or the predicate evaluates to true. * * @param isTrue * The predicate to wait on. * @throws TimeoutException * If the timeout expires. */ public void until(final Predicate isTrue) { until(new Function() { public Boolean apply(T input) { return isTrue.apply(input); } public String toString() { return isTrue.toString(); } }); } /** * Repeatedly applies this instance's input value to the given function * until one of the following occurs: *

    *
  1. the function returns neither null nor false,
  2. *
  3. the function throws an unignored exception,
  4. *
  5. the timeout expires, *
  6. *
  7. the current thread is interrupted
  8. *
* * @param isTrue * the parameter to pass to the {@link ExpectedCondition} * @param * The function's expected return type. * @return The functions' return value if the function returned something * different from null or false before the timeout expired. * @throws TimeoutException * If the timeout expires. */ public V until(Function isTrue) { long end = laterBy(timeout); Throwable lastException = null; while (true) { try { V value = isTrue.apply(input); if (value != null && Boolean.class.equals(value.getClass())) { if (Boolean.TRUE.equals(value)) { return value; } } else if (value != null) { return value; } } catch (Throwable e) { lastException = propagateIfNotIgnored(e); } // Check the timeout after evaluating the function to ensure // conditions // with a zero timeout can succeed. if (!isNowBefore(end)) { String message = messageSupplier != null ? messageSupplier.get() : null; String toAppend = message == null ? " waiting for " + isTrue.toString() : ": " + message; String timeoutMessage = String.format("Timed out after %d seconds%s", SECONDS.convert(timeout,MILLISECONDS), toAppend); throw new TimeoutException(timeoutMessage, lastException); } pause(interval); } } /** * Sets how long to wait for the evaluated condition to be true. The default * timeout is {@link #FIVE_HUNDRED_MILLIS}. * * @param duration * The timeout duration. * @param unit * The unit of time. * @return A self reference. */ public DynamicWait withTimeout(long duration, TimeUnit unit) { this.timeout = duration(duration, unit); return this; } private Throwable propagateIfNotIgnored(Throwable e) { for (Class ignoredException : ignoredExceptions) { if (ignoredException.isInstance(e)) { return e; } } throw Throwables.propagate(e); } /** * Configures this instance to ignore specific types of exceptions while * waiting for a condition. Any exceptions not whitelisted will be allowed * to propagate, terminating the wait. * * @param types * The types of exceptions to ignore. * @param * an Exception that extends Throwable * @return A self reference. */ @SafeVarargs public final DynamicWait ignoring( Class... types) { ignoredExceptions.addAll(Arrays.asList(types)); return this; } private static class StringSupplier implements Supplier { String message; public StringSupplier(String message) { this.message = message; } @Override public String get() { return message; } } public static long getDefaultTimeout() { return getBundle().getLong("selenium.explicit.wait.timeout", ApplicationProperties.SELENIUM_WAIT_TIMEOUT.getIntVal(5000)); } public static long getDefaultInterval() { return getBundle().getLong("selenium.explicit.wait.interval", getBundle().getLong("selenium.wait.interval", 1000)); } private long laterBy(long durationInMillis) { return now() + durationInMillis; } private boolean isNowBefore(long endInMillis) { return now() < endInMillis; } private long now() { return System.currentTimeMillis(); } public static long duration(long time, TimeUnit unit){ return unit.convert(time, MILLISECONDS); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy