blob: f7a903027ebe9a04acd83995f4436ab83001455e [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.LoginActivity.ID_USERNAME_CONTAINER;
import static android.autofillservice.cts.activities.PreSimpleSaveActivity.ID_PRE_INPUT;
import static android.autofillservice.cts.activities.SimpleSaveActivity.ID_INPUT;
import static android.autofillservice.cts.activities.SimpleSaveActivity.ID_LABEL;
import static android.autofillservice.cts.testcore.Helper.ID_STATIC_TEXT;
import static android.autofillservice.cts.testcore.Helper.assertTextAndValue;
import static android.autofillservice.cts.testcore.Helper.findAutofillIdByResourceId;
import static android.autofillservice.cts.testcore.Helper.findNodeByResourceId;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_PASSWORD;
import static com.google.common.truth.Truth.assertThat;
import android.autofillservice.cts.R;
import android.autofillservice.cts.activities.LoginActivity;
import android.autofillservice.cts.activities.PreSimpleSaveActivity;
import android.autofillservice.cts.activities.SimpleSaveActivity;
import android.autofillservice.cts.activities.TrampolineWelcomeActivity;
import android.autofillservice.cts.activities.WelcomeActivity;
import android.autofillservice.cts.commontests.CustomDescriptionWithLinkTestCase;
import android.autofillservice.cts.testcore.AutofillActivityTestRule;
import android.autofillservice.cts.testcore.CannedFillResponse;
import android.autofillservice.cts.testcore.InstrumentedAutoFillService.SaveRequest;
import android.autofillservice.cts.testcore.UiBot;
import android.service.autofill.BatchUpdates;
import android.service.autofill.CustomDescription;
import android.service.autofill.RegexValidator;
import android.service.autofill.Validator;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiObject2;
import android.view.View;
import android.view.autofill.AutofillId;
import android.widget.RemoteViews;
import java.util.regex.Pattern;
public class PreSimpleSaveActivityTest
extends CustomDescriptionWithLinkTestCase<PreSimpleSaveActivity> {
private static final AutofillActivityTestRule<PreSimpleSaveActivity> sActivityRule =
new AutofillActivityTestRule<PreSimpleSaveActivity>(PreSimpleSaveActivity.class, false);
public PreSimpleSaveActivityTest() {
super(PreSimpleSaveActivity.class);
}
@Override
protected AutofillActivityTestRule<PreSimpleSaveActivity> getActivityRule() {
return sActivityRule;
}
@Override
protected void saveUiRestoredAfterTappingLinkTest(PostSaveLinkTappedAction type)
throws Exception {
startActivity(false);
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_PRE_INPUT)
.setSaveInfoVisitor((contexts, builder) -> builder
.setCustomDescription(newCustomDescription(WelcomeActivity.class)))
.build());
// Trigger autofill.
mActivity.syncRunOnUiThread(() -> mActivity.mPreInput.requestFocus());
sReplier.getNextFillRequest();
// Trigger save.
mActivity.syncRunOnUiThread(() -> {
mActivity.mPreInput.setText("108");
mActivity.mSubmit.performClick();
});
// Make sure post-save activity is shown...
mUiBot.assertShownByRelativeId(ID_INPUT);
// Tap the link.
final UiObject2 saveUi = assertSaveUiWithLinkIsShown(SAVE_DATA_TYPE_PASSWORD);
tapSaveUiLink(saveUi);
// Make sure new activity is shown...
WelcomeActivity.assertShowingDefaultMessage(mUiBot);
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
// .. then do something to return to previous activity...
switch (type) {
case ROTATE_THEN_TAP_BACK_BUTTON:
mUiBot.setScreenOrientation(UiBot.LANDSCAPE);
WelcomeActivity.assertShowingDefaultMessage(mUiBot);
// not breaking on purpose
case TAP_BACK_BUTTON:
mUiBot.pressBack();
break;
case FINISH_ACTIVITY:
// ..then finishes it.
WelcomeActivity.finishIt();
break;
default:
throw new IllegalArgumentException("invalid type: " + type);
}
// ... and tap save.
final UiObject2 newSaveUi = assertSaveUiWithLinkIsShown(SAVE_DATA_TYPE_PASSWORD);
mUiBot.saveForAutofill(newSaveUi, true);
final SaveRequest saveRequest = sReplier.getNextSaveRequest();
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_PRE_INPUT), "108");
}
@Override
protected void tapLinkThenTapBackThenStartOverTest(PostSaveLinkTappedAction action,
boolean manualRequest) throws Exception {
startActivity(false);
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_PRE_INPUT)
.setSaveInfoVisitor((contexts, builder) -> builder
.setCustomDescription(newCustomDescription(WelcomeActivity.class)))
.build());
// Trigger autofill.
mActivity.syncRunOnUiThread(() -> mActivity.mPreInput.requestFocus());
sReplier.getNextFillRequest();
// Trigger save.
mActivity.syncRunOnUiThread(() -> {
mActivity.mPreInput.setText("108");
mActivity.mSubmit.performClick();
});
// Make sure post-save activity is shown...
mUiBot.assertShownByRelativeId(ID_INPUT);
// Tap the link.
final UiObject2 saveUi = assertSaveUiWithLinkIsShown(SAVE_DATA_TYPE_PASSWORD);
tapSaveUiLink(saveUi);
// Make sure new activity is shown...
WelcomeActivity.assertShowingDefaultMessage(mUiBot);
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
// Tap back to restore the Save UI...
mUiBot.pressBack();
// ...but don't tap it...
final UiObject2 saveUi2 = mUiBot.assertSaveShowing(SAVE_DATA_TYPE_PASSWORD);
// ...instead, do something to dismiss it:
switch (action) {
case TOUCH_OUTSIDE:
mUiBot.assertShownByRelativeId(ID_LABEL).longClick();
break;
case TAP_NO_ON_SAVE_UI:
mUiBot.saveForAutofill(saveUi2, false);
break;
case TAP_YES_ON_SAVE_UI:
mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_PASSWORD);
final SaveRequest saveRequest = sReplier.getNextSaveRequest();
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_PRE_INPUT),
"108");
break;
default:
throw new IllegalArgumentException("invalid action: " + action);
}
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
// Make sure previous session was finished.
// Now triggers a new session in the new activity (SaveActivity) and do business as usual...
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_EMAIL_ADDRESS, ID_INPUT)
.build());
// Trigger autofill.
final SimpleSaveActivity newActivty = SimpleSaveActivity.getInstance();
if (manualRequest) {
newActivty.getAutofillManager().requestAutofill(newActivty.mInput);
} else {
newActivty.syncRunOnUiThread(() -> newActivty.mPassword.requestFocus());
}
sReplier.getNextFillRequest();
// Trigger save.
newActivty.syncRunOnUiThread(() -> {
newActivty.mInput.setText("42");
newActivty.mCommit.performClick();
});
// Make sure post-save activity is shown...
mUiBot.assertShownByRelativeId(ID_INPUT);
// Save it...
mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_EMAIL_ADDRESS);
// ... and assert results
final SaveRequest saveRequest = sReplier.getNextSaveRequest();
assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_INPUT), "42");
}
@Override
protected void saveUiCancelledAfterTappingLinkTest(PostSaveLinkTappedAction type)
throws Exception {
startActivity(false);
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_PRE_INPUT)
.setSaveInfoVisitor((contexts, builder) -> builder
.setCustomDescription(newCustomDescription(WelcomeActivity.class)))
.build());
// Trigger autofill.
mActivity.syncRunOnUiThread(() -> mActivity.mPreInput.requestFocus());
sReplier.getNextFillRequest();
// Trigger save.
mActivity.syncRunOnUiThread(() -> {
mActivity.mPreInput.setText("108");
mActivity.mSubmit.performClick();
});
// Make sure post-save activity is shown...
mUiBot.assertShownByRelativeId(ID_INPUT);
// Tap the link.
final UiObject2 saveUi = assertSaveUiWithLinkIsShown(SAVE_DATA_TYPE_PASSWORD);
tapSaveUiLink(saveUi);
// Make sure linked activity is shown...
WelcomeActivity.assertShowingDefaultMessage(mUiBot);
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
switch (type) {
case LAUNCH_PREVIOUS_ACTIVITY:
startActivityOnNewTask(PreSimpleSaveActivity.class);
mUiBot.assertShownByRelativeId(ID_INPUT);
break;
case LAUNCH_NEW_ACTIVITY:
// Launch a 3rd activity...
startActivityOnNewTask(LoginActivity.class);
mUiBot.assertShownByRelativeId(ID_USERNAME_CONTAINER);
// ...then go back
mUiBot.pressBack();
mUiBot.assertShownByRelativeId(ID_INPUT);
break;
default:
throw new IllegalArgumentException("invalid type: " + type);
}
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
}
@Override
protected void tapLinkLaunchTrampolineActivityThenTapBackAndStartNewSessionTest()
throws Exception {
// Prepare activity.
startActivity(false);
mActivity.mPreInput.getRootView()
.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_PRE_INPUT)
.setSaveInfoVisitor((contexts, builder) -> builder.setCustomDescription(
newCustomDescription(TrampolineWelcomeActivity.class)))
.build());
// Trigger autofill.
mActivity.getAutofillManager().requestAutofill(mActivity.mPreInput);
sReplier.getNextFillRequest();
// Trigger save.
mActivity.syncRunOnUiThread(() -> {
mActivity.mPreInput.setText("108");
mActivity.mSubmit.performClick();
});
final UiObject2 saveUi = assertSaveUiWithLinkIsShown(SAVE_DATA_TYPE_PASSWORD);
// Tap the link.
tapSaveUiLink(saveUi);
// Make sure new activity is shown...
WelcomeActivity.assertShowingDefaultMessage(mUiBot);
// Save UI should be showing as well, since Trampoline finished.
mUiBot.assertSaveShowing(SAVE_DATA_TYPE_PASSWORD);
// Go back and make sure it's showing the right activity.
// first BACK cancels save dialog
mUiBot.pressBack();
// second BACK cancel WelcomeActivity
mUiBot.pressBack();
mUiBot.assertShownByRelativeId(ID_INPUT);
// Now triggers a new session in the new activity (SaveActivity) and do business as usual...
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_EMAIL_ADDRESS, ID_INPUT)
.build());
// Trigger autofill.
final SimpleSaveActivity newActivty = SimpleSaveActivity.getInstance();
newActivty.getAutofillManager().requestAutofill(newActivty.mInput);
sReplier.getNextFillRequest();
// Trigger save.
newActivty.syncRunOnUiThread(() -> {
newActivty.mInput.setText("42");
newActivty.mCommit.performClick();
});
// Make sure post-save activity is shown...
mUiBot.assertShownByRelativeId(ID_INPUT);
// Save it...
mUiBot.saveForAutofill(true, SAVE_DATA_TYPE_EMAIL_ADDRESS);
// ... and assert results
final SaveRequest saveRequest1 = sReplier.getNextSaveRequest();
assertTextAndValue(findNodeByResourceId(saveRequest1.structure, ID_INPUT), "42");
}
@Override
protected void tapLinkAfterUpdateAppliedTest(boolean updateLinkView) throws Exception {
startActivity(false);
// Set service.
enableService();
// Set expectations.
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_PRE_INPUT)
.setSaveInfoVisitor((contexts, builder) -> {
final CustomDescription.Builder customDescription =
newCustomDescriptionBuilder(WelcomeActivity.class);
final RemoteViews update = newTemplate();
if (updateLinkView) {
update.setCharSequence(R.id.link, "setText", "TAP ME IF YOU CAN");
} else {
update.setCharSequence(R.id.static_text, "setText", "ME!");
}
final AutofillId id = findAutofillIdByResourceId(contexts.get(0), ID_PRE_INPUT);
final Validator validCondition = new RegexValidator(id, Pattern.compile(".*"));
customDescription.batchUpdate(validCondition,
new BatchUpdates.Builder().updateTemplate(update).build());
builder.setCustomDescription(customDescription.build());
})
.build());
// Trigger autofill.
mActivity.syncRunOnUiThread(() -> mActivity.mPreInput.requestFocus());
sReplier.getNextFillRequest();
// Trigger save.
mActivity.syncRunOnUiThread(() -> {
mActivity.mPreInput.setText("108");
mActivity.mSubmit.performClick();
});
// Make sure post-save activity is shown...
mUiBot.assertShownByRelativeId(ID_INPUT);
// Tap the link.
final UiObject2 saveUi;
if (updateLinkView) {
saveUi = assertSaveUiWithLinkIsShown(SAVE_DATA_TYPE_PASSWORD, "TAP ME IF YOU CAN");
} else {
saveUi = assertSaveUiWithLinkIsShown(SAVE_DATA_TYPE_PASSWORD);
final UiObject2 changed = saveUi.findObject(By.res(mPackageName, ID_STATIC_TEXT));
assertThat(changed.getText()).isEqualTo("ME!");
}
tapSaveUiLink(saveUi);
// Make sure new activity is shown...
WelcomeActivity.assertShowingDefaultMessage(mUiBot);
mUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_PASSWORD);
}
}