package com.google.android.apps.mytracks.endtoendtest;
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
import com.google.android.apps.mytracks.TrackListActivity;
import com.google.android.maps.mytracks.R;
import com.robotium.solo.Solo;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.Configuration;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import junit.framework.Assert;
/**
* Provides utilities to smoke test.
*
* @author Youtao Liu
*/
public class EndToEndTestUtils {
public static final int TINY_WAIT_TIME = 200;
public static final int VERY_SHORT_WAIT_TIME = 500;
public static final int SHORT_WAIT_TIME = 2000;
public static final int NORMAL_WAIT_TIME = 8000;
public static final int LONG_WAIT_TIME = 15000;
public static final int SUPER_LONG_WAIT_TIME = 100000;
// Pause 200ms between each send.
public static final double START_LONGITUDE = 51;
public static final double START_LATITUDE = -1.3f;
public static final double DELTA_LONGITUDE = 0.0005f;
public static final double DELTA_LADITUDE = 0.0005f;
public static final String WAYPOINT_NAME = "testWaypoint";
public static final String WAYPOINT_TYPE = "testWaypoinType";
public static final String WAYPOINT_DESCRIPTION = "testWaypointDesc";
public static final String DEFAULT_ACTIVITY_TYPE = "TestActivity";
public static final String TRACK_NAME_PREFIX = "testTrackName";
private static final String TAG = EndToEndTestUtils.class.getSimpleName();
private static final String TRACK_DESCRIPTION_PREFIX = "testTrackDesc";
private static final int ORIENTATION_PORTRAIT = 1;
private static final int ORIENTATION_LANDSCAPE = 0;
private static final String ANDROID_LOCAL_IP = "10.0.2.2";
private static final String NO_GPS_MESSAGE_PREFIX = "GPS is not available";
private static final String MORE_OPTION_CLASSNAME = "com.android.internal.view.menu.ActionMenuPresenter$OverflowMenuButton";
private static final String MENUITEM_CLASSNAME = "com.android.internal.view.menu.IconMenuItemView";
// Following is some check strings in English and Chinese
private static final HashMap<String, String>
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL = new HashMap<String, String>();
static {
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("en", "mins ago");
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("de", "Minuten");
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("fr", "minute");
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("ar", "دقيقة");
RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.put("zh", "分钟前");
}
public static int emulatorPort = 5554; // usually 5554.
public static String activityType = DEFAULT_ACTIVITY_TYPE;
public static String trackName;
public static String trackDescription;
public static com.robotium.solo.Solo SOLO;
public static Instrumentation instrumentation;
public static TrackListActivity trackListActivity;
/*
* Check whether the UI has an action bar which is related with the version of
* Android OS.
*/
public static boolean hasActionBar = false;
public static boolean isEmulator = true;
public static boolean hasGpsSignal = true;
private static boolean isCheckedFirstLaunch = false;
private static boolean isGooglePlayServicesLatest = true;
private static String language;
private EndToEndTestUtils() {};
/**
* Checks the language, then sets the fields with right string.
*/
private static void checkLanguage() {
Locale locale = new Locale("en");
Locale.setDefault(locale);
Configuration configuration = trackListActivity.getBaseContext()
.getResources().getConfiguration();
configuration.locale = locale;
language = instrumentation.getContext().getResources().getConfiguration().locale.getLanguage();
}
/**
* Sends Gps data to emulator, and the start value has an offset.
*
* @param number send times
* @param offset is used to compute the start latitude and longitude
* @param pause pause interval between each sending
*/
public static void sendGps(int number, int offset, int pause) {
if (number < 1) {
return;
}
int pauseInterval = TINY_WAIT_TIME;
if (pause != -1) {
pauseInterval = pause;
}
// If it's a real device, does not send simulated GPS signal.
if (!isEmulator) {
return;
}
PrintStream out = null;
Socket socket = null;
try {
socket = new Socket(ANDROID_LOCAL_IP, emulatorPort);
out = new PrintStream(socket.getOutputStream());
double longitude = START_LONGITUDE + offset * DELTA_LONGITUDE;
double latitude = START_LATITUDE + offset * DELTA_LADITUDE;
for (int i = 0; i < number; i++) {
out.println("geo fix " + longitude + " " + latitude);
longitude += DELTA_LONGITUDE;
latitude += DELTA_LADITUDE;
Thread.sleep(pauseInterval);
}
// Wait the GPS signal can be obtained by MyTracks.
Thread.sleep(SHORT_WAIT_TIME);
} catch (UnknownHostException e) {
System.exit(-1);
} catch (IOException e) {
System.exit(-1);
} catch (InterruptedException e) {
System.exit(-1);
} finally {
if (out != null) {
out.close();
}
}
}
/**
* Send Gps data to emulator.
*
* @param number number of signals
* @param offset is used to compute the start latitude and longitude
*/
public static void sendGps(int number, int offset) {
sendGps(number, offset, -1);
}
/**
* Send Gps data to emulator.
*
* @param number number of signals
*/
public static void sendGps(int number) {
sendGps(number, 0, -1);
}
/**
* Sets the status whether the test is run on an emulator or not.
*/
private static void setIsEmulator() {
isEmulator = android.os.Build.MODEL.equals("google_sdk");
}
/**
* Checks whether the Google Play Services need update.
*/
private static boolean isGooglePlayServicesLatest() {
return findTextView("Google Play services") == null;
}
/**
* A setup for debugging end-to-end tests.
*
* @param inst the instrumentation
* @param activity the track list activity
*/
public static void setupForDebug(Instrumentation inst, TrackListActivity activity) {
instrumentation = inst;
trackListActivity = activity;
SOLO = new Solo(instrumentation, trackListActivity);
setIsEmulator();
hasActionBar = setHasActionBar();
checkLanguage();
}
/**
* A setup for all end-to-end tests.
*
* @param inst the instrumentation
* @param activity the track list activity
*/
public static void setupForAllTest(Instrumentation inst, TrackListActivity activity) {
instrumentation = inst;
trackListActivity = activity;
SOLO = new Solo(instrumentation, trackListActivity);
if (!isGooglePlayServicesLatest) {
SOLO.finishOpenedActivities();
Assert.fail();
Log.e(TAG, "Need update Google Play Services");
}
// Check if open MyTracks first time after install. If so, there would be a
// welcome view with accept buttons. And makes sure only check once.
if (!isCheckedFirstLaunch) {
isGooglePlayServicesLatest = isGooglePlayServicesLatest();
if (!isGooglePlayServicesLatest) {
SOLO.finishOpenedActivities();
Assert.fail();
Log.e(TAG, "Need update Google Play Services");
}
setIsEmulator();
verifyFirstLaunch();
hasActionBar = setHasActionBar();
checkLanguage();
isCheckedFirstLaunch = true;
inst.waitForIdleSync();
// Check the status of real phone. For emulator, we would fix GPS signal.
if (!isEmulator) {
findAndClickMyLocation(activity);
hasGpsSignal = !SOLO.waitForText(NO_GPS_MESSAGE_PREFIX, 1, SHORT_WAIT_TIME);
SOLO.goBack();
}
}
int trackNumber = SOLO.getCurrentViews(ListView.class).get(0).getCount();
// Delete all tracks when there are two many tracks which may make some test
// run slowly, such as sync test cases.
if (trackNumber > 3) {
deleteAllTracks();
}
// Check whether is under recording. If previous test failed, the recording
// may not be recording.
if (isUnderRecording()) {
stopRecording(true);
}
resetAllSettings(activity, false);
inst.waitForIdleSync();
}
/**
* Rotates the given activity.
*
* @param activity a given activity
*/
private static void rotateActivity(Activity activity) {
activity
.setRequestedOrientation(activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ? ORIENTATION_LANDSCAPE
: ORIENTATION_PORTRAIT);
}
/**
* Accepts terms and configures units.
*/
private static void verifyFirstLaunch() {
if ((getButtonOnScreen(trackListActivity.getString(R.string.eula_accept), false, false) != null)) {
getButtonOnScreen(trackListActivity.getString(R.string.eula_accept), true, true);
}
}
/**
* Creates a simple track which can be used by subsequent test. This method
* will save a customized track name.
*
* @param numberOfGpsData number of simulated Gps data
* @param showTrackList whether stay on track list activity or track detail
* activity
*/
public static void createSimpleTrack(int numberOfGpsData, boolean showTrackList) {
startRecording();
sendGps(numberOfGpsData);
instrumentation.waitForIdleSync();
stopRecording(true);
if (showTrackList) {
SOLO.goBack();
instrumentation.waitForIdleSync();
}
}
/**
* Creates a track which contains pause during recording.
*
* @param numberOfGpsData number of simulated Gps data before pause and after
* resume
*/
public static void createTrackWithPause(int numberOfGpsData) {
startRecording();
sendGps(numberOfGpsData);
pauseRecording();
resumeRecording();
sendGps(numberOfGpsData, numberOfGpsData);
stopRecording(true);
}
/**
* Checks if there is no track in track list. For some tests need at least one
* track, the method can save time to create a new track.
*
* @param isClick if not empty, true means click any track
* @return return true if the track list is empty
*/
private static boolean isTrackListEmpty(boolean isClick) {
instrumentation.waitForIdleSync();
int trackNumber = SOLO.getCurrentViews(ListView.class).get(0).getCount();
if (trackNumber <= 0) {
return true;
}
View oneTrack = SOLO.getCurrentViews(ListView.class).get(0).getChildAt(0);
View aa = oneTrack.findViewById(R.id.list_item_name);
if (aa != null) {
trackName = (String) ((TextView) oneTrack.findViewById(R.id.list_item_name)).getText();
}
if (isClick) {
SOLO.scrollUp();
SOLO.clickOnView(oneTrack);
SOLO.waitForText(trackListActivity.getString(R.string.track_detail_chart_tab));
}
return false;
}
/**
* Create a new track if the track is empty.
*
* @param gpsNumber the number of gps signals
* @param showTrackList whether stay on track list activity or track detail
* activity
*/
public static void createTrackIfEmpty(int gpsNumber, boolean showTrackList) {
if (isTrackListEmpty(!showTrackList)) {
// Create a simple track.
createSimpleTrack(gpsNumber, showTrackList);
}
}
/**
* Starts recoding track.
*/
public static void startRecording() {
View startButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_record);
if (startButton != null && startButton.isShown()) {
SOLO.clickOnView(startButton);
}
instrumentation.waitForIdleSync();
}
/**
* Pauses recoding track.
*/
public static void pauseRecording() {
View pauseButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_record);
if (pauseButton != null && pauseButton.isShown()) {
SOLO.clickOnView(pauseButton);
}
instrumentation.waitForIdleSync();
}
/**
* Resume recoding track.
*/
public static void resumeRecording() {
View startButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_record);
if (startButton != null && startButton.isShown()) {
SOLO.clickOnView(startButton);
}
instrumentation.waitForIdleSync();
}
/**
* Checks if the MyTracks is under recording.
*
* @return true if it is under recording.
*/
private static boolean isUnderRecording() {
instrumentation.waitForIdleSync();
View view = SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop);
// TODO: understand why view can be null here
return view != null ? view.isEnabled() : false;
}
/**
* Stops recoding track.
*
* @param isSave true means should save this track
*/
public static void stopRecording(boolean isSave) {
View stopButton = SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop);
if (stopButton != null && stopButton.isShown()) {
SOLO.clickOnView(stopButton);
if (isSave) {
SOLO.waitForText(trackListActivity.getString(R.string.generic_save), 1, 5000);
// Make every track name is unique to make sure every check can be
// trusted.
long currentMillis = System.currentTimeMillis();
trackName = TRACK_NAME_PREFIX + currentMillis;
trackDescription = TRACK_DESCRIPTION_PREFIX + currentMillis;
SOLO.sendKey(KeyEvent.KEYCODE_DEL);
enterTextAvoidSoftKeyBoard(0, trackName);
enterTextAvoidSoftKeyBoard(1, activityType);
enterTextAvoidSoftKeyBoard(2, trackDescription);
SOLO.clickOnText(trackListActivity.getString(R.string.generic_save));
instrumentation.waitForIdleSync();
} else {
instrumentation.waitForIdleSync();
}
}
}
/**
* Deletes all tracks. This method should be call when the TracksListActivity
* is shown.
*/
public static void deleteAllTracks() {
if (!isTrackListEmpty(false)) {
findMenuItem(trackListActivity.getString(R.string.menu_delete_all), true);
getButtonOnScreen(trackListActivity.getString(R.string.generic_yes), true, true);
waitTextToDisappear(trackListActivity.getString(R.string.generic_progress_title));
}
}
/**
* Checks if a button is existed in the screen.
*
* @param buttonName the name string of the button
* @param isWait whether wait the text
* @param isClick whether click the button if find it
* @return the button to search, and null means can not find the button
*/
public static View getButtonOnScreen(String buttonName, boolean isWait, boolean isClick) {
View button = null;
instrumentation.waitForIdleSync();
if (isWait) {
SOLO.waitForText(buttonName);
}
// Find on action bar.
if (hasActionBar) {
ArrayList<View> allViews = SOLO.getViews();
for (View view : allViews) {
String className = view.getClass().getName();
if (className.indexOf("ActionMenuItemView") > 0) {
String menuItemNameString = view.getContentDescription().toString();
if (menuItemNameString.equalsIgnoreCase(buttonName)) {
button = view;
break;
}
}
}
}
// Get all buttons and find.
if (button == null) {
ArrayList<Button> currentButtons = SOLO.getCurrentViews(Button.class);
for (Button oneButton : currentButtons) {
String title = (String) oneButton.getText();
if (title.equalsIgnoreCase(buttonName)) {
button = oneButton;
}
}
}
if (button != null && isClick) {
SOLO.clickOnView(button);
}
if (button == null && isClick) {
Log.d(TAG, "Don't find the button " + buttonName);
}
return button;
}
/**
* Checks whether an action bar is shown.
*
* @return false means can not check failed.
*/
@SuppressLint("NewApi")
private static boolean setHasActionBar() {
try {
return trackListActivity.getActionBar() == null ? false : true;
} catch (Throwable e) {
// For in Android which does not has action bar, here will meet a error.
return false;
}
}
/**
* Rotates all activities.
*/
public static void rotateCurrentActivity() {
rotateActivity(SOLO.getCurrentActivity());
instrumentation.waitForIdleSync();
}
/**
* Finds an item in the menu with the option to click the item.
*
* @param menuName the name of item
* @param click true means need click this menu
* @return true if find this menu
*/
public static boolean findMenuItem(String menuName, boolean click) {
instrumentation.waitForIdleSync();
boolean findResult = false;
boolean isMoreMenuOpened = false;
// ICS phone.
if (hasActionBar) {
// Firstly find in action bar.
View button = getButtonOnScreen(menuName, false, false);
if (button != null) {
findResult = true;
if (click) {
SOLO.clickOnView(button);
instrumentation.waitForIdleSync();
}
return findResult;
}
showMenuItem();
findResult = SOLO.waitForText(menuName, 1, LONG_WAIT_TIME, true);
} else {
// Non-ICS phone.
SOLO.sendKey(KeyEvent.KEYCODE_MENU);
if (SOLO.searchText(menuName, 1, true)) {
findResult = true;
} else if (getMoreOptionView() != null) {
SOLO.clickOnView(getMoreOptionView());
findResult = SOLO.searchText(menuName, 1, true);
isMoreMenuOpened = true;
}
}
if (findResult && click) {
SOLO.clickOnView(SOLO.getText(menuName));
instrumentation.waitForIdleSync();
} else {
// Quit more menu list if opened.
if (isMoreMenuOpened) {
SOLO.goBack();
}
// Quit menu list.
SOLO.goBack();
}
return findResult;
}
/**
* Show menu item list.
*/
private static void showMenuItem() {
showMenuItem(0);
}
/**
* Gets more menu items operation is different for different Android OS. When
* get overflow button view on action, it usually be able to click. But in
* some situation, will meet an error when click it. So catch it and try
* again. In most situation, the second click will be pass.
*
* @param depth control the depth of recursion to prevent dead circulation
*/
private static void showMenuItem(int depth) {
// ICS phone.
if (hasActionBar) {
instrumentation.waitForIdleSync();
View moreButton = getMoreOptionView();
// ICS phone without menu key.
if (moreButton != null) {
try {
SOLO.clickOnView(moreButton);
} catch (Throwable e) {
if (depth < 5 && e.getMessage().indexOf("Click can not be completed") > -1) {
showMenuItem(depth++);
}
}
return;
} else {
// ICS phone with menu key.
SOLO.sendKey(KeyEvent.KEYCODE_MENU);
}
} else {
// Non-ICS phone with menu key.
SOLO.sendKey(KeyEvent.KEYCODE_MENU);
}
}
/**
* Finds the more option menu. It should match following conditions:
* <ul>
* <li>The view extends ImageButton.</li>
* <li>The view name equals {@link #MORE_OPTION_CLASSNAME}.</li>
* </ul>
*
* @return the more option view. Null means can not find it.
*/
private static View getMoreOptionView() {
View viewResult = null;
if (hasActionBar) {
ArrayList<View> allViews = SOLO.getViews();
for (View view : allViews) {
if (view instanceof ImageButton && view.getClass().getName().equals(MORE_OPTION_CLASSNAME)) {
viewResult = view;
break;
}
}
} else {
ArrayList<View> allViews = SOLO.getViews();
for (View view : allViews) {
if (view.getClass().getName().equals(MENUITEM_CLASSNAME)) {
viewResult = view;
// No break here to get the last menu item.
}
}
}
return viewResult;
}
/**
* Finds a displayed text view with specified text in a view.
*
* @param text text to find
* @param parent which text view in in
* @return the text view, null means can not find it
*/
public static TextView findTextViewInView(String text, View parent) {
ArrayList<TextView> textViews = SOLO.getCurrentViews(TextView.class, parent);
for (TextView textView : textViews) {
String textString = (String) textView.getText();
if (textView.isShown() && textString.endsWith(text)) {
return textView;
}
}
return null;
}
/**
* Finds a displayed text view with specified text.
*
* @param text text to find
* @return the text view, null means can not find it
*/
public static TextView findTextView(String text) {
ArrayList<View> allViews = SOLO.getViews();
if (allViews != null) {
for (View view : allViews) {
if (view instanceof TextView) {
TextView textView = (TextView) view;
String textString = (String) textView.getText();
if (textView.isShown() && textString.endsWith(text)) {
return textView;
}
}
}
}
return null;
}
/**
* Finds a displayed text view with specified text and index number.
*
* @param text text to find
* @param index the index to search
* @return the text view, null means can not find it
*/
public static TextView findTextViewByIndex(String text, int index) {
int number = 1;
ArrayList<View> allViews = SOLO.getViews();
for (View view : allViews) {
if (view instanceof TextView) {
TextView textView = (TextView) view;
String textString = (String) textView.getText();
if (textView.isShown() && textString.endsWith(text)) {
if (number == index) {
return textView;
} else {
number++;
}
}
}
}
return null;
}
/**
* Resets all settings of MyTracks.
*
* @param activityMyTracks current activity
* @param keepInSettingList whether keep in setting list or not
*/
public static void resetAllSettings(Activity activityMyTracks, boolean keepInSettingList) {
findMenuItem(activityMyTracks.getString(R.string.menu_settings), true);
SOLO.clickOnText(activityMyTracks.getString(R.string.settings_advanced));
Assert.assertTrue(SOLO.waitForText(activityMyTracks.getString(R.string.settings_reset)));
SOLO.clickOnText(activityMyTracks.getString(R.string.settings_reset));
getButtonOnScreen(trackListActivity.getString(R.string.generic_yes), true, true);
Assert.assertTrue(SOLO.waitForText(activityMyTracks.getString(R.string.settings_reset_done)));
instrumentation.waitForIdleSync();
SOLO.goBack();
instrumentation.waitForIdleSync();
if (!keepInSettingList) {
SOLO.goBack();
}
}
/**
* Finds a edit text and enter text in it. This method can hides soft key
* board when input text.
*
* @param editTextIndex the index of edit text
* @param text to enter
*/
public static void enterTextAvoidSoftKeyBoard(int editTextIndex, String text) {
EditText editText = SOLO.getEditText(editTextIndex);
SOLO.enterText(editText, text);
SOLO.hideSoftKeyboard();
// Above line does not work every time. And it is should be a Robotium
// issue.
InputMethodManager imm = (InputMethodManager) trackListActivity.getApplicationContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
}
/**
* Waits n milliseconds.
*
* @param milliseconds time to sleep
*/
public static void sleep(long milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
Log.e(TAG, "Unable to sleep " + milliseconds, e);
}
}
/**
* Checks whether the recording is not started.
*/
public static void checkNotRecording() {
instrumentation.waitForIdleSync();
Assert.assertEquals(trackListActivity.getString(R.string.image_record),
(String) SOLO.getCurrentActivity()
.findViewById(R.id.track_controller_record).getContentDescription());
Assert.assertFalse(
SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop).isEnabled());
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_recording)));
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_paused)));
Assert.assertFalse(
SOLO.getCurrentActivity().findViewById(R.id.track_controller_total_time).isShown());
}
/**
* Checks whether the MyTracks is under recording.
*/
public static void checkUnderRecording() {
instrumentation.waitForIdleSync();
Assert.assertEquals(trackListActivity.getString(R.string.image_pause), (String) SOLO
.getCurrentActivity().findViewById(R.id.track_controller_record).getContentDescription());
Assert.assertTrue(SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop)
.isEnabled());
Assert.assertNotNull(findTextView(trackListActivity.getString(R.string.generic_recording)));
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_paused)));
String totalTimeOld = ((TextView) SOLO.getCurrentActivity().findViewById(
R.id.track_controller_total_time)).getText().toString();
sleep(2000);
String totalTimeNew = ((TextView) SOLO.getCurrentActivity().findViewById(
R.id.track_controller_total_time)).getText().toString();
Assert.assertFalse(totalTimeOld.equalsIgnoreCase(totalTimeNew));
}
/**
* Checks whether the recording is paused.
*/
public static void checkUnderPaused() {
instrumentation.waitForIdleSync();
Assert.assertEquals(trackListActivity.getString(R.string.image_record), (String) SOLO
.getCurrentActivity().findViewById(R.id.track_controller_record).getContentDescription());
Assert.assertTrue(SOLO.getCurrentActivity().findViewById(R.id.track_controller_stop)
.isEnabled());
Assert.assertNull(findTextView(trackListActivity.getString(R.string.generic_recording)));
Assert.assertNotNull(findTextView(trackListActivity.getString(R.string.generic_paused)));
String totalTimeOld = ((TextView) SOLO.getCurrentActivity().findViewById(
R.id.track_controller_total_time)).getText().toString();
sleep(2000);
String totalTimeNew = ((TextView) SOLO.getCurrentActivity().findViewById(
R.id.track_controller_total_time)).getText().toString();
Assert.assertTrue(totalTimeOld.equalsIgnoreCase(totalTimeNew));
}
/**
* Creates a way point during track recording.
*
* @param markerNumber of number of previous markers
*/
public static void createWaypoint(int markerNumber) {
findMenuItem(trackListActivity.getString(R.string.menu_markers), true);
instrumentation.waitForIdleSync();
if (markerNumber > 0 && hasGpsSignal) {
SOLO.waitForText(WAYPOINT_NAME);
int actualMarkerNumber = SOLO.getCurrentViews(ListView.class).get(0).getCount();
Assert.assertEquals(markerNumber, actualMarkerNumber);
} else {
Log.d(TAG, "marker number, hasGpsSignal: " + markerNumber + ", " + hasGpsSignal);
Assert.assertTrue(SOLO.waitForText(trackListActivity
.getString(R.string.marker_list_empty_message)));
}
findMenuItem(trackListActivity.getString(R.string.menu_insert_marker), true);
enterTextAvoidSoftKeyBoard(0, WAYPOINT_NAME + (markerNumber + 1));
enterTextAvoidSoftKeyBoard(1, WAYPOINT_TYPE + (markerNumber + 1));
enterTextAvoidSoftKeyBoard(2, WAYPOINT_DESCRIPTION + (markerNumber + 1));
SOLO.clickOnButton(trackListActivity.getString(R.string.generic_add));
instrumentation.waitForIdleSync();
if (hasGpsSignal) {
Assert.assertTrue(SOLO.waitForText(WAYPOINT_NAME, 1, LONG_WAIT_TIME, true));
} else {
Assert.assertFalse(SOLO.searchText(WAYPOINT_NAME));
}
SOLO.goBack();
}
/**
* Waits a text to disappear.
*/
public static void waitTextToDisappear(String text) {
instrumentation.waitForIdleSync();
SOLO.waitForText(text, 1, VERY_SHORT_WAIT_TIME);
while (SOLO.waitForText(text, 1, VERY_SHORT_WAIT_TIME)) {}
return;
}
/**
* Finds the My Location view and click it.
*
* @param activity
*/
private static void findAndClickMyLocation(Activity activity) {
createTrackIfEmpty(1, false);
sendGps(30);
View myLocation = SOLO.getCurrentActivity().findViewById(R.id.map_my_location);
instrumentation.waitForIdleSync();
// Find the My Location button in another if null.
if (myLocation == null) {
ArrayList<ImageButton> aa = SOLO.getCurrentViews(ImageButton.class);
for (ImageButton imageButton : aa) {
if (imageButton.getContentDescription() != null
&& imageButton.getContentDescription().equals(
activity.getString(R.string.image_my_location))) {
myLocation = imageButton;
break;
}
}
}
SOLO.clickOnView(myLocation);
}
/**
* Gets the relative start time suffix.
*/
public static String getRelativeStartTimeSuffix() {
String value = RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.get(language);
return value != null ? value : RELATIVE_START_TIME_SUFFIX_MULTILINGUAL.get("en");
}
/**
* Changes to metric units.
*/
public static void changeToMetricUnits() {
EndToEndTestUtils.findMenuItem(trackListActivity.getString(R.string.menu_settings), true);
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.track_detail_stats_tab));
Assert.assertTrue(EndToEndTestUtils.SOLO.waitForText(
trackListActivity.getString(R.string.settings_stats_units_title)));
// Change the preferred units
EndToEndTestUtils.SOLO.clickOnText(
trackListActivity.getString(R.string.settings_stats_units_title));
EndToEndTestUtils.SOLO.clickOnText(trackListActivity.getString(R.string.unit_kilometer));
EndToEndTestUtils.SOLO.goBack();
EndToEndTestUtils.SOLO.goBack();
}
}