// Copyright 2015 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.components.infobars;
import android.content.Context;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup.LayoutParams;
import androidx.test.InstrumentationRegistry;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.components.infobars.InfoBarControlLayout.ControlLayoutParams;
import org.chromium.components.infobars.test.R;
/**
* Tests for InfoBarControlLayout. This suite doesn't check for specific details, like margins
* paddings, and instead focuses on whether controls are placed correctly.
*/
@RunWith(BaseJUnit4ClassRunner.class)
public class InfoBarControlLayoutTest {
private static final int SWITCH_ID_1 = 1;
private static final int SWITCH_ID_2 = 2;
private static final int SWITCH_ID_3 = 3;
private static final int SWITCH_ID_4 = 4;
private static final int INFOBAR_WIDTH = 3200;
private Context mContext;
@Before
public void setUp() {
mContext = InstrumentationRegistry.getTargetContext();
mContext.setTheme(R.style.Theme_BrowserUI_DayNight);
}
/** A small control on the last line takes up the full width. */
@Test
@SmallTest
@UiThreadTest
public void testOneSmallControlTakesFullWidth() {
InfoBarControlLayout layout = new InfoBarControlLayout(mContext);
layout.setLayoutParams(
new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
View smallSwitch = layout.addSwitch(0, 0, "A", SWITCH_ID_1, false);
// Trigger the measurement algorithm.
int parentWidthSpec = MeasureSpec.makeMeasureSpec(INFOBAR_WIDTH, MeasureSpec.AT_MOST);
int parentHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
layout.measure(parentWidthSpec, parentHeightSpec);
// Small control takes the full width of the layout because it's put on its own line.
ControlLayoutParams params = InfoBarControlLayout.getControlLayoutParams(smallSwitch);
Assert.assertEquals(0, params.top);
Assert.assertEquals(0, params.start);
Assert.assertEquals(2, params.columnsRequired);
Assert.assertEquals(INFOBAR_WIDTH, smallSwitch.getMeasuredWidth());
}
/**
* Tests the layout algorithm on a set of five controls, the second of which is a huge control
* and takes up the whole line. The other smaller controls try to pack themselves as tightly as
* possible, strecthing out if necessary for aesthetics, resulting in a layout like this:
*
* <p>------------------------- | A (small) | ------------------------- | B (big) |
* ------------------------- | C (small) | D (small) | ------------------------- | E (small) |
* -------------------------
*/
@Test
@SmallTest
@UiThreadTest
public void testComplexSwitchLayout() {
// Add five controls to the layout.
InfoBarControlLayout layout = new InfoBarControlLayout(mContext);
layout.setLayoutParams(
new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
View switch1 = layout.addSwitch(0, 0, "A", SWITCH_ID_1, false);
View switch2 = layout.addSwitch(0, 0, "B", SWITCH_ID_2, false);
View switch3 = layout.addSwitch(0, 0, "C", SWITCH_ID_3, false);
View switch4 = layout.addSwitch(0, 0, "D", SWITCH_ID_4, false);
View switch5 = layout.addSwitch(0, 0, "E", SWITCH_ID_4, false);
// Make the second control require the full layout width.
switch2.setMinimumWidth(INFOBAR_WIDTH);
// Trigger the measurement algorithm.
int parentWidthSpec = MeasureSpec.makeMeasureSpec(INFOBAR_WIDTH, MeasureSpec.AT_MOST);
int parentHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
layout.measure(parentWidthSpec, parentHeightSpec);
ControlLayoutParams params1 = InfoBarControlLayout.getControlLayoutParams(switch1);
ControlLayoutParams params2 = InfoBarControlLayout.getControlLayoutParams(switch2);
ControlLayoutParams params3 = InfoBarControlLayout.getControlLayoutParams(switch3);
ControlLayoutParams params4 = InfoBarControlLayout.getControlLayoutParams(switch4);
ControlLayoutParams params5 = InfoBarControlLayout.getControlLayoutParams(switch5);
// Small control takes the full width of the layout because the next one doesn't fit.
Assert.assertEquals(0, params1.top);
Assert.assertEquals(0, params1.start);
Assert.assertEquals(2, params1.columnsRequired);
Assert.assertEquals(INFOBAR_WIDTH, switch1.getMeasuredWidth());
// Big control gets shunted onto the next row and takes up the whole space.
Assert.assertTrue(params2.top > switch1.getMeasuredHeight());
Assert.assertEquals(0, params2.start);
Assert.assertEquals(2, params2.columnsRequired);
Assert.assertEquals(INFOBAR_WIDTH, switch2.getMeasuredWidth());
// Small control gets placed onto the next line and takes only half the width.
int bottomOfSwitch2 = params2.top + switch2.getMeasuredHeight();
Assert.assertTrue(params3.top > bottomOfSwitch2);
Assert.assertEquals(0, params3.start);
Assert.assertEquals(1, params3.columnsRequired);
Assert.assertTrue(switch3.getMeasuredWidth() < INFOBAR_WIDTH);
// Small control gets placed next to the previous small control.
Assert.assertEquals(params3.top, params4.top);
Assert.assertTrue(params4.start > switch3.getMeasuredWidth());
Assert.assertEquals(1, params4.columnsRequired);
Assert.assertTrue(switch4.getMeasuredWidth() < INFOBAR_WIDTH);
// Last small control has no room left and gets put on its own line, taking the full width.
int bottomOfSwitch4 = params4.top + switch4.getMeasuredHeight();
Assert.assertTrue(params5.top > bottomOfSwitch4);
Assert.assertEquals(0, params5.start);
Assert.assertEquals(2, params5.columnsRequired);
Assert.assertEquals(INFOBAR_WIDTH, switch5.getMeasuredWidth());
}
/** Tests that the message is always the full width of the layout. */
@Test
@SmallTest
@UiThreadTest
public void testFullWidthMessageControl() {
// Add two controls to the layout. The main message automatically requests the full width.
InfoBarControlLayout layout = new InfoBarControlLayout(mContext);
layout.setLayoutParams(
new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
View view1 = layout.addMainMessage("A");
View view2 = layout.addSwitch(0, 0, "B", SWITCH_ID_2, false);
// Trigger the measurement algorithm.
int parentWidthSpec = MeasureSpec.makeMeasureSpec(INFOBAR_WIDTH, MeasureSpec.AT_MOST);
int parentHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
layout.measure(parentWidthSpec, parentHeightSpec);
ControlLayoutParams params1 = InfoBarControlLayout.getControlLayoutParams(view1);
ControlLayoutParams params2 = InfoBarControlLayout.getControlLayoutParams(view2);
// Main message takes up the full space.
Assert.assertEquals(0, params1.top);
Assert.assertEquals(0, params1.start);
Assert.assertEquals(2, params1.columnsRequired);
Assert.assertEquals(INFOBAR_WIDTH, view1.getMeasuredWidth());
// Small control gets shunted onto the next row.
Assert.assertTrue(params2.top > view1.getMeasuredHeight());
Assert.assertEquals(0, params2.start);
Assert.assertEquals(2, params2.columnsRequired);
Assert.assertEquals(INFOBAR_WIDTH, view2.getMeasuredWidth());
}
}