/* MonkeyTalk - a cross-platform functional testing tool Copyright (C) 2012 Gorilla Logic, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.gorillalogic.fonemonkey.automators; import java.lang.reflect.Field; import java.util.List; import android.view.KeyEvent; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import com.gorillalogic.fonemonkey.Log; import com.gorillalogic.monkeytalk.automators.AutomatorConstants; public class TextViewAutomator extends ViewAutomator { private static String componentType = "Label"; private static Class<?> componentClass = TextView.class; static { Log.log("Initializing TextViewAutomator"); } private static boolean ignoreNext = false; // @Override // public String getMonkeyID() { // String text = getTextView().getText().toString(); // return (text != null && text.trim().length() > 0) ? // text : super.getMonkeyID(); // } @Override public String getComponentType() { // if (getTextView() == null || // !(getTextView().getTransformationMethod() instanceof // SingleLineTransformationMethod)) { // return "TextArea"; // } // if (getTextView().getInputType() == InputType.TYPE_NULL) { // return "Label"; // } // return "Input"; return componentType; } @Override public Class<?> getComponentClass() { return componentClass; } public TextView getTextView() { return (TextView) getComponent(); } @Override public String play(String action, String... args) { if (action.equalsIgnoreCase(AutomatorConstants.ACTION_ENTER_TEXT)) { if (args.length < 1) { throw new IllegalArgumentException("EnterText action requires one argument"); } final String text = args[0]; boolean hitDone = false; if (args.length > 1 && (Boolean.valueOf(args[1]) || args[1].equalsIgnoreCase("enter"))) { hitDone = true; } final boolean hitEnter = hitDone; AutomationManager.runOnUIThread(new Runnable() { public void run() { getTextView().setText(""); tap(); enterText(text, hitEnter); } }); return null; } if (action.equalsIgnoreCase(AutomatorConstants.ACTION_CLEAR)) { AutomationManager.runOnUIThread(new Runnable() { public void run() { getTextView().setText(""); } }); return null; } return super.play(action, args); } /* * (non-Javadoc) * * @see com.gorillalogic.fonemonkey.automators.AutomatorBase#record(java.lang .String, * java.lang.String[]) */ @Override public void record(String action, String... args) { if (action.equalsIgnoreCase("ignoreNext")) { ignoreNext = true; return; } if (ignoreNext) { ignoreNext = false; return; } super.record(action, args); } // public String[] getAliases() { // return new String[] {"Label"}; // } public String getValue() { return getTextView().getText().toString(); } // @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { AutomationManager .record(AutomatorConstants.ACTION_ENTER_TEXT, (String) v.getText(), "true"); return false; } @Override public boolean installDefaultListeners() { OnEditorActionListener listener = null; Field inputContentTypeField; Object target = getTextView(); Class<?> targetClass = TextView.class; try { try { // mInputContentType moved to inner class in Android 4.1 (JellyBean) Field editorField = TextView.class.getDeclaredField("mEditor"); editorField.setAccessible(true); Object editor = editorField.get(getTextView()); if (editor != null) { targetClass = editor.getClass(); target = editor; } else { target = null; } } catch (NoSuchFieldException e) { // Pre-4.1 JellyBean } if (target != null) { inputContentTypeField = targetClass.getDeclaredField("mInputContentType"); inputContentTypeField.setAccessible(true); Object inputContentType = inputContentTypeField.get(target); if (inputContentType != null) { Field editorActionListenerField = inputContentType.getClass().getDeclaredField( "onEditorActionListener"); editorActionListenerField.setAccessible(true); listener = (OnEditorActionListener) editorActionListenerField .get(inputContentType); } } } catch (Exception e) { throw new IllegalStateException("Error chaining onEditorActionListener", e); } final OnEditorActionListener origListener = listener; getTextView().setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { AutomationManager.record(AutomatorConstants.ACTION_ENTER_TEXT, getView(), v .getText().toString(), "enter"); if (origListener == null) { return false; } return origListener.onEditorAction(v, actionId, event); } }); return super.installDefaultListeners(); } @Override public List<String> getIdentifyingValues() { List<String> list = super.getIdentifyingValues(); CharSequence text = getTextView().getText(); if (text != null) { list.add(text.toString()); } return list; } }