blob: b6135ef41ec6e6f7d84681edd2c06db8bd27ca2b [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* 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.
*/
package androidx.leanback.app.wizard;
import static org.junit.Assert.assertTrue;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.view.KeyEvent;
import androidx.leanback.app.GuidedStepFragment;
import androidx.leanback.test.R;
import androidx.leanback.widget.GuidanceStylist;
import androidx.leanback.widget.GuidedAction;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@LargeTest
@RunWith(AndroidJUnit4.class)
public class GuidedStepAttributesTest {
static final long TRANSITION_LENGTH = 1000;
static final String TAG = "GuidedStepAttributesTest";
@Rule
public ActivityTestRule<GuidedStepAttributesTestActivity> activityTestRule =
new ActivityTestRule<>(GuidedStepAttributesTestActivity.class, false, false);
GuidedStepAttributesTestActivity mActivity;
private void initActivity(Intent intent) {
mActivity = activityTestRule.launchActivity(intent);
try {
Thread.sleep(2000);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
Context mContext;
@Before
public void setUp() {
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();;
}
public static void sendKey(int keyCode) {
InstrumentationRegistry.getInstrumentation().sendKeyDownUpSync(keyCode);
}
@Test
public void testFocusDisabledOnActions() throws Throwable {
Intent intent = new Intent();
Resources res = mContext.getResources();
final int NUM_SEARCH_ACTIONS = 10;
final List<Integer> ACTIONS_WITH_DISABLED_FOCUS = new ArrayList<>(
Arrays.asList(1, 3, 4, 5, 8));
final int ACTION_ID_SEARCH = 1;
List<Integer> EXPECTED_ACTIONS_ID_AFTER_EACH_SELECT = new ArrayList<>();
// we will traverse actions from top to bottom and then back to the top
for(int i = 0; i < NUM_SEARCH_ACTIONS; i++) {
if (!ACTIONS_WITH_DISABLED_FOCUS.contains(i))
EXPECTED_ACTIONS_ID_AFTER_EACH_SELECT.add(i);
}
for(int i = EXPECTED_ACTIONS_ID_AFTER_EACH_SELECT.size(); i-- != 0;) {
EXPECTED_ACTIONS_ID_AFTER_EACH_SELECT.add(EXPECTED_ACTIONS_ID_AFTER_EACH_SELECT.get(i));
}
String title = "Guided Actions Focusable Test";
String breadcrumb = "Focusable Test Demo";
String description = "";
GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
breadcrumb, null);
List<GuidedAction> actionList = new ArrayList<>();
for (int i = 0; i < NUM_SEARCH_ACTIONS; i++ ) {
actionList.add(new GuidedAction.Builder(mContext)
.id(ACTION_ID_SEARCH)
.title(res.getString(R.string.search) + "" + i)
.description(res.getString(R.string.search_description) + i)
.build()
);
}
for(int action_id : ACTIONS_WITH_DISABLED_FOCUS )
actionList.get(action_id).setFocusable(false);
GuidedStepAttributesTestFragment.GUIDANCE = guidance;
GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
initActivity(intent);
int lastSelectedActionId = -1;
int selectIndex = 0;
GuidedStepFragment mFragment = (GuidedStepFragment) mActivity.getGuidedStepTestFragment();
int prevSelectedActionPosition = -1;
int nextSelectedActionPosition = mFragment.getSelectedActionPosition();
while ( nextSelectedActionPosition != prevSelectedActionPosition ) {
lastSelectedActionId = mFragment.getSelectedActionPosition();
assertTrue(res.getString(R.string.focusable_test_error_message,
actionList.get(lastSelectedActionId).getTitle()),
lastSelectedActionId == EXPECTED_ACTIONS_ID_AFTER_EACH_SELECT.get(selectIndex));
selectIndex++;
sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
prevSelectedActionPosition = nextSelectedActionPosition;
nextSelectedActionPosition = mFragment.getSelectedActionPosition();
Thread.sleep(TRANSITION_LENGTH);
}
prevSelectedActionPosition = -1;
while ( nextSelectedActionPosition != prevSelectedActionPosition ) {
lastSelectedActionId = mFragment.getSelectedActionPosition();
assertTrue(res.getString(R.string.focusable_test_error_message,
actionList.get(lastSelectedActionId).getTitle()),
lastSelectedActionId == EXPECTED_ACTIONS_ID_AFTER_EACH_SELECT.get(selectIndex));
selectIndex++;
sendKey(KeyEvent.KEYCODE_DPAD_UP);
prevSelectedActionPosition = nextSelectedActionPosition;
nextSelectedActionPosition = mFragment.getSelectedActionPosition();
Thread.sleep(TRANSITION_LENGTH);
}
}
// Note: do not remove final or sRevertCallback gets null from 2nd test on!
static final GuidedStepAttributesTestFragment.Callback sRevertCallback = new
GuidedStepAttributesTestFragment.Callback() {
@Override
public void onActionClicked(GuidedStepFragment fragment, long id) {
List<GuidedAction> allActions = fragment.getActions();
for(int i = 1; i < allActions.size(); i++) {
GuidedAction action = allActions.get(i);
action.setEnabled(!action.isEnabled());
fragment.notifyActionChanged(fragment.findActionPositionById(action.getId()));
}
}
};
/**
* Creates a number of enabled and disable actions and tests whether the flag is correctly set
* by clicking on each individual action and checking whether the click event is triggered.
* @throws Throwable
*/
@Test
public void testDisabledActions() throws Throwable {
Intent intent = new Intent();
Resources res = mContext.getResources();
final int NUM_SEARCH_ACTIONS = 10;
final List<Integer> DISABLED_ACTIONS = new ArrayList<>(
Arrays.asList(1, 3, 5, 7));
final int ACTION_ID_REVERT_BUTTON = 0;
final int ACTION_ID_SEARCH_BEGIN = ACTION_ID_REVERT_BUTTON + 1;
int ACTION_ID_SEARCH_END = ACTION_ID_SEARCH_BEGIN;
// sequence of clicked actions simulated in the test
List<Integer> CLICK_SEQUENCE = new ArrayList<>();
// Expected Clicked sequence can be different from focused ones since some of the actions
// are disabled hence not clickable
List<Integer> EXPECTED_FOCUSED_SEQUENCE = new ArrayList<>();
List<Integer> EXPECTED_CLICKED_SEQUENCE = new ArrayList<>();
// Expected actions state according to list of DISABLED_ACTIONS: false for disabled actions
List<Boolean> EXPECTED_ACTIONS_STATE = new ArrayList<>(
Arrays.asList(new Boolean[NUM_SEARCH_ACTIONS])
);
Collections.fill(EXPECTED_ACTIONS_STATE, Boolean.TRUE);
for(int i = 0; i < NUM_SEARCH_ACTIONS; i++) {
CLICK_SEQUENCE.add(i + 1);
}
for(int clickedActionId : CLICK_SEQUENCE) {
EXPECTED_FOCUSED_SEQUENCE.add(clickedActionId);
if (!DISABLED_ACTIONS.contains(clickedActionId - 1))
EXPECTED_CLICKED_SEQUENCE.add(clickedActionId);
else
EXPECTED_CLICKED_SEQUENCE.add(-1);
}
String title = "Guided Actions Enabled Test";
String breadcrumb = "Enabled Test Demo";
String description = "";
GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
breadcrumb, null);
List<GuidedAction> actionList = new ArrayList<>();
actionList.add(new GuidedAction.Builder(mContext)
.id(ACTION_ID_REVERT_BUTTON)
.title(res.getString(R.string.invert_title))
.description(res.getString(R.string.revert_description))
.build()
);
for (int i = 0; i < NUM_SEARCH_ACTIONS; i++ ) {
actionList.add(new GuidedAction.Builder(mContext)
.id(ACTION_ID_SEARCH_END++)
.title(res.getString(R.string.search) + "" + i)
.description(res.getString(R.string.search_description) + i)
.build()
);
}
for(int action_id : DISABLED_ACTIONS ) {
if ( action_id >= 0 && action_id < NUM_SEARCH_ACTIONS ) {
actionList.get(action_id + 1).setEnabled(false);
EXPECTED_ACTIONS_STATE.set(action_id, Boolean.FALSE);
}
}
GuidedStepAttributesTestFragment.clear();
GuidedStepAttributesTestFragment.GUIDANCE = guidance;
GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
GuidedStepAttributesTestFragment.setActionClickCallback(ACTION_ID_REVERT_BUTTON,
sRevertCallback);
initActivity(intent);
examineEnabledAndDisabledActions(actionList, CLICK_SEQUENCE, EXPECTED_FOCUSED_SEQUENCE,
EXPECTED_CLICKED_SEQUENCE);
}
/**
* Toggles Enabled flags in oll the actions of the prior test, and tests whether they are
* correctly reverted.
*/
@Test
public void testToggleEnabledFlags() throws Throwable {
Intent intent = new Intent();
Resources res = mContext.getResources();
final int NUM_SEARCH_ACTIONS = 10;
final List<Integer> DISABLED_ACTIONS = new ArrayList<>(
Arrays.asList(1, 3, 5, 7));
final int ACTION_ID_REVERT_BUTTON = 0;
final int ACTION_ID_SEARCH_BEGIN = ACTION_ID_REVERT_BUTTON + 1;
int ACTION_ID_SEARCH_END = ACTION_ID_SEARCH_BEGIN;
// sequence of clicked actions simulated in the test
List<Integer> CLICK_SEQUENCE = new ArrayList<>();
// Expected Clicked sequence can be different from focused ones since some of the actions
// are disabled hence not clickable
List<Integer> EXPECTED_FOCUSED_SEQUENCE = new ArrayList<>();
List<Integer> EXPECTED_CLICKED_SEQUENCE = new ArrayList<>();
// Expected actions state according to list of DISABLED_ACTIONS: false for disabled actions
List<Boolean> EXPECTED_ACTIONS_STATE = new ArrayList<>(
Arrays.asList(new Boolean[NUM_SEARCH_ACTIONS])
);
Collections.fill(EXPECTED_ACTIONS_STATE, Boolean.FALSE);
for(int i = 0; i < NUM_SEARCH_ACTIONS; i++) {
CLICK_SEQUENCE.add(i + 1);
}
for(int clickedActionId : CLICK_SEQUENCE) {
EXPECTED_FOCUSED_SEQUENCE.add(clickedActionId);
if (DISABLED_ACTIONS.contains(clickedActionId - 1))
EXPECTED_CLICKED_SEQUENCE.add(clickedActionId);
else
EXPECTED_CLICKED_SEQUENCE.add(-1);
}
String title = "Guided Actions Enabled Test";
String breadcrumb = "Toggle Enabled Flag Test Demo";
String description = "";
GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
breadcrumb, null);
List<GuidedAction> actionList = new ArrayList<>();
actionList.add(new GuidedAction.Builder(mContext)
.id(ACTION_ID_REVERT_BUTTON)
.title(res.getString(R.string.invert_title))
.description(res.getString(R.string.revert_description))
.build()
);
for (int i = 0; i < NUM_SEARCH_ACTIONS; i++ ) {
actionList.add(new GuidedAction.Builder(mContext)
.id(ACTION_ID_SEARCH_END++)
.title(res.getString(R.string.search) + "" + i)
.description(res.getString(R.string.search_description) + i)
.build()
);
}
for(int action_id : DISABLED_ACTIONS ) {
if ( action_id >= 0 && action_id < NUM_SEARCH_ACTIONS ) {
actionList.get(action_id + 1).setEnabled(false);
EXPECTED_ACTIONS_STATE.set(action_id, Boolean.TRUE);
}
}
GuidedStepAttributesTestFragment.clear();
GuidedStepAttributesTestFragment.GUIDANCE = guidance;
GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
GuidedStepAttributesTestFragment.setActionClickCallback(ACTION_ID_REVERT_BUTTON,
sRevertCallback);
initActivity(intent);
final GuidedStepFragment mFragment = (GuidedStepFragment)
mActivity.getGuidedStepTestFragment();
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mFragment.setSelectedActionPosition(0);
}
});
Thread.sleep(TRANSITION_LENGTH);
sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
Thread.sleep(TRANSITION_LENGTH);
examineEnabledAndDisabledActions(actionList, CLICK_SEQUENCE, EXPECTED_FOCUSED_SEQUENCE,
EXPECTED_CLICKED_SEQUENCE);
}
private void examineEnabledAndDisabledActions(
List<GuidedAction> actionList, List<Integer> CLICK_SEQUENCE,
List<Integer> EXPECTED_FOCUSED_SEQUENCE,
List<Integer> EXPECTED_CLICKED_SEQUENCE)
throws Throwable {
final GuidedStepFragment mFragment = (GuidedStepFragment)
mActivity.getGuidedStepTestFragment();
for(int i = 0; i < CLICK_SEQUENCE.size(); i++) {
GuidedStepAttributesTestFragment.LAST_SELECTED_ACTION_ID =
GuidedStepAttributesTestFragment.LAST_CLICKED_ACTION_ID = -1;
final int id = CLICK_SEQUENCE.get(i);
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mFragment.setSelectedActionPosition(id);
}
});
Thread.sleep(TRANSITION_LENGTH);
sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
Thread.sleep(TRANSITION_LENGTH);
assertTrue(mContext.getResources().getString(
R.string.enabled_test_wrong_focus_error_message),
GuidedStepAttributesTestFragment.LAST_SELECTED_ACTION_ID
== EXPECTED_FOCUSED_SEQUENCE.get(i)
);
assertTrue(mContext.getResources().getString(
R.string.enabled_test_wrong_click_error_message),
GuidedStepAttributesTestFragment.LAST_CLICKED_ACTION_ID
== EXPECTED_CLICKED_SEQUENCE.get(i)
);
assertTrue(mContext.getResources().getString(
R.string.enabled_test_wrong_flag_error_message),
(GuidedStepAttributesTestFragment.LAST_CLICKED_ACTION_ID == -1)
? !actionList.get(id).isEnabled()
: actionList.get(id).isEnabled()
);
}
}
@Test
public void testCheckedActions() throws Throwable {
Intent intent = new Intent();
Resources res = mContext.getResources();
final int NUM_RADIO_ACTIONS = 3;
final int NUM_CHECK_BOX_ACTIONS = 3;
final int INITIALLY_CHECKED_RADIO_ACTION = 0;
final List<Integer> INITIALLY_CHECKED_CHECKBOX_ACTIONS = new ArrayList<>(
Arrays.asList(1, 2)
);
List<Integer> CLICK_SEQUENCE = new ArrayList<>();
for(int i = 0; i < NUM_RADIO_ACTIONS + NUM_CHECK_BOX_ACTIONS; i++) {
CLICK_SEQUENCE.add(i);
}
List<Boolean> EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK = new ArrayList<>(
Arrays.asList(new Boolean[CLICK_SEQUENCE.size()])
);
Collections.fill(EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK, Boolean.FALSE);
// initial state of actions before any clicks happen
EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK.set(INITIALLY_CHECKED_RADIO_ACTION, true);
for(int checkedCheckBox : INITIALLY_CHECKED_CHECKBOX_ACTIONS) {
EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK.set(NUM_RADIO_ACTIONS + checkedCheckBox, true);
}
String title = "Guided Actions Checked Test";
String breadcrumb = "Checked Test Demo";
String description = "";
GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
breadcrumb, null);
List<GuidedAction> actionList = new ArrayList<>();
actionList.add(new GuidedAction.Builder(mContext)
.title(res.getString(R.string.radio_actions_info_title))
.description(res.getString(R.string.radio_actions_info_desc))
.infoOnly(true)
.enabled(true)
.focusable(false)
.build()
);
int firstRadioActionIndex = actionList.size();
for(int i = 0; i < NUM_RADIO_ACTIONS; i++) {
actionList.add(new GuidedAction.Builder(mContext)
.title(res.getString(R.string.checkbox_title) + i)
.description(res.getString(R.string.checkbox_desc) + i)
.checkSetId(GuidedAction.DEFAULT_CHECK_SET_ID)
.build()
);
if (i == INITIALLY_CHECKED_RADIO_ACTION)
actionList.get(firstRadioActionIndex + i).setChecked(true);
}
actionList.add(new GuidedAction.Builder(mContext)
.title(res.getString(R.string.checkbox_actions_info_title))
.description(res.getString(R.string.checkbox_actions_info_desc))
.infoOnly(true)
.enabled(true)
.focusable(false)
.build()
);
int firstCheckBoxActionIndex = actionList.size();
for(int i = 0; i < NUM_CHECK_BOX_ACTIONS; i++) {
actionList.add(new GuidedAction.Builder(mContext)
.title(res.getString(R.string.checkbox_title) + i)
.description(res.getString(R.string.checkbox_desc) + i)
.checkSetId(GuidedAction.CHECKBOX_CHECK_SET_ID)
.build()
);
}
for(int i = 0; i < INITIALLY_CHECKED_CHECKBOX_ACTIONS.size(); i++ ) {
actionList.get(firstCheckBoxActionIndex + INITIALLY_CHECKED_CHECKBOX_ACTIONS.get(i))
.setChecked(true);
}
GuidedStepAttributesTestFragment.GUIDANCE = guidance;
GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
initActivity(intent);
examineCheckedAndUncheckedActions(actionList, EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK,
NUM_RADIO_ACTIONS, NUM_CHECK_BOX_ACTIONS);
}
private void updateExpectedActionsStateAfterClick(
List<Boolean> EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK, int NUM_RADIO_ACTIONS,
int NUM_CHECK_BOX_ACTIONS, int clickedActionIndex) {
if (clickedActionIndex < NUM_RADIO_ACTIONS) {
for(int i = 0; i < NUM_RADIO_ACTIONS; i++)
EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK.set(i, false);
EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK.set(clickedActionIndex, true);
}
else if (clickedActionIndex < NUM_RADIO_ACTIONS + NUM_CHECK_BOX_ACTIONS) {
EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK.set(clickedActionIndex,
!EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK.get(clickedActionIndex));
}
}
private void verifyIfActionsStateIsCorrect(List<GuidedAction> actionList,
List<Boolean> EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK) {
int actionIndex = 0;
for(GuidedAction checkAction : actionList) {
if (checkAction.infoOnly())
continue;
assertTrue("Action " + actionIndex + " is " + (!checkAction.isChecked() ? "un-" : "")
+ "checked while it shouldn't be!", checkAction.isChecked()
== EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK.get(actionIndex));
actionIndex++;
}
}
private void examineCheckedAndUncheckedActions(List<GuidedAction> actionList,
List<Boolean> EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK,
int NUM_RADIO_ACTIONS,
int NUM_CHECK_BOX_ACTIONS) throws Throwable {
final GuidedStepFragment guidedStepCheckedFragment = (GuidedStepFragment)
mActivity.getGuidedStepTestFragment();
final int firstRadioActionIndex = 1;
final int firstCheckBoxActionIndex = firstRadioActionIndex + NUM_RADIO_ACTIONS + 1;
for(int actionId = 0; actionId < NUM_RADIO_ACTIONS; actionId++) {
final int id = actionId;
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
guidedStepCheckedFragment
.setSelectedActionPosition(firstRadioActionIndex + id);
}
});
Thread.sleep(TRANSITION_LENGTH);
sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
Thread.sleep(TRANSITION_LENGTH);
updateExpectedActionsStateAfterClick(EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK,
NUM_RADIO_ACTIONS, NUM_CHECK_BOX_ACTIONS, actionId);
verifyIfActionsStateIsCorrect(actionList, EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK);
}
for(int actionId = 0; actionId < NUM_CHECK_BOX_ACTIONS; actionId++) {
final int id = actionId;
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
guidedStepCheckedFragment
.setSelectedActionPosition(firstCheckBoxActionIndex + id);
}
});
Thread.sleep(TRANSITION_LENGTH);
sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
Thread.sleep(TRANSITION_LENGTH);
updateExpectedActionsStateAfterClick(EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK,
NUM_RADIO_ACTIONS, NUM_CHECK_BOX_ACTIONS, NUM_RADIO_ACTIONS + actionId);
verifyIfActionsStateIsCorrect(actionList, EXPECTED_ACTIONS_STATE_AFTER_EACH_CLICK);
}
}
@Test
public void testActionWithTwoSubActions() throws Throwable {
ExpectedSubActionResult result = setUpActionsForSubActionsTest();
final int actionPos = 0;
final GuidedAction selectedAction = result.actionList.get(actionPos);
List<Integer> expectedFocusedSeq = result.expectedFocusedSeq.get(actionPos);
List<Integer> expectedClickedSeq = result.expectedClickedSeq.get(actionPos);
traverseSubActionsAndVerifyFocusAndClickEvents(selectedAction, actionPos, expectedFocusedSeq,
expectedClickedSeq);
}
@Test
public void testActionWithOneSubAction() throws Throwable {
ExpectedSubActionResult result = setUpActionsForSubActionsTest();
final int actionPos = 1;
final GuidedAction selectedAction = result.actionList.get(actionPos);
List<Integer> expectedFocusedSeq = result.expectedFocusedSeq.get(actionPos);
List<Integer> expectedClickedSeq = result.expectedClickedSeq.get(actionPos);
traverseSubActionsAndVerifyFocusAndClickEvents(selectedAction, actionPos, expectedFocusedSeq,
expectedClickedSeq);
}
@Test
public void testActionWithZeroSubActions() throws Throwable {
ExpectedSubActionResult result = setUpActionsForSubActionsTest();
final int actionPos = 2;
final GuidedAction selectedAction = result.actionList.get(actionPos);
List<Integer> expectedFocusedSeq = result.expectedFocusedSeq.get(actionPos);
List<Integer> expectedClickedSeq = result.expectedClickedSeq.get(actionPos);
traverseSubActionsAndVerifyFocusAndClickEvents(selectedAction, actionPos, expectedFocusedSeq,
expectedClickedSeq);
}
@Test
public void testActionWithThreeSubActions() throws Throwable {
ExpectedSubActionResult result = setUpActionsForSubActionsTest();
final int actionPos = 3;
final GuidedAction selectedAction = result.actionList.get(actionPos);
List<Integer> expectedFocusedSeq = result.expectedFocusedSeq.get(actionPos);
List<Integer> expectedClickedSeq = result.expectedClickedSeq.get(actionPos);
traverseSubActionsAndVerifyFocusAndClickEvents(selectedAction, actionPos, expectedFocusedSeq,
expectedClickedSeq);
}
/**
* Traverses the list of sub actions of a gudied action. It also verifies the correct action
* or sub action is focused or clicked as the traversal is performed.
* @param selectedAction The action of interest
* @param actionPos The position of selectedAction within the array of guidedactions
* @param expectedFocusedSeq The actual actions IDs used as a reference to verify focused actions
* @param expectedClickedSeq The actual action IDs used as a reference to verify clicked actions
* @throws Throwable
*/
private void traverseSubActionsAndVerifyFocusAndClickEvents(GuidedAction selectedAction,
int actionPos,
List<Integer> expectedFocusedSeq,
List<Integer> expectedClickedSeq)
throws Throwable{
final GuidedStepFragment mFragment =
(GuidedStepFragment) mActivity.getGuidedStepTestFragment();
int focusStep = 0, clickStep = 0;
GuidedStepAttributesTestFragment.LAST_SELECTED_ACTION_ID =
GuidedStepAttributesTestFragment.LAST_CLICKED_ACTION_ID = -1;
final int pos = actionPos;
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mFragment.setSelectedActionPosition(pos);
}
});
Thread.sleep(TRANSITION_LENGTH);
if (mFragment.getSelectedActionPosition() != actionPos) {
assertTrue(mContext.getResources().getString(
R.string.subaction_test_wrong_focus_error_message),
GuidedStepAttributesTestFragment.LAST_SELECTED_ACTION_ID
== expectedFocusedSeq.get(focusStep++)
);
} else {
// If the currently focused position is the same as the position of the action of interest,
// then GuidedStepFragment won't received onGuidedActionFocused callback. Since the first
// element in the expectedFocusSeq is always the id of this action, we need to move focusStep
// one step forward.
focusStep++;
}
if (selectedAction.hasSubActions()) {
// Following for loop clicks on a specific action and scrolls & clicks through
// all its subactions
for (int j = 0; j < selectedAction.getSubActions().size(); j++) {
sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
Thread.sleep(TRANSITION_LENGTH);
assertTrue(mContext.getResources().getString(
R.string.subaction_test_wrong_focus_error_message),
GuidedStepAttributesTestFragment.LAST_SELECTED_ACTION_ID
== expectedFocusedSeq.get(focusStep++)
);
assertTrue(mContext.getResources().getString(
R.string.subaction_test_wrong_click_error_message),
GuidedStepAttributesTestFragment.LAST_CLICKED_ACTION_ID
== expectedClickedSeq.get(clickStep++)
);
for (int k = 0; k < j; k++) {
sendKey(KeyEvent.KEYCODE_DPAD_DOWN);
Thread.sleep(TRANSITION_LENGTH);
assertTrue(mContext.getResources().getString(
R.string.subaction_test_wrong_focus_error_message),
GuidedStepAttributesTestFragment.LAST_SELECTED_ACTION_ID
== expectedFocusedSeq.get(focusStep++)
);
}
sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
Thread.sleep(TRANSITION_LENGTH);
assertTrue(mContext.getResources().getString(
R.string.subaction_test_wrong_focus_error_message),
GuidedStepAttributesTestFragment.LAST_SELECTED_ACTION_ID
== expectedFocusedSeq.get(focusStep++)
);
assertTrue(mContext.getResources().getString(
R.string.subaction_test_wrong_click_error_message),
GuidedStepAttributesTestFragment.LAST_CLICKED_ACTION_ID
== expectedClickedSeq.get(clickStep++)
);
}
} else {
sendKey(KeyEvent.KEYCODE_DPAD_CENTER);
Thread.sleep(TRANSITION_LENGTH);
assertTrue(mContext.getResources().getString(
R.string.subaction_test_wrong_focus_error_message),
GuidedStepAttributesTestFragment.LAST_SELECTED_ACTION_ID
== expectedFocusedSeq.get(focusStep++)
);
assertTrue(mContext.getResources().getString(
R.string.subaction_test_wrong_click_error_message),
GuidedStepAttributesTestFragment.LAST_CLICKED_ACTION_ID
== expectedClickedSeq.get(clickStep++)
);
}
}
static class ExpectedSubActionResult {
List<List<Integer>> expectedFocusedSeq; // Expected sequence of action (or subaction) ids to receive focus events;
// Each entry corresponds to an action item in the guidedactions pane
List<List<Integer>> expectedClickedSeq; // Expected sequence of action (or subaction) ids to receive click events;
// Each entry corresponds to an action item in the guidedactions pane
List<GuidedAction> actionList; // List of GuidedActions in the guidedactions pane
}
/**
* Populates a sample list of actions and subactions in the guidedactions pane.
* @return An object holding the expected sequence of action and subactions IDs that receive
* focus and click events as well as the list of GuidedActions.
*/
private ExpectedSubActionResult setUpActionsForSubActionsTest() {
Intent intent = new Intent();
Resources res = mContext.getResources();
ExpectedSubActionResult result = new ExpectedSubActionResult();
result.expectedFocusedSeq = new ArrayList<>();
result.expectedClickedSeq = new ArrayList<>();
final int NUM_REGULAR_ACTIONS = 4;
final int[] NUM_SUBACTIONS_PER_ACTION = {2, 1, 0, 3};
final int[] REGULAR_ACTIONS_INDEX = new int[NUM_REGULAR_ACTIONS];
final int[] BEGIN_SUBACTION_INDEX_PER_ACTION = new int[NUM_REGULAR_ACTIONS];
final int[] END_SUBACTION_INDEX_PER_ACTION = new int[NUM_REGULAR_ACTIONS];
// Actions and SubActions are assigned unique sequential IDs
int lastIndex = 0;
for(int i = 0; i < NUM_REGULAR_ACTIONS; i++) {
REGULAR_ACTIONS_INDEX[i] = lastIndex;
lastIndex++;
BEGIN_SUBACTION_INDEX_PER_ACTION[i] = lastIndex;
END_SUBACTION_INDEX_PER_ACTION[i] = (lastIndex += NUM_SUBACTIONS_PER_ACTION[i]);
}
for (int i = 0; i < NUM_REGULAR_ACTIONS; i++) {
List<Integer> expectedFocusSeqForEachAction = new ArrayList<>();
List<Integer> expectedClickedSeqForEachAction = new ArrayList<>();
expectedFocusSeqForEachAction.add(REGULAR_ACTIONS_INDEX[i]);
if (NUM_SUBACTIONS_PER_ACTION[i] > 0) {
for (int j = BEGIN_SUBACTION_INDEX_PER_ACTION[i];
j < END_SUBACTION_INDEX_PER_ACTION[i]; j++) {
expectedClickedSeqForEachAction.add(REGULAR_ACTIONS_INDEX[i]);
for (int k = BEGIN_SUBACTION_INDEX_PER_ACTION[i]; k <= j; k++) {
expectedFocusSeqForEachAction.add(k);
}
expectedClickedSeqForEachAction.add(j);
expectedFocusSeqForEachAction.add(REGULAR_ACTIONS_INDEX[i]);
}
} else {
expectedClickedSeqForEachAction.add(REGULAR_ACTIONS_INDEX[i]);
expectedFocusSeqForEachAction.add(REGULAR_ACTIONS_INDEX[i]);
}
result.expectedFocusedSeq.add(expectedFocusSeqForEachAction);
result.expectedClickedSeq.add(expectedClickedSeqForEachAction);
}
String title = "Guided SubActions Test";
String breadcrumb = "SubActions Test Demo";
String description = "";
GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description,
breadcrumb, null);
List<GuidedAction> actionList = new ArrayList<>();
lastIndex = 0;
for (int i = 0; i < NUM_REGULAR_ACTIONS; i++ ) {
GuidedAction action = new GuidedAction.Builder(mContext)
.id(lastIndex++)
.title(res.getString(R.string.dropdown_action_title, i))
.description(res.getString(R.string.dropdown_action_desc, i))
.build();
if (NUM_SUBACTIONS_PER_ACTION[i] > 0) {
List<GuidedAction> subActions = new ArrayList<>();
action.setSubActions(subActions);
for(int j = 0; j < NUM_SUBACTIONS_PER_ACTION[i]; j++) {
subActions.add(new GuidedAction.Builder(mContext)
.id(lastIndex++)
.title(res.getString(R.string.subaction_title, j))
.description("")
.build()
);
}
}
actionList.add(action);
}
result.actionList = actionList;
GuidedStepAttributesTestFragment.clear();
GuidedStepAttributesTestFragment.GUIDANCE = guidance;
GuidedStepAttributesTestFragment.ACTION_LIST = actionList;
initActivity(intent);
return result;
}
}