blob: 5e9a94eed5f25a445e9ba131480ab07c51f7d041 [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.tasks.tab_management;
import android.content.res.ColorStateList;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.provider.Settings;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.SmallTest;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.FrameLayout;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.ContextUtils;
import org.chromium.chrome.browser.toolbar.ToolbarColors;
import org.chromium.chrome.browser.widget.ScrimView;
import org.chromium.chrome.tab_ui.R;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ui.DummyUiActivityTestCase;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
import org.chromium.ui.widget.ChromeImageView;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Tests for {@link TabGridPanelViewBinder}.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
public class TabGridPanelViewBinderTest extends DummyUiActivityTestCase {
private static final int CONTENT_TOP_MARGIN = 56;
private PropertyModel mModel;
private PropertyModelChangeProcessor mMCP;
private TabGroupUiToolbarView mToolbarView;
private RecyclerView mContentView;
private TabGridDialogParent mTabGridDialogParent;
private ChromeImageView mRightButton;
private ChromeImageView mLeftButton;
private EditText mTitleTextView;
private View mMainContent;
private ViewGroup mTabGridDialogParentView;
@Override
public void setUpTest() throws Exception {
super.setUpTest();
FrameLayout parentView = new FrameLayout(getActivity());
mContentView = (TabListRecyclerView) LayoutInflater.from(getActivity())
.inflate(R.layout.tab_list_recycler_view_layout, parentView, false);
mContentView.setLayoutManager(new GridLayoutManager(getActivity(), 2));
mToolbarView = (TabGroupUiToolbarView) LayoutInflater.from(getActivity())
.inflate(R.layout.bottom_tab_grid_toolbar, mContentView, false);
mTabGridDialogParent =
new TabGridDialogParent(getActivity(), new FrameLayout(getActivity()));
mTabGridDialogParentView = mTabGridDialogParent.getTabGridDialogParentViewForTesting();
mLeftButton = mToolbarView.findViewById(R.id.toolbar_left_button);
mRightButton = mToolbarView.findViewById(R.id.toolbar_right_button);
mTitleTextView = mToolbarView.findViewById(R.id.title);
mMainContent = mToolbarView.findViewById(R.id.main_content);
mModel = new PropertyModel(TabGridPanelProperties.ALL_KEYS);
mMCP = PropertyModelChangeProcessor.create(mModel,
new TabGridPanelViewBinder.ViewHolder(
mToolbarView, mContentView, mTabGridDialogParent),
TabGridPanelViewBinder::bind);
}
@Test
@SmallTest
@UiThreadTest
public void testSetCollapseClickListener() {
AtomicBoolean leftButtonClicked = new AtomicBoolean();
leftButtonClicked.set(false);
mLeftButton.performClick();
Assert.assertFalse(leftButtonClicked.get());
mModel.set(TabGridPanelProperties.COLLAPSE_CLICK_LISTENER,
(View view) -> leftButtonClicked.set(true));
mLeftButton.performClick();
Assert.assertTrue(leftButtonClicked.get());
}
@Test
@SmallTest
@UiThreadTest
public void testSetAddClickListener() {
AtomicBoolean rightButtonClicked = new AtomicBoolean();
rightButtonClicked.set(false);
mRightButton.performClick();
Assert.assertFalse(rightButtonClicked.get());
mModel.set(TabGridPanelProperties.ADD_CLICK_LISTENER,
(View view) -> rightButtonClicked.set(true));
mRightButton.performClick();
Assert.assertTrue(rightButtonClicked.get());
}
@Test
@SmallTest
@UiThreadTest
public void testSetHeaderTitle() {
String title = "1024 tabs";
Assert.assertNotEquals(title, mTitleTextView.getText());
mModel.set(TabGridPanelProperties.HEADER_TITLE, title);
Assert.assertEquals(title, mTitleTextView.getText().toString());
}
@Test
@SmallTest
@UiThreadTest
public void testContentTopMargin() {
// Since setting content top margin is only used in sheet, we can assume that the parent is
// a FrameLayout here.
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(0, 0);
params.setMargins(0, 0, 0, 0);
mContentView.setLayoutParams(new FrameLayout.LayoutParams(0, 0));
Assert.assertEquals(
0, ((ViewGroup.MarginLayoutParams) mContentView.getLayoutParams()).topMargin);
mModel.set(TabGridPanelProperties.CONTENT_TOP_MARGIN, CONTENT_TOP_MARGIN);
Assert.assertEquals(CONTENT_TOP_MARGIN,
((ViewGroup.MarginLayoutParams) mContentView.getLayoutParams()).topMargin);
}
@Test
@SmallTest
@UiThreadTest
public void testSetPrimaryColor() {
int color = ContextCompat.getColor(getActivity(), R.color.modern_blue_300);
Assert.assertNull(mMainContent.getBackground());
Assert.assertNull(mContentView.getBackground());
mModel.set(TabGridPanelProperties.PRIMARY_COLOR, color);
Assert.assertEquals(color, ((ColorDrawable) mMainContent.getBackground()).getColor());
Assert.assertEquals(color, ((ColorDrawable) mContentView.getBackground()).getColor());
}
@Test
@SmallTest
@UiThreadTest
public void testSetTint() {
ColorStateList tint = ToolbarColors.getThemedToolbarIconTint(getActivity(), true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Assert.assertNotEquals(tint, mLeftButton.getImageTintList());
Assert.assertNotEquals(tint, mRightButton.getImageTintList());
}
Assert.assertNotEquals(tint, mTitleTextView.getTextColors());
mModel.set(TabGridPanelProperties.TINT, tint);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Assert.assertEquals(tint, mLeftButton.getImageTintList());
Assert.assertEquals(tint, mRightButton.getImageTintList());
}
Assert.assertEquals(tint, mTitleTextView.getTextColors());
}
@Test
@SmallTest
@UiThreadTest
public void testSetScrimViewObserver() {
AtomicBoolean scrimViewClicked = new AtomicBoolean();
scrimViewClicked.set(false);
ScrimView.ScrimObserver scrimObserver = new ScrimView.ScrimObserver() {
@Override
public void onScrimClick() {
scrimViewClicked.set(true);
}
@Override
public void onScrimVisibilityChanged(boolean visible) {}
};
mModel.set(TabGridPanelProperties.SCRIMVIEW_OBSERVER, scrimObserver);
// Open the dialog to show the ScrimView.
mModel.set(TabGridPanelProperties.IS_DIALOG_VISIBLE, true);
// ScrimView is inserted at the lowest level of the parent view hierarchy.
View scrimView = mTabGridDialogParentView.getChildAt(0);
Assert.assertTrue(scrimView instanceof ScrimView);
Assert.assertEquals(View.VISIBLE, scrimView.getVisibility());
scrimView.performClick();
Assert.assertTrue(scrimViewClicked.get());
}
@Test
@SmallTest
public void testSetDialogVisibility() {
Assert.assertFalse(mTabGridDialogParent.getPopupWindowForTesting().isShowing());
Assert.assertNull(mTabGridDialogParent.getCurrentDialogAnimatorForTesting());
// Setup basic dialog animation. The dialog show/hide animation is always initialized before
// the visibility of dialog is set.
TestThreadUtils.runOnUiThreadBlocking(
() -> mTabGridDialogParent.setupDialogAnimation(null));
TestThreadUtils.runOnUiThreadBlocking(
() -> mModel.set(TabGridPanelProperties.IS_DIALOG_VISIBLE, true));
if (areAnimatorsEnabled()) {
Assert.assertNotNull(mTabGridDialogParent.getCurrentDialogAnimatorForTesting());
}
Assert.assertTrue(mTabGridDialogParent.getPopupWindowForTesting().isShowing());
CriteriaHelper.pollUiThread(
() -> mTabGridDialogParent.getCurrentDialogAnimatorForTesting() == null);
TestThreadUtils.runOnUiThreadBlocking(
() -> mModel.set(TabGridPanelProperties.IS_DIALOG_VISIBLE, false));
if (areAnimatorsEnabled()) {
Assert.assertNotNull(mTabGridDialogParent.getCurrentDialogAnimatorForTesting());
Assert.assertTrue(mTabGridDialogParent.getPopupWindowForTesting().isShowing());
}
CriteriaHelper.pollUiThread(
() -> mTabGridDialogParent.getCurrentDialogAnimatorForTesting() == null);
Assert.assertFalse(mTabGridDialogParent.getPopupWindowForTesting().isShowing());
}
@Test
@SmallTest
@UiThreadTest
public void testSetAnimationParams() {
// Initially, the show animation set is empty.
Assert.assertEquals(0,
mTabGridDialogParent.getShowDialogAnimationForTesting()
.getChildAnimations()
.size());
// When set with null as animation params, the show animation is set to be basic fade-in
// which contains only one animation in animation set.
mModel.set(TabGridPanelProperties.ANIMATION_PARAMS, null);
Assert.assertEquals(1,
mTabGridDialogParent.getShowDialogAnimationForTesting()
.getChildAnimations()
.size());
// Create a dummy animation param to setup the dialog animation.
Rect rect = new Rect();
View view = new View(getActivity());
TabGridDialogParent.AnimationParams dummyParams =
new TabGridDialogParent.AnimationParams(rect, view);
// When set with a specific animation param, the show animation contains 6 child animations.
mModel.set(TabGridPanelProperties.ANIMATION_PARAMS, dummyParams);
Assert.assertEquals(6,
mTabGridDialogParent.getShowDialogAnimationForTesting()
.getChildAnimations()
.size());
}
@Test
@SmallTest
@UiThreadTest
public void testSetUngroupbarStatus() {
// Default status for ungroup bar is hidden.
Assert.assertEquals(TabGridDialogParent.UngroupBarStatus.HIDE,
mTabGridDialogParent.getUngroupBarStatusForTesting());
mModel.set(TabGridPanelProperties.UNGROUP_BAR_STATUS,
TabGridDialogParent.UngroupBarStatus.SHOW);
Assert.assertEquals(TabGridDialogParent.UngroupBarStatus.SHOW,
mTabGridDialogParent.getUngroupBarStatusForTesting());
mModel.set(TabGridPanelProperties.UNGROUP_BAR_STATUS,
TabGridDialogParent.UngroupBarStatus.HOVERED);
Assert.assertEquals(TabGridDialogParent.UngroupBarStatus.HOVERED,
mTabGridDialogParent.getUngroupBarStatusForTesting());
}
@Test
@SmallTest
@UiThreadTest
public void testSetDialogBackgroundResource() {
int normalResourceId = R.drawable.tab_grid_dialog_background;
int incognitoResourceId = R.drawable.tab_grid_dialog_background_incognito;
// Default setup is in normal mode.
Assert.assertEquals(
normalResourceId, mTabGridDialogParent.getBackgroundDrawableResourceIdForTesting());
mModel.set(TabGridPanelProperties.DIALOG_BACKGROUND_RESOUCE_ID, incognitoResourceId);
Assert.assertEquals(incognitoResourceId,
mTabGridDialogParent.getBackgroundDrawableResourceIdForTesting());
}
@Test
@SmallTest
@UiThreadTest
public void testSetUngroupbarBackgroundColor() {
int normalColorId = R.color.tab_grid_dialog_background_color;
int incognitoColorId = R.color.tab_grid_dialog_background_color_incognito;
// Default setup is in normal mode.
Assert.assertEquals(normalColorId,
mTabGridDialogParent.getUngroupBarBackgroundColorResourceIdForTesting());
mModel.set(TabGridPanelProperties.DIALOG_UNGROUP_BAR_BACKGROUND_COLOR_ID, incognitoColorId);
Assert.assertEquals(incognitoColorId,
mTabGridDialogParent.getUngroupBarBackgroundColorResourceIdForTesting());
}
@Test
@SmallTest
@UiThreadTest
public void testSetUngroupbarHoveredBackgroundColor() {
int normalColorId = R.color.tab_grid_card_selected_color;
int incognitoColorId = R.color.tab_grid_card_selected_color_incognito;
// Default setup is in normal mode.
Assert.assertEquals(normalColorId,
mTabGridDialogParent.getUngroupBarHoveredBackgroundColorResourceIdForTesting());
mModel.set(TabGridPanelProperties.DIALOG_UNGROUP_BAR_HOVERED_BACKGROUND_COLOR_ID,
incognitoColorId);
Assert.assertEquals(incognitoColorId,
mTabGridDialogParent.getUngroupBarHoveredBackgroundColorResourceIdForTesting());
}
@Test
@SmallTest
@UiThreadTest
public void testSetUngroupbarTextAppearance() {
int normalStyleId = R.style.TextAppearance_BlueTitle2;
int incognitoStyleId = R.style.TextAppearance_BlueTitle2Incognito;
// Default setup is in normal mode.
Assert.assertEquals(
normalStyleId, mTabGridDialogParent.getUngroupBarTextAppearanceForTesting());
mModel.set(TabGridPanelProperties.DIALOG_UNGROUP_BAR_TEXT_APPEARANCE, incognitoStyleId);
Assert.assertEquals(
incognitoStyleId, mTabGridDialogParent.getUngroupBarTextAppearanceForTesting());
}
@Test
@SmallTest
@UiThreadTest
public void testSetMainContentVisibility() {
mContentView.setVisibility(View.INVISIBLE);
Assert.assertEquals(View.INVISIBLE, mContentView.getVisibility());
mModel.set(TabGridPanelProperties.IS_MAIN_CONTENT_VISIBLE, true);
Assert.assertEquals(View.VISIBLE, mContentView.getVisibility());
}
@Test
@SmallTest
@UiThreadTest
public void testSetTitleTextWatcher() {
String title = "cool tabs";
AtomicBoolean titleTextUpdated = new AtomicBoolean();
titleTextUpdated.set(false);
TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void afterTextChanged(Editable editable) {
titleTextUpdated.set(true);
}
};
mModel.set(TabGridPanelProperties.TITLE_TEXT_WATCHER, textWatcher);
mTitleTextView.setText(title);
Assert.assertTrue(titleTextUpdated.get());
}
@Test
@SmallTest
@UiThreadTest
public void testSetTitleTextOnFocusListener() {
AtomicBoolean textFocusChanged = new AtomicBoolean();
textFocusChanged.set(false);
Assert.assertFalse(mTitleTextView.isFocused());
View.OnFocusChangeListener listener = (view, b) -> textFocusChanged.set(true);
mModel.set(TabGridPanelProperties.TITLE_TEXT_ON_FOCUS_LISTENER, listener);
mTitleTextView.requestFocus();
Assert.assertTrue(mTitleTextView.isFocused());
Assert.assertTrue(textFocusChanged.get());
}
@Test
@SmallTest
@UiThreadTest
public void testSetCursorVisibility() {
mTitleTextView.setCursorVisible(false);
mModel.set(TabGridPanelProperties.TITLE_CURSOR_VISIBILITY, true);
Assert.assertTrue(mTitleTextView.isCursorVisible());
}
@Test
@SmallTest
@UiThreadTest
public void testSetIsTitleTextFocused() {
Assert.assertFalse(mTitleTextView.isFocused());
mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, true);
// Binder should ignore set focus signal to avoid duplicate setting.
Assert.assertFalse(mTitleTextView.isFocused());
mTitleTextView.requestFocus();
Assert.assertTrue(mTitleTextView.isFocused());
mModel.set(TabGridPanelProperties.IS_TITLE_TEXT_FOCUSED, false);
Assert.assertFalse(mTitleTextView.isFocused());
}
@Override
public void tearDownTest() throws Exception {
mMCP.destroy();
mTabGridDialogParent.destroy();
super.tearDownTest();
}
private static boolean areAnimatorsEnabled() {
// We default to assuming that animations are enabled in case ANIMATOR_DURATION_SCALE is not
// defined.
final float defaultScale = 1f;
float durationScale =
Settings.Global.getFloat(ContextUtils.getApplicationContext().getContentResolver(),
Settings.Global.ANIMATOR_DURATION_SCALE, defaultScale);
return !(durationScale == 0.0);
}
}