1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2024-10-06 19:01:15 +01:00

GooglePlayBooks: Code tidy to conform. Additional parameter added for when the search name differs to the library name. Defaults changed due to Hamlet dissapearing from the store.

Added cornercase of accidentially triggering a card popup

New version includes a new dialogue and name for search. Added support for this

If device has more than one account associated, a new popup appears. Handle that with an optional parameter listing specific account to select, if ommitted the first account in the list is selected
This commit is contained in:
Michael McGeagh 2016-09-28 18:05:04 +01:00
parent 77d724efa3
commit f8966bf324
3 changed files with 256 additions and 180 deletions

View File

@ -14,7 +14,6 @@
# #
from wlauto import AndroidUxPerfWorkload, Parameter from wlauto import AndroidUxPerfWorkload, Parameter
from wlauto.exceptions import DeviceError
class Googleplaybooks(AndroidUxPerfWorkload): class Googleplaybooks(AndroidUxPerfWorkload):
@ -27,7 +26,7 @@ class Googleplaybooks(AndroidUxPerfWorkload):
package + '/com.android.vending/com.google.android.finsky.activities.MainActivity', package + '/com.android.vending/com.google.android.finsky.activities.MainActivity',
package + '/com.google.android.apps.books.app.ReadingActivity', package + '/com.google.android.apps.books.app.ReadingActivity',
package + '/com.google.android.apps.books.app.TableOfContentsActivityLight'] package + '/com.google.android.apps.books.app.TableOfContentsActivityLight']
description = """ description = '''
A workload to perform standard productivity tasks with googleplaybooks. A workload to perform standard productivity tasks with googleplaybooks.
This workload performs various tasks, such as searching for a book title This workload performs various tasks, such as searching for a book title
online, browsing through a book, adding and removing notes, word searching, online, browsing through a book, adding and removing notes, word searching,
@ -48,32 +47,57 @@ class Googleplaybooks(AndroidUxPerfWorkload):
12. Switches page styles from 'Day' to 'Night' to 'Sepia' and back to 'Day' 12. Switches page styles from 'Day' to 'Night' to 'Sepia' and back to 'Day'
13. Uses the 'About this book' facility on the currently selected book 13. Uses the 'About this book' facility on the currently selected book
NOTE: This workload requires a network connection (ideally, wifi) to run NOTE: This workload requires a network connection (ideally, wifi) to run,
and a Google account to be setup on the device. a Google account to be setup on the device, and payment details for the account.
""" Free books require payment details to have been setup otherwise it fails.
Tip: Install the 'Google Opinion Rewards' app to bypass the need to enter valid
card/bank detail.
'''
parameters = [ parameters = [
Parameter('search_book_title', kind=str, mandatory=False, default="Hamlet", Parameter('search_book_title', kind=str, default='Nikola Tesla: Imagination and the Man That Invented the 20th Century',
description=""" description="""
The book title to search for within Google Play Books archive. The book title to search for within Google Play Books archive.
The book must either be already in the account's library, or free to purchase. The book must either be already in the account's library, or free to purchase.
"""), """),
Parameter('select_chapter_page_number', kind=int, mandatory=False, default=22, Parameter('library_book_title', kind=str, default='Nikola Tesla',
description="""
The book title to search for within My Library.
The Library name can differ (usually shorter) to the Store name.
If left blank, the ``search_book_title`` will be used.
"""),
Parameter('select_chapter_page_number', kind=int, default=4,
description=""" description="""
The Page Number to search for within a selected book's Chapter list. The Page Number to search for within a selected book's Chapter list.
Note: Accepts integers only. Note: Accepts integers only.
"""), """),
Parameter('search_word', kind=str, mandatory=False, default='the', Parameter('search_word', kind=str, default='the',
description=""" description="""
The word to search for within a selected book. The word to search for within a selected book.
Note: Accepts single words only. Note: Accepts single words only.
"""), """),
Parameter('account', kind=str, mandatory=False,
description="""
If you are running this workload on a device which has more than one
Google account setup, then this parameter is used to select which account
to select when prompted.
The account requires the book to have already been purchased or payment details
already associated with the account.
If omitted, the first account in the list will be selected if prompted.
"""),
] ]
# This workload relies on the internet so check that there is a working
# internet connection
requires_network = True requires_network = True
def validate(self): def validate(self):
super(Googleplaybooks, self).validate() super(Googleplaybooks, self).validate()
self.uiauto_params['book_title'] = self.search_book_title.replace(" ", "0space0") self.uiauto_params['search_book_title'] = self.search_book_title.replace(' ', '0space0')
# If library_book_title is blank, set it to the same as search_book_title
if not self.library_book_title: # pylint: disable=access-member-before-definition
self.library_book_title = self.search_book_title # pylint: disable=attribute-defined-outside-init
self.uiauto_params['library_book_title'] = self.library_book_title.replace(' ', '0space0')
self.uiauto_params['chapter_page_number'] = self.select_chapter_page_number self.uiauto_params['chapter_page_number'] = self.select_chapter_page_number
self.uiauto_params['search_word'] = self.search_word self.uiauto_params['search_word'] = self.search_word
self.uiauto_params['account'] = self.account

View File

@ -26,13 +26,18 @@ import com.android.uiautomator.core.UiScrollable;
import com.arm.wlauto.uiauto.UxPerfUiAutomation; import com.arm.wlauto.uiauto.UxPerfUiAutomation;
import static com.arm.wlauto.uiauto.BaseUiAutomation.FindByCriteria.BY_ID;
import static com.arm.wlauto.uiauto.BaseUiAutomation.FindByCriteria.BY_TEXT;
import static com.arm.wlauto.uiauto.BaseUiAutomation.FindByCriteria.BY_DESC;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Iterator; import java.util.Iterator;
import android.util.Log;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import android.util.Log;
public class UiAutomation extends UxPerfUiAutomation { public class UiAutomation extends UxPerfUiAutomation {
protected Bundle parameters; protected Bundle parameters;
@ -43,25 +48,31 @@ public class UiAutomation extends UxPerfUiAutomation {
private long viewTimeout = TimeUnit.SECONDS.toMillis(viewTimeoutSecs); private long viewTimeout = TimeUnit.SECONDS.toMillis(viewTimeoutSecs);
public void runUiAutomation() throws Exception { public void runUiAutomation() throws Exception {
// Override superclass value
this.uiAutoTimeout = TimeUnit.SECONDS.toMillis(8); this.uiAutoTimeout = TimeUnit.SECONDS.toMillis(8);
parameters = getParams(); parameters = getParams();
packageName = parameters.getString("package"); packageName = parameters.getString("package");
packageID = packageName + ":id/"; packageID = packageName + ":id/";
String bookTitle = parameters.getString("book_title").replace("0space0", " "); String searchBookTitle = parameters.getString("search_book_title").replace("0space0", " ");
String libraryBookTitle = parameters.getString("library_book_title").replace("0space0", " ");
String chapterPageNumber = parameters.getString("chapter_page_number"); String chapterPageNumber = parameters.getString("chapter_page_number");
String searchWord = parameters.getString("search_word"); String searchWord = parameters.getString("search_word");
String noteText = "This is a test note"; String noteText = "This is a test note";
String account = parameters.getString("account");
setScreenOrientation(ScreenOrientation.NATURAL); setScreenOrientation(ScreenOrientation.NATURAL);
chooseAccount(account);
clearFirstRunDialogues(); clearFirstRunDialogues();
dismissSendBooksAsGiftsDialog();
dismissSync(); dismissSync();
searchForBook(bookTitle); searchForBook(searchBookTitle);
addToLibrary(); addToLibrary();
openMyLibrary(); openMyLibrary();
openBook(bookTitle); openBook(libraryBookTitle);
UiWatcher pageSyncPopUpWatcher = createPopUpWatcher(); UiWatcher pageSyncPopUpWatcher = createPopUpWatcher();
registerWatcher("pageSyncPopUp", pageSyncPopUpWatcher); registerWatcher("pageSyncPopUp", pageSyncPopUpWatcher);
@ -77,45 +88,38 @@ public class UiAutomation extends UxPerfUiAutomation {
removeWatcher("pageSyncPop"); removeWatcher("pageSyncPop");
pressBack(); pressBack();
unsetScreenOrientation(); unsetScreenOrientation();
} }
// Creates a watcher for when a pop up warning appears when pages are out // If the device has more than one account setup, a prompt appears
// of sync across multiple devices. // In this case, select the first account in the list, unless `account`
private UiWatcher createPopUpWatcher() throws Exception { // has been specified as a parameter, otherwise select `account`.
UiWatcher pageSyncPopUpWatcher = new UiWatcher() { private void chooseAccount(String account) throws Exception {
UiObject accountPopup =
@Override new UiObject(new UiSelector().textContains("Choose an account")
public boolean checkForCondition() { .className("android.widget.TextView"));
UiObject popUpDialogue = if (accountPopup.exists()) {
new UiObject(new UiSelector().resourceId("android:id/message") if ("None".equals(account)) {
.textStartsWith("You're on page")); // If no account has been specified, pick the first entry in the list
UiObject list =
// Don't sync and stay on the current page new UiObject(new UiSelector().className("android.widget.ListView"));
if (popUpDialogue.exists()) { UiObject first = list.getChild(new UiSelector().index(0));
try { if (!first.exists()) {
UiObject stayOnPage = new UiObject(new UiSelector() // Some devices are not zero indexed. If 0 doesnt exist, pick 1
first = list.getChild(new UiSelector().index(1));
}
first.click();
} else {
// Account specified, select that
clickUiObject(BY_TEXT, account, "android.widget.CheckedTextView");
}
// Click OK to proceed
UiObject ok =
new UiObject(new UiSelector().textContains("OK")
.className("android.widget.Button") .className("android.widget.Button")
.text("Yes")); .enabled(true));
stayOnPage.click(); ok.clickAndWaitForNewWindow();
} catch (UiObjectNotFoundException e) {
e.printStackTrace();
}
return popUpDialogue.waitUntilGone(viewTimeout);
}
return false;
}
};
return pageSyncPopUpWatcher;
}
private void dismissSync() throws Exception {
UiObject keepSyncOff =
new UiObject(new UiSelector().textContains("Keep sync off")
.className("android.widget.Button"));
if (keepSyncOff.exists()) {
keepSyncOff.click();
} }
} }
@ -125,7 +129,6 @@ public class UiAutomation extends UxPerfUiAutomation {
private void clearFirstRunDialogues() throws Exception { private void clearFirstRunDialogues() throws Exception {
UiObject startButton = UiObject startButton =
new UiObject(new UiSelector().resourceId(packageID + "start_button")); new UiObject(new UiSelector().resourceId(packageID + "start_button"));
// First try and skip the sample book selection // First try and skip the sample book selection
if (startButton.exists()) { if (startButton.exists()) {
startButton.click(); startButton.click();
@ -133,7 +136,6 @@ public class UiAutomation extends UxPerfUiAutomation {
UiObject endButton = UiObject endButton =
new UiObject(new UiSelector().resourceId(packageID + "end_button")); new UiObject(new UiSelector().resourceId(packageID + "end_button"));
// Click next button if it exists // Click next button if it exists
if (endButton.exists()) { if (endButton.exists()) {
endButton.click(); endButton.click();
@ -148,49 +150,65 @@ public class UiAutomation extends UxPerfUiAutomation {
} }
} }
private void dismissSendBooksAsGiftsDialog() throws Exception {
UiObject gotIt =
new UiObject(new UiSelector().textContains("GOT IT!"));
if (gotIt.exists()) {
gotIt.click();
}
}
private void dismissSync() throws Exception {
UiObject keepSyncOff =
new UiObject(new UiSelector().textContains("Keep sync off")
.className("android.widget.Button"));
if (keepSyncOff.exists()) {
keepSyncOff.click();
}
}
// Searches for a "free" or "purchased" book title in Google play // Searches for a "free" or "purchased" book title in Google play
private void searchForBook(final String bookTitle) throws Exception { private void searchForBook(final String bookTitle) throws Exception {
UiObject search = UiObject search =
new UiObject(new UiSelector().resourceId(packageID + "menu_search")); new UiObject(new UiSelector().resourceId(packageID + "menu_search"));
if (!search.exists()) {
search =
new UiObject(new UiSelector().resourceId(packageID + "search_box_active_text_view"));
}
search.click(); search.click();
UiObject searchText = new UiObject(new UiSelector().textContains("Search") UiObject searchText =
new UiObject(new UiSelector().textContains("Search")
.className("android.widget.EditText")); .className("android.widget.EditText"));
searchText.setText(bookTitle); searchText.setText(bookTitle);
pressEnter(); pressEnter();
UiObject resultList = UiObject resultList =
new UiObject(new UiSelector().resourceId("com.android.vending:id/search_results_list")); new UiObject(new UiSelector().resourceId("com.android.vending:id/search_results_list"));
if (!resultList.waitForExists(viewTimeout)) { if (!resultList.waitForExists(viewTimeout)) {
throw new UiObjectNotFoundException("Could not find \"search results list view\"."); throw new UiObjectNotFoundException("Could not find \"search results list view\".");
} }
String desc = String.format("Book: " + bookTitle);
// Create a selector so that we can search for siblings of the desired // Create a selector so that we can search for siblings of the desired
// book that contains a "free" or "purchased" book identifier // book that contains a "free" or "purchased" book identifier
UiSelector bookSelector = new UiSelector().description(desc).className("android.widget.TextView");
UiObject label = UiObject label =
new UiObject(new UiSelector().fromParent(bookSelector) new UiObject(new UiSelector().fromParent(new UiSelector()
.description(String.format("Book: " + bookTitle))
.className("android.widget.TextView"))
.resourceId("com.android.vending:id/li_label") .resourceId("com.android.vending:id/li_label")
.descriptionMatches("^(Purchased|Free)$")); .descriptionMatches("^(Purchased|Free)$"));
UiScrollable searchResultsList =
new UiScrollable(new UiSelector().resourceId("com.android.vending:id/search_results_list"));
final int maxSearchTime = 30; final int maxSearchTime = 30;
int searchTime = maxSearchTime; int searchTime = maxSearchTime;
while (!label.exists()) { while (!label.exists()) {
if (searchTime <= 0) { if (searchTime > 0) {
throw new UiObjectNotFoundException(
"Exceeded maximum search time (" + maxSearchTime + " seconds) to find book \"" + bookTitle + "\"");
} else {
uiDeviceSwipeDown(100); uiDeviceSwipeDown(100);
sleep(1); sleep(1);
searchTime--; searchTime--;
} else {
throw new UiObjectNotFoundException(
"Exceeded maximum search time (" + maxSearchTime + " seconds) to find book \"" + bookTitle + "\"");
} }
} }
@ -200,18 +218,22 @@ public class UiAutomation extends UxPerfUiAutomation {
} }
private void addToLibrary() throws Exception { private void addToLibrary() throws Exception {
UiObject add = new UiObject(new UiSelector().textContains("ADD TO LIBRARY") UiObject add =
new UiObject(new UiSelector().textContains("ADD TO LIBRARY")
.className("android.widget.Button")); .className("android.widget.Button"));
if (add.exists()) { if (add.exists()) {
add.click(); // add to My Library and opens book by default // add to My Library and opens book by default
add.click();
clickUiObject(BY_TEXT, "BUY", "android.widget.Button", true);
} else { } else {
UiObject read = getUiObjectByText("READ", "android.widget.Button"); // opens book
read.click(); // opens book clickUiObject(BY_TEXT, "READ", "android.widget.Button");
} }
waitForPage(); waitForPage();
UiObject navigationButton = new UiObject(new UiSelector().description("Navigate up")); UiObject navigationButton =
new UiObject(new UiSelector().description("Navigate up"));
// Return to main app window // Return to main app window
pressBack(); pressBack();
@ -227,15 +249,14 @@ public class UiAutomation extends UxPerfUiAutomation {
private void openMyLibrary() throws Exception { private void openMyLibrary() throws Exception {
String testTag = "open_library"; String testTag = "open_library";
ActionLogger logger = new ActionLogger(testTag, parameters); ActionLogger logger = new ActionLogger(testTag, parameters);
logger.start(); logger.start();
clickUiObject(BY_DESC, "Show navigation drawer");
UiObject openDrawer = getUiObjectByDescription("Show navigation drawer");
openDrawer.click();
// To correctly find the UiObject we need to specify the index also here // To correctly find the UiObject we need to specify the index also here
UiObject myLibrary = UiObject myLibrary =
new UiObject(new UiSelector().className("android.widget.TextView") new UiObject(new UiSelector().className("android.widget.TextView")
.text("My library").index(3)); .text("My library")
.index(3));
myLibrary.clickAndWaitForNewWindow(uiAutoTimeout); myLibrary.clickAndWaitForNewWindow(uiAutoTimeout);
logger.stop(); logger.stop();
} }
@ -244,31 +265,24 @@ public class UiAutomation extends UxPerfUiAutomation {
String testTag = "open_book"; String testTag = "open_book";
ActionLogger logger = new ActionLogger(testTag, parameters); ActionLogger logger = new ActionLogger(testTag, parameters);
UiScrollable cardsGrid = long maxWaitTimeSeconds = 120;
new UiScrollable(new UiSelector().resourceId(packageID + "cards_grid")); long maxWaitTime = TimeUnit.SECONDS.toMillis(maxWaitTimeSeconds);
UiSelector bookSelector = new UiSelector().text(bookTitle).className("android.widget.TextView"); UiSelector bookSelector =
new UiSelector().text(bookTitle)
.className("android.widget.TextView");
UiObject book = new UiObject(bookSelector); UiObject book = new UiObject(bookSelector);
// Check that books are sorted by time added to library. This way we // Check that books are sorted by time added to library. This way we
// can assume any newly downloaded books will be visible on the first // can assume any newly downloaded books will be visible on the first
// screen. // screen.
UiObject menuSort = clickUiObject(BY_ID, packageID + "menu_sort", "android.widget.TextView");
getUiObjectByResourceId(packageID + "menu_sort", "android.widget.TextView"); clickUiObject(BY_TEXT, "Recent", "android.widget.TextView");
menuSort.click();
UiObject sortByRecent = getUiObjectByText("Recent", "android.widget.TextView");
sortByRecent.click();
// When the book is first added to library it may not appear in // When the book is first added to library it may not appear in
// cardsGrid until it has been fully downloaded. Wait for fully // cardsGrid until it has been fully downloaded. Wait for fully
// downloaded books // downloaded books
UiObject downloadComplete = UiObject downloadComplete =
new UiObject(new UiSelector().fromParent(bookSelector).description("100% downloaded")); new UiObject(new UiSelector().fromParent(bookSelector)
.description("100% downloaded"));
long maxWaitTimeSeconds = 120;
long maxWaitTime = TimeUnit.SECONDS.toMillis(maxWaitTimeSeconds);
if (!downloadComplete.waitForExists(maxWaitTime)) { if (!downloadComplete.waitForExists(maxWaitTime)) {
throw new UiObjectNotFoundException( throw new UiObjectNotFoundException(
"Exceeded maximum wait time (" + maxWaitTimeSeconds + " seconds) to download book \"" + bookTitle + "\""); "Exceeded maximum wait time (" + maxWaitTimeSeconds + " seconds) to download book \"" + bookTitle + "\"");
@ -280,6 +294,50 @@ public class UiAutomation extends UxPerfUiAutomation {
logger.stop(); logger.stop();
} }
// Creates a watcher for when a pop up warning appears when pages are out
// of sync across multiple devices.
private UiWatcher createPopUpWatcher() throws Exception {
UiWatcher pageSyncPopUpWatcher = new UiWatcher() {
@Override
public boolean checkForCondition() {
UiObject popUpDialogue =
new UiObject(new UiSelector().textStartsWith("You're on page")
.resourceId("android:id/message"));
// Don't sync and stay on the current page
if (popUpDialogue.exists()) {
try {
UiObject stayOnPage =
new UiObject(new UiSelector().text("Yes")
.className("android.widget.Button"));
stayOnPage.click();
} catch (UiObjectNotFoundException e) {
e.printStackTrace();
}
return popUpDialogue.waitUntilGone(viewTimeout);
}
return false;
}
};
return pageSyncPopUpWatcher;
}
private void selectChapter(final String chapterPageNumber) throws Exception {
getDropdownMenu();
UiObject contents = getUiObjectByResourceId(packageID + "menu_reader_toc");
contents.clickAndWaitForNewWindow(uiAutoTimeout);
UiObject toChapterView = getUiObjectByResourceId(packageID + "toc_list_view",
"android.widget.ExpandableListView");
// Navigate to top of chapter view
searchPage(toChapterView, "1", Direction.UP, 10);
// Search for chapter page number
UiObject page = searchPage(toChapterView, chapterPageNumber, Direction.DOWN, 10);
// Go to the page
page.clickAndWaitForNewWindow(viewTimeout);
waitForPage();
}
private void gesturesTest() throws Exception { private void gesturesTest() throws Exception {
String testTag = "gesture"; String testTag = "gesture";
@ -324,72 +382,28 @@ public class UiAutomation extends UxPerfUiAutomation {
waitForPage(); waitForPage();
} }
private UiObject searchPage(final UiObject view, final String pagenum, final Direction updown,
final int attempts) throws Exception {
if (attempts <= 0) {
throw new UiObjectNotFoundException("Could not find \"page number\" after several attempts.");
}
String search = String.format("page " + pagenum);
UiObject page = new UiObject(new UiSelector().description(search)
.className("android.widget.TextView"));
if (!page.exists()) {
// Scroll up by swiping down
if (updown == Direction.UP) {
view.swipeDown(200);
// Default case is to scroll down (swipe up)
} else {
view.swipeUp(200);
}
searchPage(view, pagenum, updown, attempts - 1);
}
return page;
}
private void selectChapter(final String chapterPageNumber) throws Exception {
getDropdownMenu();
UiObject contents = getUiObjectByResourceId(packageID + "menu_reader_toc");
contents.clickAndWaitForNewWindow(uiAutoTimeout);
UiObject toChapterView = getUiObjectByResourceId(packageID + "toc_list_view",
"android.widget.ExpandableListView");
// Navigate to top of chapter view
searchPage(toChapterView, "1", Direction.UP, 10);
UiObject page = searchPage(toChapterView, chapterPageNumber, Direction.DOWN, 10);
page.clickAndWaitForNewWindow(viewTimeout);
waitForPage();
}
private void addNote(final String text) throws Exception { private void addNote(final String text) throws Exception {
String testTag = "note_add"; String testTag = "note_add";
ActionLogger logger = new ActionLogger(testTag, parameters); ActionLogger logger = new ActionLogger(testTag, parameters);
hideDropDownMenu(); hideDropDownMenu();
UiObject clickable = new UiObject(new UiSelector().longClickable(true));
logger.start(); logger.start();
UiObject clickable = new UiObject(new UiSelector().longClickable(true));
uiObjectPerformLongClick(clickable, 100); uiObjectPerformLongClick(clickable, 100);
UiObject addNoteButton = new UiObject( UiObject addNoteButton =
new UiSelector().resourceId(packageID + "add_note_button")); new UiObject(new UiSelector().resourceId(packageID + "add_note_button"));
addNoteButton.click(); addNoteButton.click();
UiObject noteEditText = getUiObjectByResourceId(packageID + "note_edit_text", UiObject noteEditText = getUiObjectByResourceId(packageID + "note_edit_text",
"android.widget.EditText"); "android.widget.EditText");
noteEditText.setText(text); noteEditText.setText(text);
UiObject noteMenuButton = getUiObjectByResourceId(packageID + "note_menu_button", clickUiObject(BY_ID, packageID + "note_menu_button", "android.widget.ImageButton");
"android.widget.ImageButton"); clickUiObject(BY_TEXT, "Save", "android.widget.TextView");
noteMenuButton.click();
UiObject saveButton = getUiObjectByText("Save", "android.widget.TextView");
saveButton.click();
logger.stop(); logger.stop();
@ -399,17 +413,18 @@ public class UiAutomation extends UxPerfUiAutomation {
private void removeNote() throws Exception { private void removeNote() throws Exception {
String testTag = "note_remove"; String testTag = "note_remove";
ActionLogger logger = new ActionLogger(testTag, parameters); ActionLogger logger = new ActionLogger(testTag, parameters);
logger.start();
UiObject clickable = new UiObject(new UiSelector().longClickable(true)); UiObject clickable = new UiObject(new UiSelector().longClickable(true));
logger.start();
uiObjectPerformLongClick(clickable, 100); uiObjectPerformLongClick(clickable, 100);
UiObject removeButton = new UiObject( UiObject removeButton =
new UiSelector().resourceId(packageID + "remove_highlight_button")); new UiObject(new UiSelector().resourceId(packageID + "remove_highlight_button"));
removeButton.click(); removeButton.click();
UiObject confirmRemove = getUiObjectByText("Remove", "android.widget.Button"); clickUiObject(BY_TEXT, "Remove", "android.widget.Button");
confirmRemove.click();
logger.stop(); logger.stop();
@ -420,26 +435,25 @@ public class UiAutomation extends UxPerfUiAutomation {
String testTag = "search_word"; String testTag = "search_word";
ActionLogger logger = new ActionLogger(testTag, parameters); ActionLogger logger = new ActionLogger(testTag, parameters);
// Allow extra time for search queries involing high freqency words
final long searchTimeout = TimeUnit.SECONDS.toMillis(20);
getDropdownMenu(); getDropdownMenu();
UiObject search = new UiObject( UiObject search =
new UiSelector().resourceId(packageID + "menu_search")); new UiObject(new UiSelector().resourceId(packageID + "menu_search"));
search.click(); search.click();
UiObject searchText = new UiObject( UiObject searchText =
new UiSelector().resourceId(packageID + "search_src_text")); new UiObject(new UiSelector().resourceId(packageID + "search_src_text"));
logger.start(); logger.start();
searchText.setText(text); searchText.setText(text);
pressEnter(); pressEnter();
UiObject resultList = new UiObject( UiObject resultList =
new UiSelector().resourceId(packageID + "search_results_list")); new UiObject(new UiSelector().resourceId(packageID + "search_results_list"));
// Allow extra time for search queries involing high freqency words
final long searchTimeout = TimeUnit.SECONDS.toMillis(20);
if (!resultList.waitForExists(searchTimeout)) { if (!resultList.waitForExists(searchTimeout)) {
throw new UiObjectNotFoundException("Could not find \"search results list view\"."); throw new UiObjectNotFoundException("Could not find \"search results list view\".");
} }
@ -447,7 +461,6 @@ public class UiAutomation extends UxPerfUiAutomation {
UiObject searchWeb = UiObject searchWeb =
new UiObject(new UiSelector().text("Search web") new UiObject(new UiSelector().text("Search web")
.className("android.widget.TextView")); .className("android.widget.TextView"));
if (!searchWeb.waitForExists(searchTimeout)) { if (!searchWeb.waitForExists(searchTimeout)) {
throw new UiObjectNotFoundException("Could not find \"Search web view\"."); throw new UiObjectNotFoundException("Could not find \"Search web view\".");
} }
@ -461,27 +474,27 @@ public class UiAutomation extends UxPerfUiAutomation {
String testTag = "style"; String testTag = "style";
getDropdownMenu(); getDropdownMenu();
UiObject readerSettings = getUiObjectByResourceId(packageID + "menu_reader_settings",
"android.widget.TextView"); clickUiObject(BY_ID, packageID + "menu_reader_settings", "android.widget.TextView");
readerSettings.click();
// Check for lighting option button on newer versions // Check for lighting option button on newer versions
UiObject lightingOptionsButton = UiObject lightingOptionsButton =
new UiObject(new UiSelector().resourceId(packageID + "lighting_options_button")); new UiObject(new UiSelector().resourceId(packageID + "lighting_options_button"));
if (lightingOptionsButton.exists()) { if (lightingOptionsButton.exists()) {
lightingOptionsButton.click(); lightingOptionsButton.click();
} }
String[] styles = {"Night", "Sepia", "Day"}; String[] styles = {"Night", "Sepia", "Day"};
for (String style : styles) { for (String style : styles) {
try { try {
ActionLogger logger = new ActionLogger(testTag + "_" + style, parameters); ActionLogger logger = new ActionLogger(testTag + "_" + style, parameters);
UiObject pageStyle = new UiObject(new UiSelector().description(style)); UiObject pageStyle =
new UiObject(new UiSelector().description(style));
logger.start(); logger.start();
pageStyle.clickAndWaitForNewWindow(viewTimeout); pageStyle.clickAndWaitForNewWindow(viewTimeout);
logger.stop(); logger.stop();
} catch (UiObjectNotFoundException e) { } catch (UiObjectNotFoundException e) {
// On some devices the lighting options menu disappears // On some devices the lighting options menu disappears
// between clicks. Searching for the menu again would affect // between clicks. Searching for the menu again would affect
@ -501,8 +514,7 @@ public class UiAutomation extends UxPerfUiAutomation {
getDropdownMenu(); getDropdownMenu();
UiObject moreOptions = getUiObjectByDescription("More options", "android.widget.ImageView"); clickUiObject(BY_DESC, "More options", "android.widget.ImageView");
moreOptions.click();
UiObject bookInfo = getUiObjectByText("About this book", "android.widget.TextView"); UiObject bookInfo = getUiObjectByText("About this book", "android.widget.TextView");
@ -519,16 +531,52 @@ public class UiAutomation extends UxPerfUiAutomation {
pressBack(); pressBack();
} }
// Helper for waiting on a page between actions
private UiObject waitForPage() throws Exception {
UiObject activityReader =
new UiObject(new UiSelector().resourceId(packageID + "activity_reader")
.childSelector(new UiSelector()
.focusable(true)));
// On some devices the object in the view hierarchy is found before it
// becomes visible on the screen. Therefore add pause instead.
sleep(3);
if (!activityReader.waitForExists(viewTimeout)) {
throw new UiObjectNotFoundException("Could not find \"activity reader view\".");
}
return activityReader;
}
// Helper for accessing the drop down menu // Helper for accessing the drop down menu
private void getDropdownMenu() throws Exception { private void getDropdownMenu() throws Exception {
UiObject actionBar = UiObject actionBar =
new UiObject(new UiSelector().resourceId(packageID + "action_bar")); new UiObject(new UiSelector().resourceId(packageID + "action_bar"));
if (!actionBar.exists()) { if (!actionBar.exists()) {
tapDisplayCentre(); tapDisplayCentre();
sleep(1); // Allow previous views to settle sleep(1); // Allow previous views to settle
} }
UiObject card =
new UiObject(new UiSelector().resourceId(packageID + "cards")
.className("android.view.ViewGroup"));
if (card.exists()) {
// On rare occasions tapping a certain word that appears in the centre
// of the display will bring up a card to describe the word.
// (Such as a place will bring a map of its location)
// In this situation, tap centre to go back, and try again
// at a different set of coordinates
int x = (int)(getDisplayCentreWidth() * 0.8);
int y = (int)(getDisplayCentreHeight() * 0.8);
while (card.exists()) {
tapDisplay(x, y);
sleep(1);
}
tapDisplay(x, y);
sleep(1); // Allow previous views to settle
}
if (!actionBar.exists()) { if (!actionBar.exists()) {
throw new UiObjectNotFoundException("Could not find \"action bar\"."); throw new UiObjectNotFoundException("Could not find \"action bar\".");
} }
@ -537,7 +585,6 @@ public class UiAutomation extends UxPerfUiAutomation {
private void hideDropDownMenu() throws Exception { private void hideDropDownMenu() throws Exception {
UiObject actionBar = UiObject actionBar =
new UiObject(new UiSelector().resourceId(packageID + "action_bar")); new UiObject(new UiSelector().resourceId(packageID + "action_bar"));
if (actionBar.exists()) { if (actionBar.exists()) {
tapDisplayCentre(); tapDisplayCentre();
sleep(1); // Allow previous views to settle sleep(1); // Allow previous views to settle
@ -548,20 +595,25 @@ public class UiAutomation extends UxPerfUiAutomation {
} }
} }
// Helper for waiting on a page between actions private UiObject searchPage(final UiObject view, final String pagenum, final Direction updown,
private UiObject waitForPage() throws Exception { final int attempts) throws Exception {
UiObject activityReader = if (attempts <= 0) {
new UiObject(new UiSelector().resourceId(packageID + "activity_reader") throw new UiObjectNotFoundException("Could not find \"page number\" after several attempts.");
.childSelector(new UiSelector().focusable(true)));
// On some devices the object in the view hierarchy is found before it
// becomes visible on the screen. Therefore add pause instead.
sleep(3);
if (!activityReader.waitForExists(viewTimeout)) {
throw new UiObjectNotFoundException("Could not find \"activity reader view\".");
} }
return activityReader; UiObject page =
new UiObject(new UiSelector().description(String.format("page " + pagenum))
.className("android.widget.TextView"));
if (!page.exists()) {
// Scroll up by swiping down
if (updown == Direction.UP) {
view.swipeDown(200);
// Default case is to scroll down (swipe up)
} else {
view.swipeUp(200);
}
page = searchPage(view, pagenum, updown, attempts - 1);
}
return page;
} }
} }