blob: a32351a48abf10c1afe7ef66ce0c47482c9455b8 [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;
import static android.autofillservice.cts.common.ShellHelper.runShellCommand;
import static com.google.common.truth.Truth.assertThat;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.service.autofill.CustomDescription;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiObject2;
import android.util.Log;
import android.widget.RemoteViews;
import static org.junit.Assume.assumeTrue;
import org.junit.Test;
/**
* Template for tests cases that test what happens when a link in the {@link CustomDescription} is
* tapped by the user.
*
* <p>It must be extend by 2 sub-class to provide tests for the 2 distinct scenarios:
* <ul>
* <li>Save is triggered by 1st activity finishing and launching a 2nd activity.
* <li>Save is triggered by explicit {@link android.view.autofill.AutofillManager#commit()} call
* and shown in the same activity.
* </ul>
*
* <p>The overall behavior should be the same in both cases, although the implementation of the
* tests per se will be sligthly different.
*/
abstract class CustomDescriptionWithLinkTestCase extends AutoFillServiceTestCase {
private static final String TAG = "CustomDescriptionWithLinkTestCase";
private static final String ID_LINK = "link";
/**
* Tests scenarios when user taps a link in the custom description and then taps back:
* the Save UI should have been restored.
*/
@Test
public final void testTapLink_tapBack() throws Exception {
saveUiRestoredAfterTappingLinkTest(PostSaveLinkTappedAction.TAP_BACK_BUTTON);
}
/**
* Tests scenarios when user taps a link in the custom description, change the screen
* orientation while the new activity is show, then taps back:
* the Save UI should have been restored.
*/
@Test
public final void testTapLink_changeOrientationThenTapBack() throws Exception {
assumeTrue("Rotation is supported", Helper.isRotationSupported(mContext));
final int width = mUiBot.getDevice().getDisplayWidth();
final int heigth = mUiBot.getDevice().getDisplayHeight();
final int min = Math.min(width, heigth);
assumeTrue("Screen size is too small (" + width + "x" + heigth + ")", min >= 500);
Log.d(TAG, "testTapLink_changeOrientationThenTapBack(): screen size is "
+ width + "x" + heigth);
mUiBot.setScreenOrientation(UiBot.PORTRAIT);
try {
runShellCommand("wm size 1080x1920");
runShellCommand("wm density 320");
saveUiRestoredAfterTappingLinkTest(
PostSaveLinkTappedAction.ROTATE_THEN_TAP_BACK_BUTTON);
} finally {
mUiBot.setScreenOrientation(UiBot.PORTRAIT);
try {
cleanUpAfterScreenOrientationIsBackToPortrait();
} finally {
runShellCommand("wm density reset");
runShellCommand("wm size reset");
}
}
}
/**
* Tests scenarios when user taps a link in the custom description, then the new activity
* finishes:
* the Save UI should have been restored.
*/
@Test
public final void testTapLink_finishActivity() throws Exception {
saveUiRestoredAfterTappingLinkTest(PostSaveLinkTappedAction.FINISH_ACTIVITY);
}
protected abstract void saveUiRestoredAfterTappingLinkTest(PostSaveLinkTappedAction type)
throws Exception;
protected void cleanUpAfterScreenOrientationIsBackToPortrait() throws Exception {
}
/**
* Tests scenarios when user taps a link in the custom description, taps back to return to the
* activity with the Save UI, and touch outside the Save UI to dismiss it.
*
* <p>Then user starts a new session by focusing in a field.
*/
@Test
public final void testTapLink_tapBack_thenStartOverByTouchOutsideAndFocus()
throws Exception {
tapLinkThenTapBackThenStartOverTest(PostSaveLinkTappedAction.TOUCH_OUTSIDE, false);
}
/**
* Tests scenarios when user taps a link in the custom description, taps back to return to the
* activity with the Save UI, and touch outside the Save UI to dismiss it.
*
* <p>Then user starts a new session by forcing autofill.
*/
@Test
public void testTapLink_tapBack_thenStartOverByTouchOutsideAndManualRequest()
throws Exception {
tapLinkThenTapBackThenStartOverTest(PostSaveLinkTappedAction.TOUCH_OUTSIDE, true);
}
/**
* Tests scenarios when user taps a link in the custom description, taps back to return to the
* activity with the Save UI, and tap the "No" button to dismiss it.
*
* <p>Then user starts a new session by focusing in a field.
*/
@Test
public final void testTapLink_tapBack_thenStartOverBySayingNoAndFocus()
throws Exception {
tapLinkThenTapBackThenStartOverTest(PostSaveLinkTappedAction.TAP_NO_ON_SAVE_UI,
false);
}
/**
* Tests scenarios when user taps a link in the custom description, taps back to return to the
* activity with the Save UI, and tap the "No" button to dismiss it.
*
* <p>Then user starts a new session by forcing autofill.
*/
@Test
public final void testTapLink_tapBack_thenStartOverBySayingNoAndManualRequest()
throws Exception {
tapLinkThenTapBackThenStartOverTest(PostSaveLinkTappedAction.TAP_NO_ON_SAVE_UI, true);
}
/**
* Tests scenarios when user taps a link in the custom description, taps back to return to the
* activity with the Save UI, and the "Yes" button to save it.
*
* <p>Then user starts a new session by focusing in a field.
*/
@Test
public final void testTapLink_tapBack_thenStartOverBySayingYesAndFocus()
throws Exception {
tapLinkThenTapBackThenStartOverTest(PostSaveLinkTappedAction.TAP_YES_ON_SAVE_UI,
false);
}
/**
* Tests scenarios when user taps a link in the custom description, taps back to return to the
* activity with the Save UI, and the "Yes" button to save it.
*
* <p>Then user starts a new session by forcing autofill.
*/
@Test
public final void testTapLink_tapBack_thenStartOverBySayingYesAndManualRequest()
throws Exception {
tapLinkThenTapBackThenStartOverTest(PostSaveLinkTappedAction.TAP_YES_ON_SAVE_UI, true);
}
protected abstract void tapLinkThenTapBackThenStartOverTest(
PostSaveLinkTappedAction action, boolean manualRequest) throws Exception;
/**
* Tests scenarios when user taps a link in the custom description, then re-launches the
* original activity:
* the Save UI should have been canceled.
*/
@Test
public final void testTapLink_backToPreviousActivityByLaunchingIt()
throws Exception {
saveUiCancelledAfterTappingLinkTest(PostSaveLinkTappedAction.LAUNCH_PREVIOUS_ACTIVITY);
}
/**
* Tests scenarios when user taps a link in the custom description, then launches a 3rd
* activity:
* the Save UI should have been canceled.
*/
@Test
public final void testTapLink_launchNewActivityThenTapBack() throws Exception {
saveUiCancelledAfterTappingLinkTest(PostSaveLinkTappedAction.LAUNCH_NEW_ACTIVITY);
}
protected abstract void saveUiCancelledAfterTappingLinkTest(PostSaveLinkTappedAction type)
throws Exception;
@Test
public final void testTapLink_launchTrampolineActivityThenTapBackAndStartNewSession()
throws Exception {
tapLinkLaunchTrampolineActivityThenTapBackAndStartNewSessionTest();
}
protected abstract void tapLinkLaunchTrampolineActivityThenTapBackAndStartNewSessionTest()
throws Exception;
@Test
public final void testTapLinkAfterUpdateAppliedToLinkView() throws Exception {
tapLinkAfterUpdateAppliedTest(true);
}
@Test
public final void testTapLinkAfterUpdateAppliedToAnotherView() throws Exception {
tapLinkAfterUpdateAppliedTest(false);
}
protected abstract void tapLinkAfterUpdateAppliedTest(boolean updateLinkView) throws Exception;
enum PostSaveLinkTappedAction {
TAP_BACK_BUTTON,
ROTATE_THEN_TAP_BACK_BUTTON,
FINISH_ACTIVITY,
LAUNCH_NEW_ACTIVITY,
LAUNCH_PREVIOUS_ACTIVITY,
TOUCH_OUTSIDE,
TAP_NO_ON_SAVE_UI,
TAP_YES_ON_SAVE_UI
}
protected final void startActivityOnNewTask(Class<?> clazz) {
final Intent intent = new Intent(mContext, clazz);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
protected RemoteViews newTemplate() {
final RemoteViews presentation = new RemoteViews(mPackageName,
R.layout.custom_description_with_link);
return presentation;
}
protected final CustomDescription.Builder newCustomDescriptionBuilder(
Class<? extends Activity> activityClass) {
final Intent intent = new Intent(mContext, activityClass);
intent.setFlags(Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS | Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
return newCustomDescriptionBuilder(intent);
}
protected final CustomDescription newCustomDescription(
Class<? extends Activity> activityClass) {
return newCustomDescriptionBuilder(activityClass).build();
}
protected final CustomDescription.Builder newCustomDescriptionBuilder(Intent intent) {
final RemoteViews presentation = newTemplate();
final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
presentation.setOnClickPendingIntent(R.id.link, pendingIntent);
return new CustomDescription.Builder(presentation);
}
protected final CustomDescription newCustomDescription(Intent intent) {
return newCustomDescriptionBuilder(intent).build();
}
protected final UiObject2 assertSaveUiWithLinkIsShown(int saveType) throws Exception {
return assertSaveUiWithLinkIsShown(saveType, "DON'T TAP ME!");
}
protected final UiObject2 assertSaveUiWithLinkIsShown(int saveType, String expectedText)
throws Exception {
// First make sure the UI is shown...
final UiObject2 saveUi = mUiBot.assertSaveShowing(saveType);
// Then make sure it does have the custom view with link on it...
final UiObject2 link = getLink(saveUi);
assertThat(link.getText()).isEqualTo(expectedText);
return saveUi;
}
protected final UiObject2 getLink(final UiObject2 container) {
final UiObject2 link = container.findObject(By.res(mPackageName, ID_LINK));
assertThat(link).isNotNull();
return link;
}
protected final void tapSaveUiLink(UiObject2 saveUi) {
getLink(saveUi).click();
}
}