blob: 1d1568504fcfd78f8e977c5029f5e0f02d14081a [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.touch_to_fill;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.chromium.content_public.browser.test.util.CriteriaHelper.pollUiThread;
import static org.chromium.content_public.browser.test.util.TestThreadUtils.runOnUiThreadBlocking;
import android.annotation.SuppressLint;
import android.support.test.espresso.Espresso;
import android.support.test.filters.MediumTest;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.RetryOnFailure;
import org.chromium.base.test.util.ScalableTimeout;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.touch_to_fill.data.Credential;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetContent;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController.SheetState;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TouchCommon;
import java.util.Arrays;
import java.util.Collections;
/**
* Integration tests for the Touch To Fill component check that the calls to the Touch To Fill API
* end up rendering a View.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@RetryOnFailure
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class TouchToFillIntegrationTest {
private static final String EXAMPLE_URL = "https://www.example.xyz";
private static final String MOBILE_URL = "https://m.example.xyz";
private static final Credential ANA =
new Credential("Ana", "S3cr3t", "Ana", EXAMPLE_URL, false, false);
private static final Credential BOB =
new Credential("Bob", "*****", "Bob", MOBILE_URL, true, false);
private final TouchToFillComponent mTouchToFill = new TouchToFillCoordinator();
@Mock
private TouchToFillComponent.Delegate mMockBridge;
@Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
public TouchToFillIntegrationTest() {
MockitoAnnotations.initMocks(this);
}
@Before
public void setUp() throws InterruptedException {
mActivityTestRule.startMainActivityOnBlankPage();
runOnUiThreadBlocking(() -> {
mTouchToFill.initialize(mActivityTestRule.getActivity(),
mActivityTestRule.getActivity().getBottomSheetController(), mMockBridge);
});
}
@Test
@MediumTest
@DisabledTest(message = "crbug.com/1012221")
public void testClickingSuggestionsTriggersCallback() {
runOnUiThreadBlocking(() -> {
mTouchToFill.showCredentials(EXAMPLE_URL, true, Collections.singletonList(ANA));
});
pollUiThread(() -> getBottomSheetState() == BottomSheetController.SheetState.HALF);
pollUiThread(() -> getCredentials().getChildAt(1) != null);
TouchCommon.singleClickView(getCredentials().getChildAt(1));
waitForEvent(mMockBridge).onCredentialSelected(ANA);
verify(mMockBridge, never()).onDismissed();
}
@Test
@MediumTest
public void testBackDismissesAndCallsCallback() {
runOnUiThreadBlocking(() -> {
mTouchToFill.showCredentials(EXAMPLE_URL, true, Arrays.asList(ANA, BOB));
});
pollUiThread(() -> getBottomSheetState() == BottomSheetController.SheetState.HALF);
Espresso.pressBack();
waitForEvent(mMockBridge).onDismissed();
verify(mMockBridge, never()).onCredentialSelected(any());
}
@Test
@MediumTest
@SuppressLint("SetTextI18n")
public void testDismissedIfUnableToShow() throws Exception {
BottomSheetController bottomSheetController =
mActivityTestRule.getActivity().getBottomSheetController();
BottomSheetContent otherBottomSheetContent = runOnUiThreadBlocking(() -> {
TextView highPriorityBottomSheetContentView =
new TextView(mActivityTestRule.getActivity());
highPriorityBottomSheetContentView.setText("Another bottom sheet content");
BottomSheetContent content = new BottomSheetContent() {
@Override
public View getContentView() {
return highPriorityBottomSheetContentView;
}
@Nullable
@Override
public View getToolbarView() {
return null;
}
@Override
public int getVerticalScrollOffset() {
return 0;
}
@Override
public void destroy() {}
@Override
public int getPriority() {
return ContentPriority.HIGH;
}
@Override
public boolean swipeToDismissEnabled() {
return false;
}
@Override
public int getSheetContentDescriptionStringId() {
return 0;
}
@Override
public int getSheetHalfHeightAccessibilityStringId() {
return 0;
}
@Override
public int getSheetFullHeightAccessibilityStringId() {
return 0;
}
@Override
public int getSheetClosedAccessibilityStringId() {
return 0;
}
};
bottomSheetController.requestShowContent(content, /* animate = */ false);
return content;
});
pollUiThread(() -> getBottomSheetState() == SheetState.PEEK);
Espresso.onView(withText("Another bottom sheet content")).check(matches(isDisplayed()));
runOnUiThreadBlocking(() -> {
mTouchToFill.showCredentials(EXAMPLE_URL, true, Arrays.asList(ANA, BOB));
});
waitForEvent(mMockBridge).onDismissed();
verify(mMockBridge, never()).onCredentialSelected(any());
Espresso.onView(withText("Another bottom sheet content")).check(matches(isDisplayed()));
runOnUiThreadBlocking(() -> {
bottomSheetController.hideContent(otherBottomSheetContent, /* animate = */ false);
});
pollUiThread(() -> getBottomSheetState() == BottomSheetController.SheetState.HIDDEN);
}
private RecyclerView getCredentials() {
return mActivityTestRule.getActivity().findViewById(R.id.sheet_item_list);
}
public static <T> T waitForEvent(T mock) {
return verify(mock,
timeout(ScalableTimeout.scaleTimeout(CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL)));
}
private @SheetState int getBottomSheetState() {
return mActivityTestRule.getActivity().getBottomSheetController().getSheetState();
}
}