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

com.jayway.android.robotium.solo.Searcher Maven / Gradle / Ivy

There is a newer version: 5.6.3
Show newest version
package com.jayway.android.robotium.solo;

import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.Instrumentation;
import android.util.Log;
import android.widget.TextView;

/**
 * This class contains various search methods. Examples are: searchForEditTextWithTimeout(),
 * searchForTextWithTimeout(), searchForButtonWithTimeout().
 * 
 * @author Renas Reda, [email protected]
 * 
 */

class Searcher {

	private final ViewFetcher viewFetcher;
	private final Scroller scroller;
	private final Instrumentation inst;
	private final Sleeper sleeper;
	private final MatchCounter matchCounter;
	private final int TIMEOUT = 5000;
	private final String LOG_TAG = "Robotium";

	/**
	 * Constructs this object.
	 *
	 * @param viewFetcher the {@code ViewFetcher} instance.
	 * @param scroller the {@code Scroller} instance.
	 * @param inst the {@code Instrumentation} instance.
	 * @param sleeper the {@code Sleeper} instance.
	 */

	public Searcher(ViewFetcher viewFetcher, Scroller scroller, Instrumentation inst, Sleeper sleeper) {
		this.viewFetcher = viewFetcher;
		this.scroller = scroller;
		this.inst = inst;
		this.sleeper = sleeper;
		matchCounter = new MatchCounter();
	}


	/**
	 * Searches for a {@code View} with the given regex string and returns {@code true} if the
	 * searched {@code Button} is found a given number of times. Will automatically scroll when needed.
	 *
	 * @param viewClass what kind of {@code View} to search for, e.g. {@code Button.class} or {@code TextView.class}
	 * @param regex the text to search for. The parameter will be interpreted as a regular expression.
	 * @param expectedMinimumNumberOfMatches the minimum number of matches expected to be found. {@code 0} matches means that one or more
	 * matches are expected to be found
	 * @param scroll whether scrolling should be performed
	 * @param onlyVisible {@code true} if only texts visible on the screen should be searched
	 * @return {@code true} if a {@code View} of the specified class with the given text is found a given number of
	 * times, and {@code false} if it is not found
	 *
	 */

	public boolean searchWithTimeoutFor(Class viewClass, String regex, int expectedMinimumNumberOfMatches, boolean scroll, boolean onlyVisible) {
		final long endTime = System.currentTimeMillis() + TIMEOUT;

		while (System.currentTimeMillis() < endTime) {
			sleeper.sleep();
			final boolean foundAnyMatchingView = searchFor(viewClass, regex, expectedMinimumNumberOfMatches, scroll, onlyVisible);
			if (foundAnyMatchingView){
				return true;
			}
		}

		return false;
	}


	/**
	 * Searches for a {@code View} with the given regex string and returns {@code true} if the
	 * searched {@code View} is found a given number of times
	 *
	 * @param viewClass what kind of {@code View} to search for, e.g. {@code Button.class} or {@code TextView.class}
	 * @param regex the text to search for. The parameter will be interpreted as a regular expression.
	 * @param expectedMinimumNumberOfMatches the minimum number of matches expected to be found. {@code 0} matches means that one or more
	 * matches are expected to be found.
	 * @param scroll whether scrolling should be performed
	 * @param onlyVisible {@code true} if only texts visible on the screen should be searched
	 * @return {@code true} if a view of the specified class with the given text is found a given number of times.
	 * {@code false} if it is not found.
	 *
	 */

	public  boolean searchFor(final Class viewClass, final String regex, final int expectedMinimumNumberOfMatches, final boolean scroll, final boolean onlyVisible) {
		final Callable> viewFetcherCallback = new Callable>() {
			public Collection call() throws Exception {
				sleeper.sleep();
				inst.waitForIdleSync();

				if(onlyVisible)
					return RobotiumUtils.removeInvisibleViews(viewFetcher.getCurrentViews(viewClass));

					return viewFetcher.getCurrentViews(viewClass);
			}
		};
		try {
			return searchFor(viewFetcherCallback, regex, expectedMinimumNumberOfMatches, scroll);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}


	/**
	 * Searches for a {@code View} with the given regex string and returns {@code true} if the
	 * searched {@code View} is found a given number of times. Will not scroll, because the caller needs to find new
	 * {@code View}s to evaluate after scrolling, and call this method again.
	 *
	 * @param viewFetcherCallback callback which should return an updated collection of views to search
	 * @param regex the text to search for. The parameter will be interpreted as a regular expression.
	 * @param expectedMinimumNumberOfMatches the minimum number of matches expected to be found. {@code 0} matches means that one or more
	 * matches are expected to be found.
	 * @param scroll whether scrolling should be performed
	 * @return {@code true} if a view of the specified class with the given text is found a given number of times.
	 * {@code false} if it is not found.
	 *
	 * @throws Exception not really, it's just the signature of {@code Callable}
	 */

	public  boolean searchFor(Callable> viewFetcherCallback, String regex, int expectedMinimumNumberOfMatches, boolean scroll) throws Exception {
		if(expectedMinimumNumberOfMatches < 1) {
			expectedMinimumNumberOfMatches = 1;
		}
		final Pattern pattern = Pattern.compile(regex);
		Collection views;
		while (true) {	
			views = viewFetcherCallback.call();
			for(TextView view : views){
				final Matcher matcher = pattern.matcher(view.getText().toString());
				
				if (matcher.find()){
					matchCounter.addMatchToCount();
				}
				if (matchCounter.getTotalCount() == expectedMinimumNumberOfMatches) {
					matchCounter.resetCount();
					return true;
				}
			}
			if(scroll && !scroller.scroll(Scroller.DOWN)){
				logMatchesFound(regex);
				return false;
			}
			if(!scroll){
				logMatchesFound(regex);
				return false;
			}
			sleeper.sleep();
		}
	}
	
	/**
	 * Logs a (searchFor failed) message 
	 * @param regex the search string to log
	 * 
	 */
	
	private void logMatchesFound(String regex){
		if (matchCounter.getTotalCount() > 0) {
			Log.d(LOG_TAG, " There are only " + matchCounter.getTotalCount() + " matches of " + regex);
		}
		matchCounter.resetCount();
	}


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy