Commit fb8587a0 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

[Mfill Android] Wrap AccessorySheetTab data by type

This CL adds the new representation for tab data next to the existing
one. This ensures that the old UI still works and the new UI is
completely guarded by #autofill-keyboard-accessory-view.

The actual drawing of the elements follows in crrev.com/c/1356547.

Bug: 853772, 911084
Change-Id: Ia38706aefb687fbe704b62307fa7d793a9b45c36
Reviewed-on: https://chromium-review.googlesource.com/c/1350875
Commit-Queue: Friedrich Horschig [CET] <fhorschig@chromium.org>
Reviewed-by: default avatarIoana Pandele <ioanap@chromium.org>
Cr-Commit-Position: refs/heads/master@{#614338}
parent 028bb840
......@@ -5,6 +5,7 @@
package org.chromium.chrome.browser.autofill.keyboard_accessory;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.CREDENTIALS;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.PASSWORD_SHEET_DATA;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.SCROLL_LISTENER;
import android.content.Context;
......@@ -18,6 +19,7 @@ import android.view.ViewGroup;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item;
import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece;
import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetViewBinder.ItemViewHolder;
import org.chromium.chrome.browser.modelutil.ListModel;
import org.chromium.chrome.browser.modelutil.PropertyModel;
......@@ -29,10 +31,12 @@ import org.chromium.chrome.browser.modelutil.SimpleRecyclerViewMcp;
* as bottom sheet below the keyboard accessory.
*/
public class PasswordAccessorySheetCoordinator implements KeyboardAccessoryData.Tab.Listener {
private final PropertyModel mModel = new PropertyModel.Builder(CREDENTIALS, SCROLL_LISTENER)
.with(CREDENTIALS, new ListModel<>())
.with(SCROLL_LISTENER, null)
.build();
private final PropertyModel mModel =
new PropertyModel.Builder(CREDENTIALS, PASSWORD_SHEET_DATA, SCROLL_LISTENER)
.with(CREDENTIALS, new ListModel<>())
.with(PASSWORD_SHEET_DATA, new ListModel<>())
.with(SCROLL_LISTENER, null)
.build();
private final PasswordAccessorySheetMediator mMediator;
private final KeyboardAccessoryData.Tab mTab;
......@@ -123,7 +127,12 @@ public class PasswordAccessorySheetCoordinator implements KeyboardAccessoryData.
}
@VisibleForTesting
ListModel<Item> getModelForTesting() {
return mMediator.getModelForTesting();
ListModel<Item> getItemsForTesting() {
return mModel.get(CREDENTIALS);
}
@VisibleForTesting
ListModel<AccessorySheetDataPiece> getSheetDataPiecesForTesting() {
return mModel.get(PASSWORD_SHEET_DATA);
}
}
......@@ -5,16 +5,18 @@
package org.chromium.chrome.browser.autofill.keyboard_accessory;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.CREDENTIALS;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.PASSWORD_SHEET_DATA;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.SCROLL_LISTENER;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.FooterCommand;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.UserInfo;
import org.chromium.chrome.browser.modelutil.ListModel;
import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece;
import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.Type;
import org.chromium.chrome.browser.modelutil.PropertyModel;
import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor;
......@@ -32,6 +34,7 @@ class PasswordAccessorySheetMediator implements KeyboardAccessoryData.Observer<A
@Override
public void onItemAvailable(int typeId, AccessorySheetData accessorySheetData) {
mModel.get(CREDENTIALS).set(convertToItems(accessorySheetData));
mModel.get(PASSWORD_SHEET_DATA).set(splitIntoDataPieces(accessorySheetData));
}
PasswordAccessorySheetMediator(
......@@ -58,12 +61,13 @@ class PasswordAccessorySheetMediator implements KeyboardAccessoryData.Observer<A
for (UserInfo.Field field : userInfo.getFields()) {
items.add(Item.createSuggestion(field.getDisplayText(), field.getA11yDescription(),
field.isObfuscated(),
item -> field.triggerSelection(), userInfo.getFaviconProvider()));
field.isSelectable() ? (item -> field.triggerSelection()) : null,
userInfo.getFaviconProvider()));
}
}
if (!accessorySheetData.getFooterCommands().isEmpty()) items.add(Item.createDivider());
for (KeyboardAccessoryData.FooterCommand command : accessorySheetData.getFooterCommands()) {
for (FooterCommand command : accessorySheetData.getFooterCommands()) {
items.add(Item.createOption(
command.getDisplayText(), command.getDisplayText(), (i) -> command.execute()));
}
......@@ -71,8 +75,18 @@ class PasswordAccessorySheetMediator implements KeyboardAccessoryData.Observer<A
return items.toArray(new Item[0]);
}
@VisibleForTesting
ListModel<Item> getModelForTesting() {
return mModel.get(CREDENTIALS);
private AccessorySheetDataPiece[] splitIntoDataPieces(AccessorySheetData accessorySheetData) {
if (accessorySheetData == null) return new AccessorySheetDataPiece[0];
List<AccessorySheetDataPiece> items = new ArrayList<>();
items.add(new AccessorySheetDataPiece(accessorySheetData.getTitle(), Type.TITLE));
for (UserInfo userInfo : accessorySheetData.getUserInfoList()) {
items.add(new AccessorySheetDataPiece(userInfo, Type.PASSWORD_INFO));
}
for (FooterCommand command : accessorySheetData.getFooterCommands()) {
items.add(new AccessorySheetDataPiece(command, Type.FOOTER_COMMAND));
}
return items.toArray(new AccessorySheetDataPiece[0]);
}
}
......@@ -4,12 +4,21 @@
package org.chromium.chrome.browser.autofill.keyboard_accessory;
import static android.support.v7.widget.RecyclerView.OnScrollListener;
import android.support.annotation.IntDef;
import android.support.v7.widget.RecyclerView;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData;
import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetViewBinder.ItemViewHolder;
import org.chromium.chrome.browser.modelutil.ListModel;
import org.chromium.chrome.browser.modelutil.PropertyModel.ReadableObjectPropertyKey;
import org.chromium.chrome.browser.modelutil.PropertyModel.WritableObjectPropertyKey;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
// TODO(crbug.com/902425): Drop the "Password-" as soon as its used for other sheets.
/**
* This class holds properties that are used to build a model for the password accessory sheet
* component. These properties store the state of the {@link PasswordAccessorySheetView} which is
......@@ -20,8 +29,50 @@ import org.chromium.chrome.browser.modelutil.PropertyModel.WritableObjectPropert
class PasswordAccessorySheetProperties {
static final ReadableObjectPropertyKey<ListModel<KeyboardAccessoryData.Item>> CREDENTIALS =
new ReadableObjectPropertyKey<>();
static final WritableObjectPropertyKey<RecyclerView.OnScrollListener> SCROLL_LISTENER =
static final ReadableObjectPropertyKey<ListModel<AccessorySheetDataPiece>> PASSWORD_SHEET_DATA =
new ReadableObjectPropertyKey<>();
static final WritableObjectPropertyKey<OnScrollListener> SCROLL_LISTENER =
new WritableObjectPropertyKey<>();
/**
* The {@link AccessorySheetData} has to be mapped to single items in a {@link RecyclerView}.
* This class allows to wrap the {@link AccessorySheetData} into small chunks that are organized
* in a {@link ListModel}. A specific {@link ItemViewHolder}s is defined for each piece.
*/
static class AccessorySheetDataPiece {
@IntDef({Type.TITLE, Type.PASSWORD_INFO, Type.FOOTER_COMMAND})
@Retention(RetentionPolicy.SOURCE)
public @interface Type {
/**
* An item in title style used to display text. Non-interactive.
*/
int TITLE = 1;
/**
* A section with user credentials.
*/
int PASSWORD_INFO = 2;
/**
* A command at the end of the accessory sheet tab.
*/
int FOOTER_COMMAND = 3;
}
private Object mDataPiece;
private @Type int mType;
AccessorySheetDataPiece(Object dataPiece, @Type int type) {
mDataPiece = dataPiece;
mType = type;
}
public static int getType(AccessorySheetDataPiece accessorySheetDataPiece) {
return accessorySheetDataPiece.mType;
}
public Object getDataPiece() {
return mDataPiece;
}
}
private PasswordAccessorySheetProperties() {}
}
......@@ -13,12 +13,11 @@ import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.core.AllOf.allOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.AccessoryAction.AUTOFILL_SUGGESTION;
......
......@@ -18,6 +18,7 @@ import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.createEmptyCredentials;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.createUserInfo;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.whenDisplayed;
......@@ -128,6 +129,11 @@ public class PasswordAccessoryIntegrationTest {
throws InterruptedException, TimeoutException {
mHelper.loadTestPage(false);
// Focus the field to bring up the accessory.
mHelper.clickPasswordField();
mHelper.waitForKeyboard();
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
AccessorySheetData accessorySheetData = new AccessorySheetData("Passwords");
accessorySheetData.getUserInfoList().add(
createUserInfo("mayapark@gmail.com", "SomeHiddenPassword"));
......@@ -136,11 +142,6 @@ public class PasswordAccessoryIntegrationTest {
"ExtremelyLongPasswordThatUsesQuiteSomeSpaceInTheSheet"));
mHelper.sendCredentials(accessorySheetData);
// Focus the field to bring up the accessory.
mHelper.clickPasswordField();
mHelper.waitForKeyboard();
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
// Check that the provided elements are there.
whenDisplayed(withText("Passwords"));
whenDisplayed(withText("mayapark@gmail.com"));
......@@ -155,6 +156,12 @@ public class PasswordAccessoryIntegrationTest {
throws InterruptedException, TimeoutException {
mHelper.loadTestPage(false);
final AtomicReference<FooterCommand> clicked = new AtomicReference<>();
// Focus the field to bring up the accessory.
mHelper.clickPasswordField();
mHelper.waitForKeyboard();
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
AccessorySheetData accessorySheetData =
new AccessorySheetData("No saved passwords for abc.com");
accessorySheetData.getFooterCommands().add(
......@@ -163,11 +170,6 @@ public class PasswordAccessoryIntegrationTest {
new FooterCommand("Manage passwords...", clicked::set));
mHelper.sendCredentials(accessorySheetData);
// Focus the field to bring up the accessory.
mHelper.clickPasswordField();
mHelper.waitForKeyboard();
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
// Scroll down and click the suggestion.
whenDisplayed(withChild(withText("Suggest strong password...")))
.perform(scrollToPosition(2));
......@@ -185,6 +187,11 @@ public class PasswordAccessoryIntegrationTest {
mHelper.loadTestPage(false);
final AtomicReference<Field> clicked = new AtomicReference<>();
// Focus the field to bring up the accessory.
mHelper.clickPasswordField();
mHelper.waitForKeyboard();
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
AccessorySheetData accessorySheetData = new AccessorySheetData("Passwords");
accessorySheetData.getUserInfoList().add(
createUserInfo("mpark@abc.com", "ShorterPassword", clicked::set));
......@@ -194,11 +201,6 @@ public class PasswordAccessoryIntegrationTest {
createUserInfo("mayapark@gmail.com", "SomeHiddenLongPassword"));
mHelper.sendCredentials(accessorySheetData);
// Focus the field to bring up the accessory.
mHelper.clickPasswordField();
mHelper.waitForKeyboard();
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
// Click the suggestion.
whenDisplayed(withText("mpark@abc.com")).perform(click());
......@@ -216,14 +218,14 @@ public class PasswordAccessoryIntegrationTest {
// Focus the field to bring up the accessory.
mHelper.clickPasswordField();
mHelper.sendCredentials(createEmptyCredentials());
mHelper.waitForKeyboard();
// Click the tab to show the sheet and hide the keyboard.
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
mHelper.waitForKeyboardToDisappear();
whenDisplayed(withId(R.id.keyboard_accessory_sheet));
onView(withText(containsString("No Saved passwords for this site")))
.check(matches(isDisplayed()));
onView(withText(containsString("No Saved passwords"))).check(matches(isDisplayed()));
}
/**
......
......@@ -20,6 +20,8 @@ import static org.mockito.Mockito.when;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.AccessoryAction.GENERATE_PASSWORD_AUTOMATIC;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryProperties.ACTIVE_TAB;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryProperties.TABS;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.Type.PASSWORD_INFO;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.getType;
import static org.chromium.chrome.browser.tab.Tab.INVALID_TAB_ID;
import static org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType.FROM_BROWSER_ACTIONS;
import static org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType.FROM_CLOSE;
......@@ -453,7 +455,7 @@ public class ManualFillingControllerTest {
if (oldState.mPasswordAccessorySheet == null)
return; // Having no password sheet is fine - it would be completely destroyed then.
assertThat(oldState.mPasswordAccessorySheet.getModelForTesting().size(), is(0));
assertThat(oldState.mPasswordAccessorySheet.getItemsForTesting().size(), is(0));
}
@Test
......@@ -641,10 +643,16 @@ public class ManualFillingControllerTest {
}
private String getFirstPassword(ManualFillingMediator mediator) {
assert mediator.getPasswordAccessorySheet() != null;
assert mediator.getPasswordAccessorySheet().getModelForTesting() != null;
assert mediator.getPasswordAccessorySheet().getModelForTesting().size() > 1;
// The 0th item is a divider, the 1st a title, the 2nd a username and 3rd a password.
return mediator.getPasswordAccessorySheet().getModelForTesting().get(3).getCaption();
PasswordAccessorySheetCoordinator passwordSheet = mediator.getPasswordAccessorySheet();
assert passwordSheet != null;
assert passwordSheet.getSheetDataPiecesForTesting() != null;
assert passwordSheet.getSheetDataPiecesForTesting().size() > 1;
assert getType(passwordSheet.getSheetDataPiecesForTesting().get(1)) == PASSWORD_INFO;
// The 1st element is a title, the 2nd the password info.
UserInfo info =
(UserInfo) passwordSheet.getSheetDataPiecesForTesting().get(1).getDataPiece();
// The 1st field is the name, the 2nd the password.
assert info.getFields().size() > 1;
return info.getFields().get(1).getDisplayText();
}
}
......@@ -13,6 +13,11 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.Type.FOOTER_COMMAND;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.Type.PASSWORD_INFO;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.Type.TITLE;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.getType;
import android.support.v7.widget.RecyclerView;
import org.junit.Before;
......@@ -27,7 +32,12 @@ import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.metrics.test.ShadowRecordHistogram;
import org.chromium.base.task.test.CustomShadowAsyncTask;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.FooterCommand;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.PropertyProvider;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.UserInfo;
import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece;
import org.chromium.chrome.browser.modelutil.ListModel;
import org.chromium.chrome.browser.modelutil.ListObservable;
......@@ -44,7 +54,8 @@ public class PasswordAccessorySheetControllerTest {
private ListObservable.ListObserver<Void> mMockItemListObserver;
private PasswordAccessorySheetCoordinator mCoordinator;
private ListModel<Item> mModel;
private ListModel<Item> mItemList;
private ListModel<AccessorySheetDataPiece> mSheetDataPieces;
@Before
public void setUp() {
......@@ -52,7 +63,8 @@ public class PasswordAccessorySheetControllerTest {
MockitoAnnotations.initMocks(this);
mCoordinator = new PasswordAccessorySheetCoordinator(RuntimeEnvironment.application, null);
assertNotNull(mCoordinator);
mModel = mCoordinator.getModelForTesting();
mItemList = mCoordinator.getItemsForTesting();
mSheetDataPieces = mCoordinator.getSheetDataPiecesForTesting();
}
@Test
......@@ -75,37 +87,82 @@ public class PasswordAccessorySheetControllerTest {
@Test
public void testModelNotifiesAboutActionsChangedByProvider() {
final KeyboardAccessoryData
.PropertyProvider<KeyboardAccessoryData.AccessorySheetData> testProvider =
new KeyboardAccessoryData.PropertyProvider<>();
final KeyboardAccessoryData.AccessorySheetData testData =
new KeyboardAccessoryData.AccessorySheetData("Passwords");
final PropertyProvider<AccessorySheetData> testProvider = new PropertyProvider<>();
mModel.addObserver(mMockItemListObserver);
mItemList.addObserver(mMockItemListObserver);
mCoordinator.registerDataProvider(testProvider);
// If the coordinator receives an initial items, the model should report an insertion.
testProvider.notifyObservers(testData);
verify(mMockItemListObserver).onItemRangeInserted(mModel, 0, 2);
assertThat(mModel.size(), is(2));
assertThat(mModel.get(1).getCaption(), is(equalTo("Passwords")));
testProvider.notifyObservers(new AccessorySheetData("Passwords"));
verify(mMockItemListObserver).onItemRangeInserted(mItemList, 0, 2);
assertThat(mItemList.size(), is(2));
assertThat(mItemList.get(1).getCaption(), is(equalTo("Passwords")));
// If the coordinator receives a new set of items, the model should report a change.
testProvider.notifyObservers(testData);
verify(mMockItemListObserver).onItemRangeChanged(mModel, 0, 2, null);
assertThat(mModel.size(), is(2));
assertThat(mModel.get(1).getCaption(), is(equalTo("Passwords")));
testProvider.notifyObservers(new AccessorySheetData("Other Passwords"));
verify(mMockItemListObserver).onItemRangeChanged(mItemList, 0, 2, null);
assertThat(mItemList.size(), is(2));
assertThat(mItemList.get(1).getCaption(), is(equalTo("Other Passwords")));
// If the coordinator receives an empty set of items, the model should report a deletion.
testProvider.notifyObservers(null);
verify(mMockItemListObserver).onItemRangeRemoved(mModel, 0, 2);
assertThat(mModel.size(), is(0));
verify(mMockItemListObserver).onItemRangeRemoved(mItemList, 0, 2);
assertThat(mItemList.size(), is(0));
// There should be no notification if no item are reported repeatedly.
testProvider.notifyObservers(null);
verifyNoMoreInteractions(mMockItemListObserver);
}
@Test
public void testModelNotifiesAboutTabDataChangedByProvider() {
final PropertyProvider<AccessorySheetData> testProvider = new PropertyProvider<>();
mSheetDataPieces.addObserver(mMockItemListObserver);
mCoordinator.registerDataProvider(testProvider);
// If the coordinator receives a set of initial items, the model should report an insertion.
testProvider.notifyObservers(new AccessorySheetData("Passwords"));
verify(mMockItemListObserver).onItemRangeInserted(mSheetDataPieces, 0, 1);
assertThat(mSheetDataPieces.size(), is(1));
// If the coordinator receives a new set of items, the model should report a change.
testProvider.notifyObservers(new AccessorySheetData("Other Passwords"));
verify(mMockItemListObserver).onItemRangeChanged(mSheetDataPieces, 0, 1, null);
assertThat(mSheetDataPieces.size(), is(1));
// If the coordinator receives an empty set of items, the model should report a deletion.
testProvider.notifyObservers(null);
verify(mMockItemListObserver).onItemRangeRemoved(mSheetDataPieces, 0, 1);
assertThat(mSheetDataPieces.size(), is(0));
// There should be no notification if no item are reported repeatedly.
testProvider.notifyObservers(null);
verifyNoMoreInteractions(mMockItemListObserver);
}
@Test
public void testWrapsTabDataToElements() {
final PropertyProvider<AccessorySheetData> testProvider = new PropertyProvider<>();
final AccessorySheetData testData = new AccessorySheetData("Passwords for this site");
testData.getUserInfoList().add(new UserInfo(null));
testData.getUserInfoList().get(0).addField(new UserInfo.Field("Name", "Name", false, null));
testData.getUserInfoList().get(0).addField(
new UserInfo.Field("Password", "Password for Name", true, field -> {}));
testData.getFooterCommands().add(new FooterCommand("Manage passwords", result -> {}));
mCoordinator.registerDataProvider(testProvider);
testProvider.notifyObservers(testData);
assertThat(mSheetDataPieces.size(), is(3));
assertThat(getType(mSheetDataPieces.get(0)), is(TITLE));
assertThat(getType(mSheetDataPieces.get(1)), is(PASSWORD_INFO));
assertThat(getType(mSheetDataPieces.get(2)), is(FOOTER_COMMAND));
assertThat(mSheetDataPieces.get(0).getDataPiece(), is(equalTo("Passwords for this site")));
assertThat(mSheetDataPieces.get(1).getDataPiece(), is(testData.getUserInfoList().get(0)));
assertThat(mSheetDataPieces.get(2).getDataPiece(), is(testData.getFooterCommands().get(0)));
}
@Test
public void testRecordsActionImpressionsWhenShown() {
assertThat(getActionImpressions(AccessoryAction.MANAGE_PASSWORDS), is(0));
......@@ -126,7 +183,7 @@ public class PasswordAccessorySheetControllerTest {
assertThat(getSuggestionsImpressions(AccessoryTabType.ALL, 0), is(0));
// If the tab is shown without interactive item, log "0" samples.
mModel.set(new Item[] {Item.createLabel("No passwords!", ""), Item.createDivider(),
mItemList.set(new Item[] {Item.createLabel("No passwords!", ""), Item.createDivider(),
Item.createOption("Manage all passwords", "", null),
Item.createOption("Generate password", "", null)});
mCoordinator.onTabShown();
......@@ -135,7 +192,7 @@ public class PasswordAccessorySheetControllerTest {
assertThat(getSuggestionsImpressions(AccessoryTabType.ALL, 0), is(1));
// If the tab is shown with X interactive item, record "X" samples.
mModel.set(new Item[] {Item.createLabel("Your passwords", ""),
mItemList.set(new Item[] {Item.createLabel("Your passwords", ""),
Item.createSuggestion("Interactive 1", "", false, (v) -> {}, null),
Item.createSuggestion("Non-interactive 1", "", true, null, null),
Item.createSuggestion("Interactive 2", "", false, (v) -> {}, null),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment