blob: 1e38ae4e7998841dd1f126e5dc8cc424729b51bc [file] [log] [blame]
/*
* Copyright (C) 2017 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 android.autofillservice.cts.saveui;
import static android.autofillservice.cts.activities.OptionalSaveActivity.ID_ADDRESS1;
import static android.autofillservice.cts.activities.OptionalSaveActivity.ID_ADDRESS2;
import static android.autofillservice.cts.activities.OptionalSaveActivity.ID_CITY;
import static android.autofillservice.cts.activities.OptionalSaveActivity.ID_FAVORITE_COLOR;
import static android.autofillservice.cts.testcore.Helper.assertTextAndValue;
import static android.autofillservice.cts.testcore.Helper.findNodeByResourceId;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_ADDRESS;
import static com.google.common.truth.Truth.assertWithMessage;
import android.app.assist.AssistStructure;
import android.autofillservice.cts.activities.OptionalSaveActivity;
import android.autofillservice.cts.commontests.AutoFillServiceTestCase;
import android.autofillservice.cts.testcore.AutofillActivityTestRule;
import android.autofillservice.cts.testcore.CannedFillResponse;
import android.autofillservice.cts.testcore.CannedFillResponse.CannedDataset;
import android.autofillservice.cts.testcore.InstrumentedAutoFillService.SaveRequest;
import android.autofillservice.cts.testcore.Visitor;
import android.platform.test.annotations.AppModeFull;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.junit.Test;
/**
* Test case for an activity that contains 4 fields, but the service is only interested in 2-3 of
* them for Save:
*
* <ul>
* <li>Address 1: required
* <li>Address 2: required
* <li>City: optional
* <li>Favorite Color: don't care - LOL
* </ul>
*/
@AppModeFull(reason = "Service-specific test")
public class OptionalSaveActivityTest
extends AutoFillServiceTestCase.AutoActivityLaunch<OptionalSaveActivity> {
private static final boolean EXPECT_NO_SAVE_UI = false;
private static final boolean EXPECT_SAVE_UI = true;
private OptionalSaveActivity mActivity;
@Override
protected AutofillActivityTestRule<OptionalSaveActivity> getActivityRule() {
return new AutofillActivityTestRule<OptionalSaveActivity>(OptionalSaveActivity.class) {
@Override
protected void afterActivityLaunched() {
mActivity = getActivity();
}
};
}
/**
* Creates a standard builder common to all tests.
*/
private CannedFillResponse.Builder newResponseBuilder() {
return new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_ADDRESS, ID_ADDRESS1, ID_CITY)
.setOptionalSavableIds(ID_ADDRESS2);
}
@Test
public void testNoAutofillSaveAll() throws Exception {
noAutofillSaveOnChangeTest(() -> {
mActivity.mAddress1.setText("742 Evergreen Terrace"); // required
mActivity.mAddress2.setText("Simpsons House"); // not required
mActivity.mCity.setText("Springfield"); // required
mActivity.mFavoriteColor.setText("Yellow"); // lol
}, (s) -> {
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS1), "742 Evergreen Terrace");
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS2), "Simpsons House");
assertTextAndValue(findNodeByResourceId(s, ID_CITY), "Springfield");
assertTextAndValue(findNodeByResourceId(s, ID_FAVORITE_COLOR), "Yellow");
});
}
@Test
public void testNoAutofillSaveRequiredOnly() throws Exception {
noAutofillSaveOnChangeTest(() -> {
mActivity.mAddress1.setText("742 Evergreen Terrace"); // required
mActivity.mCity.setText("Springfield"); // required
}, (s) -> {
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS1), "742 Evergreen Terrace");
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS2), "");
assertTextAndValue(findNodeByResourceId(s, ID_CITY), "Springfield");
assertTextAndValue(findNodeByResourceId(s, ID_FAVORITE_COLOR), "");
});
}
/**
* Tests the scenario where the service didn't have any data to autofill, and the user filled
* all fields, even the favorite color (LOL).
*/
private void noAutofillSaveOnChangeTest(Runnable changes, Visitor<AssistStructure> assertions)
throws Exception {
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(newResponseBuilder().build());
// Trigger auto-fill.
mActivity.syncRunOnUiThread(() -> mActivity.mAddress1.requestFocus());
// Validation check.
mUiBot.assertNoDatasetsEver();
// Wait for onFill() before proceeding, otherwise the fields might be changed before
// the session started.
sReplier.getNextFillRequest();
// Manually fill fields...
mActivity.syncRunOnUiThread(changes);
// ...then tap save.
mActivity.save();
// Assert the snack bar is shown and tap "Save".
mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_ADDRESS);
final SaveRequest saveRequest = sReplier.getNextSaveRequest();
assertWithMessage("onSave() not called").that(saveRequest).isNotNull();
// Assert value of fields
assertions.visit(saveRequest.structure);
}
@Test
public void testNoAutofillFirstRequiredFieldMissing() throws Exception {
noAutofillNoChangeNoSaveTest(() -> {
// address1 is missing
mActivity.mAddress2.setText("Simpsons House"); // not required
mActivity.mCity.setText("Springfield"); // required
mActivity.mFavoriteColor.setText("Yellow"); // lol
});
}
@Test
public void testNoAutofillSecondRequiredFieldMissing() throws Exception {
noAutofillNoChangeNoSaveTest(() -> {
mActivity.mAddress1.setText("742 Evergreen Terrace"); // required
mActivity.mAddress2.setText("Simpsons House"); // not required
// city is missing
mActivity.mFavoriteColor.setText("Yellow"); // lol
});
}
/**
* Tests the scenario where the service didn't have any data to autofill, and the user filled
* didn't fill all required changes.
*/
private void noAutofillNoChangeNoSaveTest(Runnable changes) throws Exception {
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(newResponseBuilder().build());
// Trigger auto-fill.
mActivity.syncRunOnUiThread(() -> mActivity.mAddress1.requestFocus());
// Validation check.
mUiBot.assertNoDatasetsEver();
// Wait for onFill() before proceeding, otherwise the fields might be changed before
// the session started.
sReplier.getNextFillRequest();
// Manually fill fields...
mActivity.syncRunOnUiThread(changes);
// ...then tap save.
mActivity.save();
// Assert the snack bar is shown and tap "Save".
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_ADDRESS);
}
@Test
public void testAutofillAllChangedAllSaveAll() throws Exception {
mActivity.expectAutoFill("Shelbyville Nuclear Power Plant", "Shelbyville Bluffs",
"Shelbyville", "Lemon");
autofillAndSaveOnChangeTest(new CannedDataset.Builder()
// Initial dataset
.setField(ID_ADDRESS1, "Shelbyville Nuclear Power Plant")
.setField(ID_ADDRESS2, "Shelbyville Bluffs")
.setField(ID_CITY, "Shelbyville")
.setField(ID_FAVORITE_COLOR, "Lemon"),
// Changes
() -> {
mActivity.mAddress1.setText("742 Evergreen Terrace"); // required
mActivity.mAddress2.setText("Simpsons House"); // not required
mActivity.mCity.setText("Springfield"); // required
mActivity.mFavoriteColor.setText("Yellow"); // lol
}, (s) -> {
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS1),
"742 Evergreen Terrace");
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS2), "Simpsons House");
assertTextAndValue(findNodeByResourceId(s, ID_CITY), "Springfield");
assertTextAndValue(findNodeByResourceId(s, ID_FAVORITE_COLOR), "Yellow");
});
}
@Test
public void testAutofillAllChangedFirstRequiredSaveAll() throws Exception {
mActivity.expectAutoFill("Shelbyville Nuclear Power Plant", "Shelbyville Bluffs",
"Shelbyville", "Lemon");
autofillAndSaveOnChangeTest(new CannedDataset.Builder()
// Initial dataset
.setField(ID_ADDRESS1, "Shelbyville Nuclear Power Plant")
.setField(ID_ADDRESS2, "Shelbyville Bluffs")
.setField(ID_CITY, "Shelbyville")
.setField(ID_FAVORITE_COLOR, "Lemon"),
// Changes
() -> {
mActivity.mAddress1.setText("742 Evergreen Terrace"); // required
},
// Final state
(s) -> {
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS1),
"742 Evergreen Terrace");
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS2), "Shelbyville Bluffs");
assertTextAndValue(findNodeByResourceId(s, ID_CITY), "Shelbyville");
assertTextAndValue(findNodeByResourceId(s, ID_FAVORITE_COLOR), "Lemon");
});
}
@Test
public void testAutofillAllChangedSecondRequiredSaveAll() throws Exception {
mActivity.expectAutoFill("Shelbyville Nuclear Power Plant", "Shelbyville Bluffs",
"Shelbyville", "Lemon");
autofillAndSaveOnChangeTest(new CannedDataset.Builder()
// Initial dataset
.setField(ID_ADDRESS1, "Shelbyville Nuclear Power Plant")
.setField(ID_ADDRESS2, "Shelbyville Bluffs")
.setField(ID_CITY, "Shelbyville")
.setField(ID_FAVORITE_COLOR, "Lemon"),
// Changes
() -> {
mActivity.mCity.setText("Springfield"); // required
},
// Final state
(s) -> {
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS1),
"Shelbyville Nuclear Power Plant");
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS2), "Shelbyville Bluffs");
assertTextAndValue(findNodeByResourceId(s, ID_CITY), "Springfield");
assertTextAndValue(findNodeByResourceId(s, ID_FAVORITE_COLOR), "Lemon");
});
}
@Test
public void testAutofillAllChangedOptionalSaveAll() throws Exception {
mActivity.expectAutoFill("Shelbyville Nuclear Power Plant", "Shelbyville Bluffs",
"Shelbyville", "Lemon");
autofillAndSaveOnChangeTest(new CannedDataset.Builder()
// Initial dataset
.setField(ID_ADDRESS1, "Shelbyville Nuclear Power Plant")
.setField(ID_ADDRESS2, "Shelbyville Bluffs")
.setField(ID_CITY, "Shelbyville")
.setField(ID_FAVORITE_COLOR, "Lemon"),
// Changes
() -> {
mActivity.mAddress2.setText("Simpsons House"); // not required
},
// Final state
(s) -> {
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS1),
"Shelbyville Nuclear Power Plant");
assertTextAndValue(findNodeByResourceId(s, ID_ADDRESS2), "Simpsons House");
assertTextAndValue(findNodeByResourceId(s, ID_CITY), "Shelbyville");
assertTextAndValue(findNodeByResourceId(s, ID_FAVORITE_COLOR), "Lemon");
});
}
/**
* Tests the scenario where the service autofilled the activity but the user changed fields
* that triggered Save.
*/
private void autofillAndSaveOnChangeTest(CannedDataset.Builder dataset, Runnable changes,
Visitor<AssistStructure> assertions) throws Exception {
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(newResponseBuilder()
.addDataset(dataset.setPresentation(createPresentation("Da Dataset")).build())
.build());
// Trigger auto-fill.
mActivity.syncRunOnUiThread(() -> {
mActivity.mAddress1.requestFocus();
});
// Wait for onFill() before proceeding, otherwise the fields might be changed before
// the session started.
sReplier.getNextFillRequest();
// Auto-fill it.
mUiBot.selectDataset("Da Dataset");
// Check the results.
mActivity.assertAutoFilled();
// Manually fill fields...
mActivity.syncRunOnUiThread(changes);
// ...then tap save.
mActivity.save();
// Assert the snack bar is shown and tap "Save".
mUiBot.updateForAutofill(true, SAVE_DATA_TYPE_ADDRESS);
final SaveRequest saveRequest = sReplier.getNextSaveRequest();
assertWithMessage("onSave() not called").that(saveRequest).isNotNull();
// Assert value of fields
assertions.visit(saveRequest.structure);
}
@Test
public void testAutofillAllChangedIgnored() throws Exception {
mActivity.expectAutoFill("Shelbyville Nuclear Power Plant", "Shelbyville Bluffs",
"Shelbyville", "Lemon");
autofillNoChangeNoSaveTest(new CannedDataset.Builder()
.setField(ID_ADDRESS1, "Shelbyville Nuclear Power Plant")
.setField(ID_ADDRESS2, "Shelbyville Bluffs")
.setField(ID_CITY, "Shelbyville")
.setField(ID_FAVORITE_COLOR, "Lemon"), () -> {
mActivity.mFavoriteColor.setText("Yellow"); // lol
});
}
@Test
public void testAutofillAllFirstRequiredChangedToEmpty() throws Exception {
mActivity.expectAutoFill("Shelbyville Nuclear Power Plant", "Shelbyville Bluffs",
"Shelbyville", "Lemon");
autofillNoChangeNoSaveTest(new CannedDataset.Builder()
.setField(ID_ADDRESS1, "Shelbyville Nuclear Power Plant")
.setField(ID_ADDRESS2, "Shelbyville Bluffs")
.setField(ID_CITY, "Shelbyville")
.setField(ID_FAVORITE_COLOR, "Lemon"), () -> {
mActivity.mAddress1.setText("");
});
}
@Test
public void testAutofillAllSecondRequiredChangedToNull() throws Exception {
mActivity.expectAutoFill("Shelbyville Nuclear Power Plant", "Shelbyville Bluffs",
"Shelbyville", "Lemon");
autofillNoChangeNoSaveTest(new CannedDataset.Builder()
.setField(ID_ADDRESS1, "Shelbyville Nuclear Power Plant")
.setField(ID_ADDRESS2, "Shelbyville Bluffs")
.setField(ID_CITY, "Shelbyville")
.setField(ID_FAVORITE_COLOR, "Lemon"), () -> {
mActivity.mCity.setText(null);
});
}
@Test
public void testAutofillAllFirstRequiredChangedBackToInitialState() throws Exception {
mActivity.expectAutoFill("Shelbyville Nuclear Power Plant", "Shelbyville Bluffs",
"Shelbyville", "Lemon");
autofillNoChangeNoSaveTest(new CannedDataset.Builder()
.setField(ID_ADDRESS1, "Shelbyville Nuclear Power Plant")
.setField(ID_ADDRESS2, "Shelbyville Bluffs")
.setField(ID_CITY, "Shelbyville")
.setField(ID_FAVORITE_COLOR, "Lemon"), () -> {
mActivity.mAddress1.setText("I'm different");
mActivity.mAddress1.setText("Shelbyville Nuclear Power Plant");
});
}
/**
* Tests the scenario where the service autofilled the activity and the user changed fields,
* but it did not triggered Save.
*/
private void autofillNoChangeNoSaveTest(CannedDataset.Builder dataset, Runnable changes)
throws Exception {
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(newResponseBuilder()
.addDataset(dataset.setPresentation(createPresentation("Da Dataset")).build())
.build());
// Trigger auto-fill.
mActivity.syncRunOnUiThread(() -> mActivity.mAddress1.requestFocus());
// Wait for onFill() before proceeding, otherwise the fields might be changed before
// the session started.
sReplier.getNextFillRequest();
// Auto-fill it.
mUiBot.selectDataset("Da Dataset");
// Check the results.
mActivity.assertAutoFilled();
// Manually fill fields...
mActivity.syncRunOnUiThread(changes);
// ...then tap save.
mActivity.save();
// Assert the snack bar is not shown.
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_ADDRESS);
}
@Test
public void testDontShowSaveUiWhenUserManuallyFilledSameValue_oneDatasetAllRequiredFields()
throws Exception {
saveWhenUserFilledDatasetFields(
new String[] {ID_ADDRESS1, ID_ADDRESS2},
null,
() -> {
mActivity.mAddress1.setText("742 Evergreen Terrace");
mActivity.mAddress2.setText("Simpsons House");
},
EXPECT_NO_SAVE_UI,
new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_ADDRESS2, "Simpsons House")
.build()
);
}
@Test
public void testDontShowSaveUiWhenManuallyFilledSameValue_oneDatasetRequiredAndOptionalFields()
throws Exception {
saveWhenUserFilledDatasetFields(
new String[]{ID_ADDRESS1},
new String[]{ID_ADDRESS2},
() -> {
mActivity.mAddress1.setText("742 Evergreen Terrace");
mActivity.mAddress2.setText("Simpsons House");
},
EXPECT_NO_SAVE_UI,
new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_ADDRESS2, "Simpsons House")
.build()
);
}
@Test
public void testDontShowSaveUiWhenUserManuallyFilledSameValue_multipleDatasetsDataOnFirst()
throws Exception {
saveWhenUserFilledDatasetFields(
new String[] {ID_ADDRESS1},
new String[] {ID_ADDRESS2},
() -> {
mActivity.mAddress1.setText("742 Evergreen Terrace");
mActivity.mAddress2.setText("Simpsons House");
},
EXPECT_NO_SAVE_UI,
new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_ADDRESS2, "Simpsons House")
.build(),
new CannedDataset.Builder()
.setPresentation(createPresentation("SV"))
.setField(ID_ADDRESS1, "Shelbyville Nuclear Power Plant")
.setField(ID_ADDRESS2, "Shelbyville Bluffs")
.build()
);
}
@Test
public void testDontShowSaveUiWhenUserManuallyFilledSameValue_multipleDatasetsDataOnSecond()
throws Exception {
saveWhenUserFilledDatasetFields(
new String[] {ID_ADDRESS1},
new String[] {ID_ADDRESS2},
() -> {
mActivity.mAddress1.setText("Shelbyville Nuclear Power Plant");
mActivity.mAddress2.setText("Shelbyville Bluffs");
},
EXPECT_NO_SAVE_UI,
new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_ADDRESS2, "Simpsons House")
.build(),
new CannedDataset.Builder()
.setPresentation(createPresentation("SV"))
.setField(ID_ADDRESS1, "Shelbyville Nuclear Power Plant")
.setField(ID_ADDRESS2, "Shelbyville Bluffs")
.build()
);
}
@Test
public void testDontShowSaveUiWhenUserManuallyFilledSameValue_requiredOnly()
throws Exception {
saveWhenUserFilledDatasetFields(
new String[] {ID_ADDRESS1},
new String[] {ID_ADDRESS2},
() -> {
mActivity.mAddress1.setText("742 Evergreen Terrace");
},
EXPECT_NO_SAVE_UI,
new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_ADDRESS2, "Simpsons House")
.build()
);
}
@Test
public void testDontShowSaveUiWhenUserManuallyFilledSameValue_optionalOnly()
throws Exception {
saveWhenUserFilledDatasetFields(
new String[] {ID_ADDRESS1},
new String[] {ID_ADDRESS2},
() -> {
mActivity.mAddress2.setText("Simpsons House");
},
EXPECT_NO_SAVE_UI,
new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_ADDRESS2, "Simpsons House")
.build()
);
}
@Test
public void testDontShowSaveUiWhenUserManuallyFilledSameValue_optionalsOnlyNoRequired()
throws Exception {
saveWhenUserFilledDatasetFields(
null,
new String[] {ID_ADDRESS2, ID_CITY},
() -> {
mActivity.mCity.setText("Springfield");
},
EXPECT_NO_SAVE_UI,
new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_ADDRESS2, "Simpsons House")
.setField(ID_CITY, "Springfield")
.build()
);
}
@Test
public void testShowSaveUiWhenUserManuallyFilledDifferentValue_requiredOnly()
throws Exception {
saveWhenUserFilledDatasetFields(
new String[] {ID_ADDRESS1},
new String[] {ID_ADDRESS2},
() -> {
mActivity.mAddress1.setText("Shelbyville Nuclear Power Plant");
},
EXPECT_SAVE_UI,
new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_ADDRESS2, "Simpsons House")
.build()
);
}
@Test
public void testShowSaveUiWhenUserManuallyFilledDifferentValue_optionalOnly()
throws Exception {
saveWhenUserFilledDatasetFields(
null,
new String[] {ID_ADDRESS2},
() -> {
mActivity.mAddress2.setText("Shelbyville Bluffs");
},
EXPECT_SAVE_UI,
new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_ADDRESS2, "Simpsons House")
.build()
);
}
private void saveWhenUserFilledDatasetFields(@Nullable String[] requiredIds,
@Nullable String[] optionalIds, @NonNull Runnable changes, boolean expectSaveUi,
@NonNull CannedDataset...datasets) throws Exception {
// Set service.
enableService();
// Set expectations.
final CannedFillResponse.Builder response = new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_ADDRESS, requiredIds);
if (optionalIds != null) {
response.setOptionalSavableIds(optionalIds);
}
for (CannedDataset dataset : datasets) {
response.addDataset(dataset);
}
sReplier.addResponse(response.build());
// Trigger auto-fill.
mActivity.syncRunOnUiThread(() -> mActivity.mAddress1.requestFocus());
sReplier.getNextFillRequest();
// Manually fill it.
mActivity.syncRunOnUiThread(changes);
// ...then tap save.
mActivity.save();
// Make sure the snack bar is shown as expected.
if (expectSaveUi) {
mUiBot.assertSaveShowing(SAVE_DATA_TYPE_ADDRESS);
} else {
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_ADDRESS);
}
}
@Test
public void testDontShowSaveUiWhenUserClearedAutofilledFieldThatIsRequired() throws Exception {
// Set service.
enableService();
mActivity.expectAutoFill("742 Evergreen Terrace", "Simpsons House",
"Springfield", "Yellow");
// Set expectations.
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_ADDRESS, ID_ADDRESS1, ID_ADDRESS2)
.setOptionalSavableIds(ID_CITY)
.addDataset(new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_ADDRESS2, "Simpsons House")
.setField(ID_CITY, "Springfield")
.setField(ID_FAVORITE_COLOR, "Yellow")
.build())
.build());
// Trigger autofill.
mActivity.syncRunOnUiThread(() -> mActivity.mAddress1.requestFocus());
sReplier.getNextFillRequest();
mUiBot.selectDataset("SF");
mActivity.assertAutoFilled();
// Clear the field.
mActivity.syncRunOnUiThread(() -> mActivity.mAddress2.setText(""));
// Trigger save...
mActivity.save();
// ...and make sure the snack bar is not shown.
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_ADDRESS);
}
@Test
public void testShowSaveUiWhenUserClearedAutofilledFieldThatIsOptional() throws Exception {
// Set service.
enableService();
mActivity.expectAutoFill("742 Evergreen Terrace", "Simpsons House",
"Springfield", "Yellow");
// Set expectations.
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_ADDRESS, ID_ADDRESS1, ID_ADDRESS2)
.setOptionalSavableIds(ID_CITY)
.addDataset(new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_ADDRESS2, "Simpsons House")
.setField(ID_CITY, "Springfield")
.setField(ID_FAVORITE_COLOR, "Yellow")
.build())
.build());
// Trigger autofill.
mActivity.syncRunOnUiThread(() -> mActivity.mAddress1.requestFocus());
sReplier.getNextFillRequest();
mUiBot.selectDataset("SF");
mActivity.assertAutoFilled();
// Clear the field.
mActivity.syncRunOnUiThread(() -> mActivity.mCity.setText(""));
// Trigger save...
mActivity.save();
// ...and make sure the snack bar is shown.
mUiBot.updateForAutofill(true, SAVE_DATA_TYPE_ADDRESS);
// Finally, assert values.
final SaveRequest saveRequest = sReplier.getNextSaveRequest();
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_ADDRESS1),
"742 Evergreen Terrace");
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_ADDRESS2),
"Simpsons House");
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_CITY), "");
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_FAVORITE_COLOR),
"Yellow");
}
@Test
public void testShowUpdateWhenUserChangedOptionalValueFromDatasetAndRequiredNotFromDataset()
throws Exception {
// Set service.
enableService();
// Address 2 will be required but not available
mActivity.expectAutoFill("742 Evergreen Terrace", null, "Springfield", "Yellow");
// Set expectations.
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_ADDRESS, ID_ADDRESS1, ID_ADDRESS2)
.setOptionalSavableIds(ID_CITY)
.addDataset(new CannedDataset.Builder()
.setPresentation(createPresentation("SF"))
.setField(ID_ADDRESS1, "742 Evergreen Terrace")
.setField(ID_CITY, "Springfield")
.setField(ID_FAVORITE_COLOR, "Yellow")
.build())
.build());
// Trigger autofill.
mActivity.syncRunOnUiThread(() -> mActivity.mAddress1.requestFocus());
sReplier.getNextFillRequest();
mUiBot.selectDataset("SF");
mActivity.assertAutoFilled();
// Change required and optional field.
mActivity.syncRunOnUiThread(() -> {
mActivity.mAddress2.setText("Simpsons House");
mActivity.mCity.setText("Shelbyville");
});
// Trigger save...
mActivity.save();
// ...and make sure the snack bar is shown.
mUiBot.updateForAutofill(true, SAVE_DATA_TYPE_ADDRESS);
// Finally, assert values.
final SaveRequest saveRequest = sReplier.getNextSaveRequest();
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_ADDRESS1),
"742 Evergreen Terrace");
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_ADDRESS2),
"Simpsons House");
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_CITY), "Shelbyville");
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_FAVORITE_COLOR),
"Yellow");
}
}