/* * Copyright (C) 2016 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 com.google.android.material.textfield; import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.clearText; import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.action.ViewActions.typeText; import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.isEnabled; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static com.google.android.material.testutils.TestUtilsActions.setEnabled; import static com.google.android.material.testutils.TestUtilsActions.setLayoutDirection; import static com.google.android.material.testutils.TestUtilsMatchers.withTextColor; import static com.google.android.material.testutils.TestUtilsMatchers.withTypeface; import static com.google.android.material.testutils.TextInputLayoutActions.setBoxBackgroundColor; import static com.google.android.material.testutils.TextInputLayoutActions.setBoxCornerFamily; import static com.google.android.material.testutils.TextInputLayoutActions.setBoxCornerRadii; import static com.google.android.material.testutils.TextInputLayoutActions.setBoxStrokeColor; import static com.google.android.material.testutils.TextInputLayoutActions.setBoxStrokeErrorColor; import static com.google.android.material.testutils.TextInputLayoutActions.setBoxStrokeWidth; import static com.google.android.material.testutils.TextInputLayoutActions.setBoxStrokeWidthFocused; import static com.google.android.material.testutils.TextInputLayoutActions.setCounterEnabled; import static com.google.android.material.testutils.TextInputLayoutActions.setCounterMaxLength; import static com.google.android.material.testutils.TextInputLayoutActions.setError; import static com.google.android.material.testutils.TextInputLayoutActions.setErrorAccessibilityLiveRegion; import static com.google.android.material.testutils.TextInputLayoutActions.setErrorContentDescription; import static com.google.android.material.testutils.TextInputLayoutActions.setErrorEnabled; import static com.google.android.material.testutils.TextInputLayoutActions.setErrorTextAppearance; import static com.google.android.material.testutils.TextInputLayoutActions.setExpandedHintEnabled; import static com.google.android.material.testutils.TextInputLayoutActions.setHelperText; import static com.google.android.material.testutils.TextInputLayoutActions.setHelperTextEnabled; import static com.google.android.material.testutils.TextInputLayoutActions.setHint; import static com.google.android.material.testutils.TextInputLayoutActions.setHintTextAppearance; import static com.google.android.material.testutils.TextInputLayoutActions.setPlaceholderText; import static com.google.android.material.testutils.TextInputLayoutActions.setShapeAppearanceModel; import static com.google.android.material.testutils.TextInputLayoutActions.setTypeface; import static com.google.common.truth.Truth.assertThat; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import android.app.Activity; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Color; import android.graphics.Typeface; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Parcelable; import android.text.TextPaint; import android.util.SparseArray; import android.view.inputmethod.EditorInfo; import android.widget.AutoCompleteTextView; import android.widget.EditText; import android.widget.TextView; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.core.view.ViewCompat; import androidx.core.widget.TextViewCompat; import androidx.test.annotation.UiThreadTest; import androidx.test.espresso.ViewAssertion; import androidx.test.filters.MediumTest; import androidx.test.filters.SdkSuppress; import androidx.test.rule.ActivityTestRule; import androidx.test.runner.AndroidJUnit4; import com.google.android.material.shape.CornerFamily; import com.google.android.material.shape.CornerTreatment; import com.google.android.material.shape.CutCornerTreatment; import com.google.android.material.shape.RoundedCornerTreatment; import com.google.android.material.shape.ShapeAppearanceModel; import com.google.android.material.testapp.R; import com.google.android.material.testapp.TextInputLayoutActivity; import com.google.android.material.testutils.TestUtils; import com.google.android.material.testutils.ViewStructureImpl; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @MediumTest @RunWith(AndroidJUnit4.class) public class TextInputLayoutTest { @Rule public final ActivityTestRule activityTestRule = new ActivityTestRule<>(TextInputLayoutActivity.class); private static final String ERROR_MESSAGE_1 = "An error has occurred"; private static final String ERROR_MESSAGE_2 = "Some other error has occurred"; private static final String HELPER_MESSAGE_1 = "Helpful helper text"; private static final String HELPER_MESSAGE_2 = "Some other helper text"; private static final String PLACEHOLDER_TEXT = "This text is holding the place"; private static final String HINT_TEXT = "Hint text"; private static final String INPUT_TEXT = "Random input text"; private static final Typeface CUSTOM_TYPEFACE = Typeface.SANS_SERIF; private static class TestTextInputLayout extends TextInputLayout { public int animateToExpansionFractionCount = 0; public float animateToExpansionFractionRecentValue = -1; public TestTextInputLayout(Context context) { super(context); } @Override protected void animateToExpansionFraction(float target) { super.animateToExpansionFraction(target); animateToExpansionFractionRecentValue = target; animateToExpansionFractionCount++; } } @Test public void testTypingTextCollapsesHint() { // Type some text onView(withId(R.id.textinput_edittext)).perform(typeText(INPUT_TEXT)); // ...and check that the hint has collapsed onView(withId(R.id.textinput)).check(isHintExpanded(false)); } @Test public void testNoBoxNoCutout() { // Type some text on the non-box text field. onView(withId(R.id.textinput_edittext)).perform(typeText(INPUT_TEXT)); // Check that there is no cutout. onView(withId(R.id.textinput)).check(isCutoutOpen(false)); } @Test public void testFilledBoxHintCollapseNoCutout() { // Type some text on the filled box text field. onView(withId(R.id.textinput_edittext_filled)).perform(typeText(INPUT_TEXT)); // Check that there is no cutout. onView(withId(R.id.textinput_box_filled)).check(isCutoutOpen(false)); } @Test public void testOutlineBoxNoHintNoCutout() { // Type some text on the outline box without a hint. onView(withId(R.id.textinput_edittext_outline_no_hint)).perform(typeText(INPUT_TEXT)); // Check that there is no cutout. onView(withId(R.id.textinput_box_outline_no_hint)).check(isCutoutOpen(false)); } @Test public void testOutlineBoxHintCollapseCreatesCutout() { // Type some text on the outline box that has a hint. onView(withId(R.id.textinput_edittext_outline)).perform(typeText(INPUT_TEXT)); // Check that the cutout is open. onView(withId(R.id.textinput_box_outline)).check(isCutoutOpen(true)); } @Test public void testOutlineBoxHintExpandHidesCutout() { // Type some text on the outline box that has a hint. onView(withId(R.id.textinput_edittext_outline)).perform(typeText(INPUT_TEXT)); // Remove the text so that the hint will go away when the text box loses focus. onView(withId(R.id.textinput_edittext_outline)).perform(clearText()); // Type some text on another text field to remove focus from the outline box. onView(withId(R.id.textinput_edittext_filled)).perform(typeText(INPUT_TEXT)); // Check that the cutout is closed. onView(withId(R.id.textinput_box_outline)).check(isCutoutOpen(false)); } @Test public void testHintIsCollapsedIfExpandedHintNotEnabled() { // Set expandedHintEnabled to false. onView(withId(R.id.textinput_box_filled)).perform(setExpandedHintEnabled(false)); // Check the hint is collapsed. onView(withId(R.id.textinput_box_filled)).check(isHintExpanded(false)); } @Test public void testSetErrorEnablesErrorIsDisplayed() { onView(withId(R.id.textinput)).perform(setError(ERROR_MESSAGE_1)); onView(withText(ERROR_MESSAGE_1)).check(matches(isDisplayed())); } @Test public void testSetHelperEnablesHelperIsDisplayed() { onView(withId(R.id.textinput)).perform(setHelperText(HELPER_MESSAGE_1)); onView(withText(HELPER_MESSAGE_1)).check(matches(isDisplayed())); } @Test public void testSetHelperTextViaAttribute() { // The text input with id textinput_box_outline has the string textinput_helper set on it via // the helper text attribute. Check that the helper text is displayed via the attribute. String helperText = activityTestRule.getActivity().getResources().getString(R.string.textinput_helper); onView(withText(helperText)).check(matches(isDisplayed())); } @Test public void testSetHelperTextViaAttributeHelperDisabled() { // The text input with id textinput_box_filled has the string // textinput_helper_not_enabled set on it via the helper text attribute, but helperTextEnabled // is not set to true. Check that the helper text is displayed via the attribute, even when // helperTextEnabled is not explicitly set to true. String helperTextNotEnabled = activityTestRule .getActivity() .getResources() .getString(R.string.textinput_helper_not_enabled); onView(withText(helperTextNotEnabled)).check(matches(isDisplayed())); } @Test public void testDisabledErrorIsNotDisplayed() { // First show an error, and then disable error functionality onView(withId(R.id.textinput)) .perform(setError(ERROR_MESSAGE_1)) .perform(setErrorEnabled(false)); // Check that the error is no longer there onView(withText(ERROR_MESSAGE_1)).check(doesNotExist()); } @Test public void testDisabledHelperIsNotDisplayed() { // First show a helper, and then disable helper functionality onView(withId(R.id.textinput)) .perform(setHelperText(HELPER_MESSAGE_1)) .perform(setHelperTextEnabled(false)); // Check that the helper is no longer there onView(withText(HELPER_MESSAGE_1)).check(doesNotExist()); } @Test public void testSetErrorOnDisabledSetErrorIsDisplayed() { // First show an error, and then disable error functionality onView(withId(R.id.textinput)) .perform(setError(ERROR_MESSAGE_1)) .perform(setErrorEnabled(false)); // Now show a different error message onView(withId(R.id.textinput)).perform(setError(ERROR_MESSAGE_2)); // And check that it is displayed onView(withText(ERROR_MESSAGE_2)).check(matches(isDisplayed())); } @Test public void testSetHelperOnDisabledSetHelperIsDisplayed() { // First show a helper, and then disable helper functionality onView(withId(R.id.textinput)) .perform(setHelperText(HELPER_MESSAGE_1)) .perform(setHelperTextEnabled(false)); // Now show a different helper message onView(withId(R.id.textinput)).perform(setHelperText(HELPER_MESSAGE_2)); // And check that it is displayed onView(withText(HELPER_MESSAGE_2)).check(matches(isDisplayed())); } @Test public void testSetPlaceholderText() { onView(withId(R.id.textinput_box_outline)).perform(setPlaceholderText(PLACEHOLDER_TEXT)); // Click on the EditText so that the hint collapses and the placeholder text is shown. onView(withId(R.id.textinput_edittext_outline)).perform(click()); // Check that the placeholder text is displayed. onView(withText(PLACEHOLDER_TEXT)).check(matches(isDisplayed())); } @Test public void testSetPlaceholderTextViaAttribute() { // The text input with id textinput_box_outline has the string textinput_placeholder set on it // via the placeholder text attribute. Check that the placeholder text is displayed via the // attribute. String placeholderText = activityTestRule.getActivity().getResources().getString(R.string.textinput_placeholder); // Click on the EditText so that the hint collapses and the placeholder text is shown. onView(withId(R.id.textinput_edittext_outline)).perform(click()); // Check that the placeholder text is displayed. onView(withText(placeholderText)).check(matches(isDisplayed())); } @Test public void testSetErrorNullDoesNotHideHelperText() { // Show helper text in layout with error enabled onView(withId(R.id.textinput)).perform(setHelperText(HELPER_MESSAGE_1)); // Set error to null onView(withId(R.id.textinput)).perform(setError(null)); // Check helper text is still visible onView(withText(HELPER_MESSAGE_1)).check(matches(isDisplayed())); } @Test public void testSetEnabledFalse() { // First click on the EditText, so that it is focused and the hint collapses... onView(withId(R.id.textinput_edittext)).perform(click()); // Now disable the TextInputLayout and check that the hint expands onView(withId(R.id.textinput)).perform(setEnabled(false)).check(isHintExpanded(true)); // Finally check that the EditText is no longer enabled onView(withId(R.id.textinput_edittext)).check(matches(not(isEnabled()))); } @Test public void testSetEnabledFalseWithText() { // First set some text, then disable the TextInputLayout onView(withId(R.id.textinput_edittext)).perform(typeText(INPUT_TEXT)); onView(withId(R.id.textinput)).perform(setEnabled(false)); // Now check that the EditText is no longer enabled onView(withId(R.id.textinput_edittext)).check(matches(not(isEnabled()))); } @UiThreadTest @Test public void testExtractUiHintSet() { final Activity activity = activityTestRule.getActivity(); // Set a hint on the TextInputLayout final TextInputLayout layout = activity.findViewById(R.id.textinput); layout.setHint(INPUT_TEXT); final EditText editText = activity.findViewById(R.id.textinput_edittext); // Now manually pass in a EditorInfo to the EditText and make sure it updates the // hintText to our known value final EditorInfo info = new EditorInfo(); editText.onCreateInputConnection(info); assertEquals(INPUT_TEXT, info.hintText.toString()); } @UiThreadTest @Test @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O) public void testDispatchProvideAutofillStructure() { final Activity activity = activityTestRule.getActivity(); final TextInputLayout layout = activity.findViewById(R.id.textinput_layout_without_hint); final ViewStructureImpl structure = new ViewStructureImpl(); layout.dispatchProvideAutofillStructure(structure, 0); // 1 x EditText, 2 x TextView (prefix/suffix). assertEquals(3, structure.getChildCount()); // Asserts the structure. ViewStructureImpl childStructure = structure.getChildAt(0); assertEquals(EditText.class.getName(), childStructure.getClassName()); assertEquals("Nested hint", childStructure.getHint().toString()); // Make sure the widget's hint was restored. assertEquals("Nested hint", layout.getHint().toString()); final EditText editText = activity.findViewById(R.id.textinput_edittext_with_hint); assertNull(editText.getHint()); } @UiThreadTest @Test public void testDrawableStateChanged() { final Activity activity = activityTestRule.getActivity(); final TextInputLayout layout = (TextInputLayout) activity.findViewById(R.id.textinput); // Force a drawable state change. layout.drawableStateChanged(); } @UiThreadTest @Test public void testSaveRestoreStateAnimation() { final Activity activity = activityTestRule.getActivity(); final TestTextInputLayout layout = new TestTextInputLayout(activity); layout.setId(R.id.textinputlayout); final TextInputEditText editText = new TextInputEditText(activity); editText.setText(INPUT_TEXT); editText.setId(R.id.textinputedittext); layout.addView(editText); SparseArray container = new SparseArray<>(); layout.saveHierarchyState(container); layout.restoreHierarchyState(container); assertEquals( "Expected no animations since we simply saved/restored state", 0, layout.animateToExpansionFractionCount); editText.setText(""); assertEquals( "Expected one call to animate because we cleared text in editText", 1, layout.animateToExpansionFractionCount); assertEquals(0f, layout.animateToExpansionFractionRecentValue, 0f); container = new SparseArray<>(); layout.saveHierarchyState(container); layout.restoreHierarchyState(container); assertEquals( "Expected no additional animations since we simply saved/restored state", 1, layout.animateToExpansionFractionCount); } @UiThreadTest @Test public void testMaintainsLeftRightCompoundDrawables() throws Throwable { final Activity activity = activityTestRule.getActivity(); // Set a known set of test compound drawables on the EditText final Drawable left = new ColorDrawable(Color.RED); final Drawable top = new ColorDrawable(Color.GREEN); final Drawable right = new ColorDrawable(Color.BLUE); final Drawable bottom = new ColorDrawable(Color.BLACK); final TextInputEditText editText = new TextInputEditText(activity); editText.setCompoundDrawables(left, top, right, bottom); // Now add the EditText to a TextInputLayout TextInputLayout til = activity.findViewById(R.id.textinput_noedittext); til.addView(editText); // Finally assert that all of the drawables are untouched final Drawable[] compoundDrawables = editText.getCompoundDrawables(); assertSame(left, compoundDrawables[0]); assertSame(top, compoundDrawables[1]); assertSame(right, compoundDrawables[2]); assertSame(bottom, compoundDrawables[3]); } @UiThreadTest @Test public void testMaintainsStartEndCompoundDrawables() throws Throwable { final Activity activity = activityTestRule.getActivity(); // Set a known set of test compound drawables on the EditText final Drawable start = new ColorDrawable(Color.RED); final Drawable top = new ColorDrawable(Color.GREEN); final Drawable end = new ColorDrawable(Color.BLUE); final Drawable bottom = new ColorDrawable(Color.BLACK); final TextInputEditText editText = new TextInputEditText(activity); TextViewCompat.setCompoundDrawablesRelative(editText, start, top, end, bottom); // Now add the EditText to a TextInputLayout TextInputLayout til = activity.findViewById(R.id.textinput_noedittext); til.addView(editText); // Finally assert that all of the drawables are untouched final Drawable[] compoundDrawables = TextViewCompat.getCompoundDrawablesRelative(editText); assertSame(start, compoundDrawables[0]); assertSame(top, compoundDrawables[1]); assertSame(end, compoundDrawables[2]); assertSame(bottom, compoundDrawables[3]); } @Test public void testSetErrorContentDescription() { String errorContentDesc = "Error content description"; // Set error and error content description. onView(withId(R.id.textinput)) .perform(setErrorEnabled(true)) .perform(setError(ERROR_MESSAGE_1)) .perform(setErrorContentDescription(errorContentDesc)); final Activity activity = activityTestRule.getActivity(); final TextInputLayout textInputLayout = activity.findViewById(R.id.textinput); // Assert the error content description is as expected. assertEquals(errorContentDesc, textInputLayout.getErrorContentDescription().toString()); } @Test public void testSetErrorAccessibilityLiveRegion() { int errorAccessibilityLiveRegion = ViewCompat.ACCESSIBILITY_LIVE_REGION_NONE; // Set error and error accessibility live region. onView(withId(R.id.textinput)) .perform(setErrorEnabled(true)) .perform(setError(ERROR_MESSAGE_1)) .perform(setErrorAccessibilityLiveRegion(errorAccessibilityLiveRegion)); final Activity activity = activityTestRule.getActivity(); final TextInputLayout textInputLayout = activity.findViewById(R.id.textinput); // Assert the error accessibility live region is as expected. assertEquals(errorAccessibilityLiveRegion, textInputLayout.getErrorAccessibilityLiveRegion()); } @Test public void testDefaultErrorAccessibilityLiveRegionIsPolite() { // Set error. onView(withId(R.id.textinput)) .perform(setErrorEnabled(true)) .perform(setError(ERROR_MESSAGE_1)); final Activity activity = activityTestRule.getActivity(); final TextInputLayout textInputLayout = activity.findViewById(R.id.textinput); // Assert the error accessibility live region is as expected. assertEquals( ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE, textInputLayout.getErrorAccessibilityLiveRegion()); } @Test public void testSetTypefaceUpdatesErrorView() { onView(withId(R.id.textinput)) .perform(setErrorEnabled(true)) .perform(setError(ERROR_MESSAGE_1)) .perform(setTypeface(CUSTOM_TYPEFACE)); // Check that the error message is updated onView(withText(ERROR_MESSAGE_1)).check(matches(withTypeface(CUSTOM_TYPEFACE))); } @Test public void testSetTypefaceUpdatesCharacterCountView() { // Turn on character counting onView(withId(R.id.textinput)) .perform(setCounterEnabled(true), setCounterMaxLength(10)) .perform(setTypeface(CUSTOM_TYPEFACE)); // Check that the counter message is updated onView(withId(R.id.textinput_counter)).check(matches(withTypeface(CUSTOM_TYPEFACE))); } @Test public void testThemedColorStateListForErrorTextColor() { final Activity activity = activityTestRule.getActivity(); final int textColor = TestUtils.getThemeAttrColor(activity, R.attr.colorAccent); onView(withId(R.id.textinput)) .perform(setErrorEnabled(true)) .perform(setError(ERROR_MESSAGE_1)) .perform(setErrorTextAppearance(R.style.TextAppearanceWithThemedCslTextColor)); onView(withText(ERROR_MESSAGE_1)).check(matches(withTextColor(textColor))); } @Test public void testHintIsErrorTextColorOnError() { final Activity activity = activityTestRule.getActivity(); final TextInputLayout layout = activity.findViewById(R.id.textinput); onView(withId(R.id.textinput)) .perform(setErrorEnabled(true)) .perform(setError(ERROR_MESSAGE_1)); @ColorInt int hintColor = layout.getHintCurrentCollapsedTextColor(); @ColorInt int errorColor = layout.getErrorCurrentTextColors(); assertEquals(hintColor, errorColor); } @Test public void testTextSetViaAttributeCollapsedHint() { onView(withId(R.id.textinput_with_text)).check(isHintExpanded(false)); } @Test public void testHintCollapsedHeightMeasuredFromBaseline() { final Activity activity = activityTestRule.getActivity(); final TextInputLayout layout = activity.findViewById(R.id.textinput_box_outline); // Create a TextView and set it to a custom text and TextAppearance. TextView textView = new TextView(layout.getContext()); textView.setText(HINT_TEXT); TextViewCompat.setTextAppearance(textView, R.style.TextMediumGreenStyle); // Create a TextPaint to measure the text's height from the baseline, and port over aspects of // the TextAppearance from the textView. TextPaint textPaint = new TextPaint(); textPaint.setSubpixelText(true); textPaint.setColor(textView.getCurrentTextColor()); textPaint.setTypeface(textView.getTypeface()); textPaint.setTextSize(textView.getTextSize()); // Set the same custom text and text appearance on the outline box's hint. onView(withId(R.id.textinput_box_outline)) .perform(setHint(HINT_TEXT)) .perform(setHintTextAppearance(R.style.TextMediumGreenStyle)); // Check that the hint's collapsed height is the same as the TextPaint's height, measured from // the baseline (-ascent). assertEquals(layout.getHintCollapsedTextHeight(), -textPaint.ascent(), 0.01); } @Test public void testSetBoxStrokeWidth() { final Activity activity = activityTestRule.getActivity(); final TextInputLayout layout = activity.findViewById(R.id.textinput_box_outline); // Set stroke width onView(withId(R.id.textinput_box_outline)).perform(setBoxStrokeWidth(10)); // Assert stroke width is correct assertEquals(10, layout.getBoxStrokeWidth()); } @Test public void testSetBoxStrokeFocusedWidth() { final Activity activity = activityTestRule.getActivity(); final TextInputLayout layout = activity.findViewById(R.id.textinput_box_outline); // Set stroke width onView(withId(R.id.textinput_box_outline)).perform(setBoxStrokeWidthFocused(10)); // Assert stroke width is correct assertEquals(10, layout.getBoxStrokeWidthFocused()); } @Test public void testOutlineBoxStrokeChangesColor() { @ColorInt int cyan = Color.CYAN; @ColorInt int green = Color.GREEN; // Change the outline box's stroke color to cyan. onView(withId(R.id.textinput_box_outline)).perform(setBoxStrokeColor(cyan)); // Check that the outline box's stroke color is cyan. onView(withId(R.id.textinput_box_outline)).check(isBoxStrokeColor(cyan)); // Change the outline box's stroke color to green. onView(withId(R.id.textinput_box_outline)).perform(setBoxStrokeColor(green)); // Check that the outline box's stroke color is green. onView(withId(R.id.textinput_box_outline)).check(isBoxStrokeColor(green)); } @Test public void testOutlineBoxStrokeChangesErrorColor() { ColorStateList cyan = new ColorStateList(new int[][] {new int[] {}}, new int[] {Color.CYAN}); ColorStateList green = new ColorStateList(new int[][] {new int[] {}}, new int[] {Color.GREEN}); onView(withId(R.id.textinput_box_outline)).perform(setError(ERROR_MESSAGE_1)); // Change the outline box's stroke error color to cyan. onView(withId(R.id.textinput_box_outline)).perform(setBoxStrokeErrorColor(cyan)); // Check that the outline box's stroke error color is cyan. onView(withId(R.id.textinput_box_outline)).check(isBoxStrokeErrorColor(cyan)); // Change the outline box's stroke error color to green. onView(withId(R.id.textinput_box_outline)).perform(setBoxStrokeErrorColor(green)); // Check that the outline box's stroke error color is green. onView(withId(R.id.textinput_box_outline)).check(isBoxStrokeErrorColor(green)); } @Test public void testOutlineBoxBackgroundChangesColor() { @ColorInt int blue = Color.BLUE; @ColorInt int yellow = Color.YELLOW; // Change the outline box's background color to blue. onView(withId(R.id.textinput_box_outline)).perform(setBoxBackgroundColor(blue)); // Check that the outline box's background color is blue. onView(withId(R.id.textinput_box_outline)).check(isBoxBackgroundColor(blue)); // Change the outline box's background color to yellow. onView(withId(R.id.textinput_box_outline)).perform(setBoxBackgroundColor(yellow)); // Check that the outline box's background color is yellow. onView(withId(R.id.textinput_box_outline)).check(isBoxBackgroundColor(yellow)); } @Test public void testFilledBoxBackgroundChangesColor() { @ColorInt int blue = Color.BLUE; @ColorInt int yellow = Color.YELLOW; // Change the filled box's background color to blue. onView(withId(R.id.textinput_box_filled)).perform(setBoxBackgroundColor(blue)); // Check that the filled box's background color is blue. onView(withId(R.id.textinput_box_filled)).check(isBoxBackgroundColor(blue)); // Change the filled box's background color to yellow. onView(withId(R.id.textinput_box_filled)).perform(setBoxBackgroundColor(yellow)); // Check that the filled box's background color is yellow. onView(withId(R.id.textinput_box_filled)).check(isBoxBackgroundColor(yellow)); } @Test public void testSetBoxCornerFamily() { onView(withId(R.id.textinput_box_outline)).perform(setBoxCornerFamily(CornerFamily.CUT)); onView(withId(R.id.textinput_box_outline)).check(isCornerFamily(CutCornerTreatment.class)); } @Test public void testSetShapeAppearanceModel() { float cornerRadius = 30; ShapeAppearanceModel shapeAppearanceModel = ShapeAppearanceModel.builder() .setTopLeftCorner(CornerFamily.CUT, cornerRadius) .setBottomRightCorner(CornerFamily.CUT, cornerRadius) .build(); onView(withId(R.id.textinput_box_outline)) .perform(setShapeAppearanceModel(shapeAppearanceModel)); // Assert the new shape appearance model set. onView(withId(R.id.textinput_box_outline)).check(isShapeAppearanceModel(shapeAppearanceModel)); // Assert corner radii values. onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusTopStart(cornerRadius)); onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusTopEnd(0)); onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusBottomStart(0)); onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusBottomEnd(cornerRadius)); // Assert corner family values. onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyTopLeft(CutCornerTreatment.class)); onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyTopRight(RoundedCornerTreatment.class)); onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyBottomLeft(RoundedCornerTreatment.class)); onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyBottomRight(CutCornerTreatment.class)); } @Test public void testSetShapeAppearanceModelSwitchFromLtrToRtl() { float cornerRadius = 30; final Activity activity = activityTestRule.getActivity(); final TextInputLayout textInputLayout = activity.findViewById(R.id.textinput_box_outline); ShapeAppearanceModel shapeAppearanceModel = ShapeAppearanceModel.builder() .setTopLeftCorner(CornerFamily.CUT, cornerRadius) .setBottomRightCorner(CornerFamily.CUT, cornerRadius) .build(); // Set the shape appearance model. onView(withId(R.id.textinput_box_outline)) .perform(setShapeAppearanceModel(shapeAppearanceModel)); // Set to RTL. onView(withId(R.id.textinput_box_outline)) .perform(setLayoutDirection(ViewCompat.LAYOUT_DIRECTION_RTL)); if (ViewCompat.getLayoutDirection(textInputLayout) == ViewCompat.LAYOUT_DIRECTION_RTL) { // Asserts corner radii values are RTL. onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusTopLeft(0)); onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusTopRight(cornerRadius)); onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusBottomLeft(cornerRadius)); onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusBottomRight(0)); // Assert corner family values are RTL. onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyTopLeft(RoundedCornerTreatment.class)); onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyTopRight(CutCornerTreatment.class)); onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyBottomLeft(CutCornerTreatment.class)); onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyBottomRight(RoundedCornerTreatment.class)); } } @Test public void testSetShapeAppearanceModelSwitchFromRtlToLtr() { float cornerRadius = 30; final Activity activity = activityTestRule.getActivity(); final TextInputLayout textInputLayout = activity.findViewById(R.id.textinput_box_outline); ShapeAppearanceModel shapeAppearanceModel = ShapeAppearanceModel.builder() .setTopLeftCorner(CornerFamily.CUT, cornerRadius) .setBottomRightCorner(CornerFamily.CUT, cornerRadius) .build(); // Set the shape appearance model. onView(withId(R.id.textinput_box_outline)) .perform(setShapeAppearanceModel(shapeAppearanceModel)); // Set to RTL. onView(withId(R.id.textinput_box_outline)) .perform(setLayoutDirection(ViewCompat.LAYOUT_DIRECTION_RTL)); if (ViewCompat.getLayoutDirection(textInputLayout) == ViewCompat.LAYOUT_DIRECTION_RTL) { // Set back to LTR. onView(withId(R.id.textinput_box_outline)) .perform(setLayoutDirection(ViewCompat.LAYOUT_DIRECTION_LTR)); // Asserts corner radii values are LTR. onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusTopLeft(cornerRadius)); onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusTopRight(0)); onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusBottomLeft(0)); onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusBottomRight(cornerRadius)); // Assert corner family values are LTR. onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyTopLeft(CutCornerTreatment.class)); onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyTopRight(RoundedCornerTreatment.class)); onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyBottomLeft(RoundedCornerTreatment.class)); onView(withId(R.id.textinput_box_outline)) .check(isCornerFamilyBottomRight(CutCornerTreatment.class)); } } @Test public void testSetBoxCornerRadii() { float boxCornerRadiusTopStart = 0.5f; float boxCornerRadiusTopEnd = 1f; float boxCornerRadiusBottomStart = 1.5f; float boxCornerRadiusBottomEnd = 2f; // Set the outline box's corner radii. onView(withId(R.id.textinput_box_outline)) .perform( setBoxCornerRadii( boxCornerRadiusTopStart, boxCornerRadiusTopEnd, boxCornerRadiusBottomStart, boxCornerRadiusBottomEnd)); // Assert values match each respective corner. onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusTopStart(boxCornerRadiusTopStart)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusTopEnd(boxCornerRadiusTopEnd)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusBottomStart(boxCornerRadiusBottomStart)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusBottomEnd(boxCornerRadiusBottomEnd)); } @Test public void testSetBoxCornerRadiiInRtl() { float boxCornerRadiusTopStart = 0.5f; float boxCornerRadiusTopEnd = 1f; float boxCornerRadiusBottomStart = 1.5f; float boxCornerRadiusBottomEnd = 2f; final Activity activity = activityTestRule.getActivity(); final TextInputLayout textInputLayout = activity.findViewById(R.id.textinput_box_outline); // Set to RTL. onView(withId(R.id.textinput_box_outline)) .perform(setLayoutDirection(ViewCompat.LAYOUT_DIRECTION_RTL)); if (ViewCompat.getLayoutDirection(textInputLayout) == ViewCompat.LAYOUT_DIRECTION_RTL) { // Set the outline box's corner radii. onView(withId(R.id.textinput_box_outline)) .perform( setBoxCornerRadii( boxCornerRadiusTopStart, boxCornerRadiusTopEnd, boxCornerRadiusBottomStart, boxCornerRadiusBottomEnd)); // Assert values match each respective corner in RTL. onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusTopLeft(boxCornerRadiusTopEnd)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusTopRight(boxCornerRadiusTopStart)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusBottomLeft(boxCornerRadiusBottomEnd)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusBottomRight(boxCornerRadiusBottomStart)); // Assert getCornerRadius methods return correct values. onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusTopStart(boxCornerRadiusTopStart)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusTopEnd(boxCornerRadiusTopEnd)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusBottomStart(boxCornerRadiusBottomStart)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusBottomEnd(boxCornerRadiusBottomEnd)); } } @Test public void testSetBoxCornerRadiiSwitchFromLtrToRtl() { float boxCornerRadiusTopStart = 0.5f; float boxCornerRadiusTopEnd = 1f; float boxCornerRadiusBottomStart = 1.5f; float boxCornerRadiusBottomEnd = 2f; final Activity activity = activityTestRule.getActivity(); final TextInputLayout textInputLayout = activity.findViewById(R.id.textinput_box_outline); // Set the outline box's corner radii. onView(withId(R.id.textinput_box_outline)) .perform( setBoxCornerRadii( boxCornerRadiusTopStart, boxCornerRadiusTopEnd, boxCornerRadiusBottomStart, boxCornerRadiusBottomEnd)); // Set to RTL. onView(withId(R.id.textinput_box_outline)) .perform(setLayoutDirection(ViewCompat.LAYOUT_DIRECTION_RTL)); if (ViewCompat.getLayoutDirection(textInputLayout) == ViewCompat.LAYOUT_DIRECTION_RTL) { // Assert values match what they should be in RTL. onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusTopLeft(boxCornerRadiusTopEnd)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusTopRight(boxCornerRadiusTopStart)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusBottomLeft(boxCornerRadiusBottomEnd)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusBottomRight(boxCornerRadiusBottomStart)); } } @Test public void testSetBoxCornerRadiiSwitchFromRtlToLtr() { float boxCornerRadiusTopStart = 0.5f; float boxCornerRadiusTopEnd = 1f; float boxCornerRadiusBottomStart = 1.5f; float boxCornerRadiusBottomEnd = 2f; final Activity activity = activityTestRule.getActivity(); final TextInputLayout textInputLayout = activity.findViewById(R.id.textinput_box_outline); // Set to RTL. onView(withId(R.id.textinput_box_outline)) .perform(setLayoutDirection(ViewCompat.LAYOUT_DIRECTION_RTL)); // Set the outline box's corner radii. onView(withId(R.id.textinput_box_outline)) .perform( setBoxCornerRadii( boxCornerRadiusTopStart, boxCornerRadiusTopEnd, boxCornerRadiusBottomStart, boxCornerRadiusBottomEnd)); if (ViewCompat.getLayoutDirection(textInputLayout) == ViewCompat.LAYOUT_DIRECTION_RTL) { // Set back to LTR. onView(withId(R.id.textinput_box_outline)) .perform(setLayoutDirection(ViewCompat.LAYOUT_DIRECTION_LTR)); // Assert values are correct. onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusTopLeft(boxCornerRadiusTopStart)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusTopRight(boxCornerRadiusTopEnd)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusBottomLeft(boxCornerRadiusBottomStart)); onView(withId(R.id.textinput_box_outline)) .check(isBoxCornerRadiusBottomRight(boxCornerRadiusBottomEnd)); } } @Test public void testBoxTopEndCornerRadiusChangesWithFloatValue() { float cornerRadiusSmall = activityTestRule.getActivity().getResources().getDimension(R.dimen.corner_radius_small); float cornerRadiusMedium = activityTestRule.getActivity().getResources().getDimension(R.dimen.corner_radius_medium); // Set the filled box's corner radii to cornerRadiusSmall. onView(withId(R.id.textinput_box_filled)) .perform( setBoxCornerRadii( cornerRadiusSmall, cornerRadiusSmall, cornerRadiusSmall, cornerRadiusSmall)); // Check that the outline box's top end corner radius is cornerRadiusSmall. onView(withId(R.id.textinput_box_filled)).check(isBoxCornerRadiusTopEnd(cornerRadiusSmall)); // Set the filled box's corner radius to cornerRadiusMedium. onView(withId(R.id.textinput_box_filled)) .perform( setBoxCornerRadii( cornerRadiusMedium, cornerRadiusMedium, cornerRadiusMedium, cornerRadiusMedium)); // Check that the outline box's top end corner radius is cornerRadiusMedium. onView(withId(R.id.textinput_box_filled)).check(isBoxCornerRadiusTopEnd(cornerRadiusMedium)); } @Test public void testBoxTopEndCornerRadiusChangesWithResource() { float cornerRadiusSmall = activityTestRule.getActivity().getResources().getDimension(R.dimen.corner_radius_small); float cornerRadiusMedium = activityTestRule.getActivity().getResources().getDimension(R.dimen.corner_radius_medium); // Set the outline box's corner radii to cornerRadiusSmall. onView(withId(R.id.textinput_box_outline)) .perform( setBoxCornerRadii( R.dimen.corner_radius_small, R.dimen.corner_radius_small, R.dimen.corner_radius_small, R.dimen.corner_radius_small)); // Check that the outline box's top end corner radius is cornerRadiusSmall. onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusTopEnd(cornerRadiusSmall)); // Set the outline box's corner radii to corner_radius_medium. onView(withId(R.id.textinput_box_outline)) .perform( setBoxCornerRadii( R.dimen.corner_radius_medium, R.dimen.corner_radius_medium, R.dimen.corner_radius_medium, R.dimen.corner_radius_medium)); // Check that the outline box's top end corner radius is cornerRadiusMedium. onView(withId(R.id.textinput_box_outline)).check(isBoxCornerRadiusTopEnd(cornerRadiusMedium)); } @UiThreadTest @Test @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O) public void hintSetOnNestedEditText_propagateInnerHintToAutofillProvider() { final Activity activity = activityTestRule.getActivity(); TextInputLayout textInputLayout = activity.findViewById(R.id.textinput_layout_without_hint); ViewStructureImpl structure = new ViewStructureImpl(); textInputLayout.dispatchProvideAutofillStructure(structure, /* flags= */ 0); final ViewStructureImpl editText = structure.getChildAt(0); assertEquals(EditText.class.getName(), editText.getClassName()); assertEquals(structure.getAutofillId(), textInputLayout.getAutofillId()); assertEquals("Nested hint", editText.getHint().toString()); } @UiThreadTest @Test @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O) public void hintSetOnOuterLayout_propagateOuterHintToAutofillProvider() { final Activity activity = activityTestRule.getActivity(); TextInputLayout textInputLayout = activity.findViewById(R.id.textinput_layout_with_hint); ViewStructureImpl structure = new ViewStructureImpl(); textInputLayout.dispatchProvideAutofillStructure(structure, /* flags= */ 0); final ViewStructureImpl editText = structure.getChildAt(0); assertEquals(EditText.class.getName(), editText.getClassName()); assertEquals(structure.getAutofillId(), textInputLayout.getAutofillId()); assertEquals("Outer hint", editText.getHint().toString()); } @UiThreadTest @Test public void testDropdownMenu_nonEditable_endIconIsNotFocusableOrClickable() { final Activity activity = activityTestRule.getActivity(); final TextInputLayout textInputLayout = activity.findViewById(R.id.textinput_noedittext); final AutoCompleteTextView editText = new AutoCompleteTextView(activity); textInputLayout.setEndIconMode(TextInputLayout.END_ICON_DROPDOWN_MENU); editText.setKeyListener(null); // This makes the EditText not-editable textInputLayout.addView(editText); assertThat(textInputLayout.getEndIconView().isFocusable()).isFalse(); assertThat(textInputLayout.getEndIconView().isClickable()).isFalse(); } @UiThreadTest @Test public void testDropdownMenu_editable_endIconIsFocusableAndClickable() { final Activity activity = activityTestRule.getActivity(); final TextInputLayout textInputLayout = activity.findViewById(R.id.textinput_noedittext); final AutoCompleteTextView editText = new AutoCompleteTextView(activity); textInputLayout.setEndIconMode(TextInputLayout.END_ICON_DROPDOWN_MENU); textInputLayout.addView(editText); assertThat(textInputLayout.getEndIconView().isFocusable()).isTrue(); assertThat(textInputLayout.getEndIconView().isClickable()).isTrue(); } private static ViewAssertion isHintExpanded(final boolean expanded) { return (view, noViewFoundException) -> { assertTrue(view instanceof TextInputLayout); assertEquals(expanded, ((TextInputLayout) view).isHintExpanded()); }; } private static ViewAssertion isBoxStrokeColor(@ColorInt final int boxStrokeColor) { return (view, noViewFoundException) -> { assertTrue(view instanceof TextInputLayout); assertEquals(boxStrokeColor, ((TextInputLayout) view).getBoxStrokeColor()); }; } private static ViewAssertion isBoxStrokeErrorColor(final ColorStateList boxStrokeColor) { return (view, noViewFoundException) -> { assertTrue(view instanceof TextInputLayout); assertEquals(boxStrokeColor, ((TextInputLayout) view).getBoxStrokeErrorColor()); }; } private static ViewAssertion isBoxBackgroundColor(@ColorInt final int boxBackgroundColor) { return (view, noViewFoundException) -> { assertTrue(view instanceof TextInputLayout); assertEquals(boxBackgroundColor, ((TextInputLayout) view).getBoxBackgroundColor()); }; } private static ViewAssertion isShapeAppearanceModel( @NonNull ShapeAppearanceModel shapeAppearanceModelt) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); assertEquals(shapeAppearanceModelt, ((TextInputLayout) view).getShapeAppearanceModel()); }; } private static ViewAssertion isCornerFamily(Class cornerFamily) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); ShapeAppearanceModel shapeAppearanceModel = ((TextInputLayout) view).getShapeAppearanceModel(); assertThat(shapeAppearanceModel.getTopLeftCorner()).isInstanceOf(cornerFamily); assertThat(shapeAppearanceModel.getTopRightCorner()).isInstanceOf(cornerFamily); assertThat(shapeAppearanceModel.getBottomRightCorner()).isInstanceOf(cornerFamily); assertThat(shapeAppearanceModel.getBottomLeftCorner()).isInstanceOf(cornerFamily); }; } private static ViewAssertion isCornerFamilyTopLeft( Class cornerFamily) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); ShapeAppearanceModel shapeAppearanceModel = ((TextInputLayout) view).getShapeAppearanceModel(); assertThat(shapeAppearanceModel.getTopLeftCorner()).isInstanceOf(cornerFamily); }; } private static ViewAssertion isCornerFamilyTopRight( Class cornerFamily) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); ShapeAppearanceModel shapeAppearanceModel = ((TextInputLayout) view).getShapeAppearanceModel(); assertThat(shapeAppearanceModel.getTopRightCorner()).isInstanceOf(cornerFamily); }; } private static ViewAssertion isCornerFamilyBottomLeft( Class cornerFamily) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); ShapeAppearanceModel shapeAppearanceModel = ((TextInputLayout) view).getShapeAppearanceModel(); assertThat(shapeAppearanceModel.getBottomLeftCorner()).isInstanceOf(cornerFamily); }; } private static ViewAssertion isCornerFamilyBottomRight( Class cornerFamily) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); ShapeAppearanceModel shapeAppearanceModel = ((TextInputLayout) view).getShapeAppearanceModel(); assertThat(shapeAppearanceModel.getBottomRightCorner()).isInstanceOf(cornerFamily); }; } private static ViewAssertion isBoxCornerRadiusTopStart(final float boxCornerRadiusTopStart) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); assertEquals( boxCornerRadiusTopStart, ((TextInputLayout) view).getBoxCornerRadiusTopStart(), 0.01); }; } private static ViewAssertion isBoxCornerRadiusTopEnd(final float boxCornerRadiusTopEnd) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); assertEquals( boxCornerRadiusTopEnd, ((TextInputLayout) view).getBoxCornerRadiusTopEnd(), 0.01); }; } private static ViewAssertion isBoxCornerRadiusBottomEnd(final float boxCornerRadiusBottomEnd) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); assertEquals( boxCornerRadiusBottomEnd, ((TextInputLayout) view).getBoxCornerRadiusBottomEnd(), 0.01); }; } private static ViewAssertion isBoxCornerRadiusBottomStart( final float boxCornerRadiusBottomStart) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); assertEquals( boxCornerRadiusBottomStart, ((TextInputLayout) view).getBoxCornerRadiusBottomStart(), 0.01); }; } private static ViewAssertion isBoxCornerRadiusTopLeft(final float boxCornerRadius) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); assertEquals( boxCornerRadius, ((TextInputLayout) view).getBoxBackground().getTopLeftCornerResolvedSize(), 0.01); }; } private static ViewAssertion isBoxCornerRadiusTopRight(final float boxCornerRadius) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); assertEquals( boxCornerRadius, ((TextInputLayout) view).getBoxBackground().getTopRightCornerResolvedSize(), 0.01); }; } private static ViewAssertion isBoxCornerRadiusBottomLeft(final float boxCornerRadius) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); assertEquals( boxCornerRadius, ((TextInputLayout) view).getBoxBackground().getBottomLeftCornerResolvedSize(), 0.01); }; } private static ViewAssertion isBoxCornerRadiusBottomRight(final float boxCornerRadius) { return (view, noViewFoundException) -> { assertThat(view).isInstanceOf(TextInputLayout.class); assertEquals( boxCornerRadius, ((TextInputLayout) view).getBoxBackground().getBottomRightCornerResolvedSize(), 0.01); }; } private static ViewAssertion isCutoutOpen(final boolean open) { return (view, noViewFoundException) -> { assertTrue(view instanceof TextInputLayout); assertEquals(open, ((TextInputLayout) view).cutoutIsOpen()); }; } }