// Copyright 2021 The Chromium Authors
// 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.ui;
import android.view.View;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.CriteriaHelper;
import org.chromium.base.test.util.Restriction;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.layouts.LayoutType;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.R;
import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.ui.test.util.UiRestriction;
import java.util.concurrent.TimeoutException;
/** Tests for MediaCaptureOverlayController. */
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@Batch(Batch.PER_CLASS)
public class MediaCaptureOverlayControllerTest {
@ClassRule
public static final ChromeTabbedActivityTestRule sActivityTestRule =
new ChromeTabbedActivityTestRule();
@Rule
public final BlankCTATabInitialStateRule mInitialStateRule =
new BlankCTATabInitialStateRule(sActivityTestRule, false);
private ChromeTabbedActivity mActivity;
private MediaCaptureOverlayController mController;
private View mOverlayView;
@Before
public void setUp() throws Exception {
mActivity = sActivityTestRule.getActivity();
ThreadUtils.runOnUiThreadBlocking(
() -> {
mController = MediaCaptureOverlayController.from(mActivity.getWindowAndroid());
});
Assert.assertNotNull(mController);
mOverlayView = mActivity.findViewById(R.id.capture_overlay);
}
public Tab openNewTab() {
// Launch a new tab in the foreground.
ChromeTabUtils.newTabFromMenu(InstrumentationRegistry.getInstrumentation(), mActivity);
return mActivity.getActivityTab();
}
public void waitForOverlayVisibility(boolean visible) {
CriteriaHelper.pollUiThread(
() -> {
return visible
? (mOverlayView.getVisibility() == View.VISIBLE)
: (mOverlayView.getVisibility() != View.VISIBLE);
},
"Overlay did not reach desired visibility in the alloted time.");
}
@Test
@SmallTest
@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
public void testSimpleCapture() {
Tab tab = mActivity.getActivityTab();
// Before capture starts the overlay should not be visible.
waitForOverlayVisibility(false);
// Once capture starts the overlay should be visible.
ThreadUtils.runOnUiThreadBlocking(() -> mController.startCapture(tab));
waitForOverlayVisibility(true);
// Once capture stops the overlay should no longer be visible.
ThreadUtils.runOnUiThreadBlocking(() -> mController.stopCapture(tab));
waitForOverlayVisibility(false);
}
@Test
@SmallTest
@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
public void testShowHideWithOverview() throws TimeoutException {
Tab tab = mActivity.getActivityTab();
// Start capturing the tab and assert that the overlay is visible.
ThreadUtils.runOnUiThreadBlocking(() -> mController.startCapture(tab));
waitForOverlayVisibility(true);
// Summon the overview, and assert that the overlay is no longer visible.
TabUiTestHelper.enterTabSwitcher(mActivity);
waitForOverlayVisibility(false);
// Now hide the overview and assert that it becomes visible again.
ThreadUtils.runOnUiThreadBlocking(
() -> mActivity.getLayoutManager().showLayout(LayoutType.BROWSING, false));
waitForOverlayVisibility(true);
}
@Test
@SmallTest
@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
public void testCloseTabStopsOverlay() {
Tab tab = mActivity.getActivityTab();
// Start capturing the tab and assert that the overlay is visible.
ThreadUtils.runOnUiThreadBlocking(() -> mController.startCapture(tab));
waitForOverlayVisibility(true);
// Now close the tab and assert that the overlay disappears.
ChromeTabUtils.closeCurrentTab(InstrumentationRegistry.getInstrumentation(), mActivity);
waitForOverlayVisibility(false);
}
@Test
@SmallTest
@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
public void testSwitchToNonCapturedTab() throws TimeoutException {
Tab firstTab = mActivity.getActivityTab();
// Start capturing the tab and assert that the overlay is visible.
ThreadUtils.runOnUiThreadBlocking(() -> mController.startCapture(firstTab));
waitForOverlayVisibility(true);
// Now open a new tab and assert that the overlay disappears.
Tab secondTab = openNewTab();
waitForOverlayVisibility(false);
}
@Test
@SmallTest
@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
public void testStopOtherCapturedTab() throws TimeoutException {
Tab firstTab = mActivity.getActivityTab();
// Start capturing the tab and assert that the overlay is visible.
ThreadUtils.runOnUiThreadBlocking(() -> mController.startCapture(firstTab));
waitForOverlayVisibility(true);
// Now open a new tab and begin capturing it and assert that the overlay becomes visible.
Tab secondTab = openNewTab();
ThreadUtils.runOnUiThreadBlocking(() -> mController.startCapture(secondTab));
waitForOverlayVisibility(true);
// Stop capturing the non-visible tab, and then assert that the overlay is still visible.
ThreadUtils.runOnUiThreadBlocking(() -> mController.stopCapture(firstTab));
waitForOverlayVisibility(true);
}
}