/* This file is part of SlumDroid <https://github.com/slumdroid/slumdroid>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License <http://www.gnu.org/licenses/gpl-3.0.txt>
* for more details.
*
* Copyright (C) 2012-2016 Gennaro Imparato
*/
package it.slumdroid.tool.components.automation;
import static it.slumdroid.droidmodels.model.InteractionType.CHANGE_ORIENTATION;
import static it.slumdroid.droidmodels.model.InteractionType.CLICK;
import static it.slumdroid.droidmodels.model.InteractionType.ENTER_TEXT;
import static it.slumdroid.droidmodels.model.InteractionType.LIST_LONG_SELECT;
import static it.slumdroid.droidmodels.model.InteractionType.LIST_SELECT;
import static it.slumdroid.droidmodels.model.InteractionType.LONG_CLICK;
import static it.slumdroid.droidmodels.model.InteractionType.PRESS_ACTION;
import static it.slumdroid.droidmodels.model.InteractionType.PRESS_BACK;
import static it.slumdroid.droidmodels.model.InteractionType.PRESS_MENU;
import static it.slumdroid.droidmodels.model.InteractionType.RADIO_SELECT;
import static it.slumdroid.droidmodels.model.InteractionType.SET_BAR;
import static it.slumdroid.droidmodels.model.InteractionType.SPINNER_SELECT;
import static it.slumdroid.droidmodels.model.InteractionType.SWAP_TAB;
import static it.slumdroid.droidmodels.model.InteractionType.SWIPE_TAB;
import static it.slumdroid.droidmodels.model.InteractionType.WRITE_TEXT;
import static it.slumdroid.droidmodels.model.SimpleType.MENU_ITEM;
import static it.slumdroid.tool.Resources.SLEEP_AFTER_EVENT;
import static it.slumdroid.tool.Resources.SLEEP_AFTER_RESTART;
import static it.slumdroid.tool.Resources.SLEEP_ON_THROBBER;
import static it.slumdroid.tool.Resources.TAG;
import java.util.ArrayList;
import com.robotium.solo.Solo;
import android.app.Activity;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
import android.view.View;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TabHost;
import it.slumdroid.droidmodels.model.Task;
import it.slumdroid.droidmodels.model.Transition;
import it.slumdroid.droidmodels.model.UserEvent;
import it.slumdroid.droidmodels.model.UserInput;
// TODO: Auto-generated Javadoc
/**
* The Class Automation.
*/
public class Automation {
/** The extractor. */
private static Extractor extractor;
/** The executor. */
private static Executor executor;
/**
* Instantiates a new automation.
*/
public Automation() {
extractor = new Extractor();
}
/**
* Bind.
*
* @param test the test
*/
public void bind(ActivityInstrumentationTestCase2<?> test) {
executor = new Executor(test);
getRobotium().unlockScreen();
afterRestart();
}
/**
* Execute.
*
* @param theTask the the task
*/
public void execute(Task theTask) {
Log.i (TAG, "Playing Task " + theTask.getId());
for (Transition transition: theTask) {
process(transition);
}
}
/**
* Process.
*
* @param theTransition the transition
*/
private void process(Transition theTransition) {
for (UserInput input: theTransition) {
setInput(input);
}
fireEvent (theTransition.getEvent());
}
/**
* Sets the input.
*
* @param input the new input
*/
public void setInput(UserInput input) {
String toWrite = "Setting input: " + input.getType() + " widgetId=" + input.getWidgetId() + " widgetType=" + input.getWidget().getSimpleType();
if (!input.getValue().equals("")) {
toWrite += " value=" + input.getValue();
}
Log.i(TAG, toWrite);
View view = getExtractor().getAllViews().get(input.getWidget().getIndex());
injectInputInteractions(view, input.getType(), input.getValue());
}
/**
* Inject input interactions.
*
* @param view the view
* @param interactionType the interaction type
* @param value the value
*/
private void injectInputInteractions(View view, String interactionType, String value) {
if (interactionType.equals(CLICK)) {
getExecutor().click(view);
return;
}
if (interactionType.equals(WRITE_TEXT)) {
if (view instanceof AutoCompleteTextView) {
getExecutor().typeText((EditText)view, value);
return;
} else {
getExecutor().writeText((EditText)view, value);
return;
}
}
if (interactionType.equals(SPINNER_SELECT)) {
getExecutor().selectSpinnerItem((Spinner)view, value);
return;
}
if (interactionType.equals(SET_BAR)) {
getExecutor().setProgressBar((ProgressBar)view, value);
return;
}
}
/**
* Fire event.
*
* @param event the event
*/
public void fireEvent(UserEvent event) {
String eventType = event.getType();
if (eventType.contains("press") || eventType.equals(CHANGE_ORIENTATION)) {
injectSpecialInteractions(eventType);
} else {
String toWrite = "Firing event: " + eventType + " widgetId=" + event.getWidgetId() + " widgetType=" + event.getWidget().getSimpleType();
if (!event.getValue().equals("")) {
toWrite += " value=" + event.getValue();
}
if (event.getWidget().getSimpleType().equals(MENU_ITEM)) {
if (!event.getWidgetName().equals("")) {
toWrite += " item=" + event.getWidgetName();
}
}
Log.i(TAG, toWrite);
if (event.getWidgetType().equals("com.android.internal.view.menu.IconMenuItemView")
&& !event.getWidgetName().equals("")) {
getRobotium().clickOnMenuItem(event.getWidgetName());
} else {
View view = getExtractor().getAllViews().get(event.getWidget().getIndex());
injectEventInteractions(view, eventType, event.getValue());
}
}
afterEvent();
}
/**
* Inject special interactions.
*
* @param interactionType the interaction type
*/
private void injectSpecialInteractions(String interactionType) {
Log.i(TAG, "Firing event: " + interactionType);
if (interactionType.contains("press")) {
if (interactionType.equals(PRESS_BACK)) {
getRobotium().goBack();
return;
}
if (interactionType.equals(PRESS_MENU)) {
getRobotium().sendKey(Solo.MENU);
return;
}
if (interactionType.equals(PRESS_ACTION)) {
getRobotium().clickOnActionBarHomeButton();
return;
}
}
if (interactionType.equals(CHANGE_ORIENTATION)) {
getExecutor().changeOrientation();
return;
}
}
/**
* Inject interaction.
*
* @param view the view
* @param interactionType the interaction type
* @param value the value
*/
private void injectEventInteractions(View view, String interactionType, String value) {
if (interactionType.endsWith("Item")) {
if (interactionType.equals(LIST_SELECT)) {
getExecutor().selectListItem((ListView)view, value);
return;
}
if (interactionType.equals(LIST_LONG_SELECT)) {
getExecutor().selectLongListItem((ListView)view, value);
return;
}
if (interactionType.equals(SPINNER_SELECT)) {
getExecutor().selectSpinnerItem((Spinner)view, value);
return;
}
if (interactionType.equals(RADIO_SELECT)) {
getExecutor().selectRadioItem((RadioGroup)view, value);
return;
}
}
if (interactionType.endsWith("Text")) {
if (interactionType.equals(WRITE_TEXT)) {
getExecutor().typeText((EditText)view, value);
return;
}
if (interactionType.equals(ENTER_TEXT)) {
getExecutor().writeTextAndEnter((EditText)view, value);
return;
}
}
if (interactionType.equals(CLICK)) {
getExecutor().click(view);
return;
}
if (interactionType.equals(LONG_CLICK)) {
getExecutor().longClick(view);
return;
}
if (interactionType.equals(SWAP_TAB)) {
getExecutor().swapTab((TabHost)view, value);
return;
}
if (interactionType.equals(SWIPE_TAB)) {
getExecutor().swipeTab(view, value);
return;
}
}
/**
* Wait.
*
* @param milli the milli
*/
public void wait(int milli) {
getExecutor().wait(milli);
}
/**
* After restart.
*/
private void afterRestart() {
if (SLEEP_AFTER_RESTART != 0) {
wait(SLEEP_AFTER_RESTART);
}
if (SLEEP_ON_THROBBER != 0) {
waitOnThrobber();
}
}
/**
* After event.
*/
private void afterEvent() {
if (SLEEP_AFTER_EVENT != 0) {
wait(SLEEP_AFTER_EVENT);
}
if (SLEEP_ON_THROBBER != 0) {
waitOnThrobber();
}
getExtractor().extractState();
}
/**
* Wait on throbber.
*/
private void waitOnThrobber() {
int sleepTime = SLEEP_ON_THROBBER;
boolean flag;
do {
flag = false;
ArrayList<ProgressBar> bars = getRobotium().getCurrentViews(ProgressBar.class);
for (ProgressBar bar: bars) {
if (bar.isShown() && bar.isIndeterminate()) {
flag = true;
wait(50);
sleepTime-=50;
}
}
} while (flag && (sleepTime > 0));
getExecutor().sync();
}
/**
* Gets the extractor.
*
* @return the extractor
*/
public static Extractor getExtractor() {
return extractor;
}
/**
* Gets the executor.
*
* @return the executor
*/
public static Executor getExecutor() {
return executor;
}
/**
* Gets the robotium.
*
* @return the robotium
*/
public static Solo getRobotium() {
return getExecutor().getRobotium();
}
/**
* Gets the current activity.
*
* @return the current activity
*/
public static Activity getCurrentActivity() {
return getExecutor().getCurrentActivity();
}
}