Testing appearance-related APIs on NavigationView.

Also fix a bug where setting item background wouldn't update
the navigation view content. In addition, mark a few method
signatures with @Nullable where appropriate.

Bug: 26793013
Change-Id: Ie91c376d73beb7acb317510ac8322771ca17b66a
diff --git a/design/src/android/support/design/internal/NavigationMenuPresenter.java b/design/src/android/support/design/internal/NavigationMenuPresenter.java
index cb95f4f..609795f 100644
--- a/design/src/android/support/design/internal/NavigationMenuPresenter.java
+++ b/design/src/android/support/design/internal/NavigationMenuPresenter.java
@@ -238,12 +238,14 @@
         updateMenuView(false);
     }
 
+    @Nullable
     public Drawable getItemBackground() {
         return mItemBackground;
     }
 
-    public void setItemBackground(Drawable itemBackground) {
+    public void setItemBackground(@Nullable Drawable itemBackground) {
         mItemBackground = itemBackground;
+        updateMenuView(false);
     }
 
     public void setUpdateSuspended(boolean updateSuspended) {
diff --git a/design/src/android/support/design/widget/NavigationView.java b/design/src/android/support/design/widget/NavigationView.java
index a73dc65..42f4eed 100644
--- a/design/src/android/support/design/widget/NavigationView.java
+++ b/design/src/android/support/design/widget/NavigationView.java
@@ -297,7 +297,7 @@
     }
 
     /**
-     * Returns the tint which is applied to our item's icons.
+     * Returns the tint which is applied to our menu items' icons.
      *
      * @see #setItemIconTintList(ColorStateList)
      *
@@ -309,7 +309,7 @@
     }
 
     /**
-     * Set the tint which is applied to our item's icons.
+     * Set the tint which is applied to our menu items' icons.
      *
      * @param tint the tint to apply.
      *
@@ -320,7 +320,7 @@
     }
 
     /**
-     * Returns the tint which is applied to our item's icons.
+     * Returns the tint which is applied to our menu items' icons.
      *
      * @see #setItemTextColor(ColorStateList)
      *
@@ -332,7 +332,7 @@
     }
 
     /**
-     * Set the text color which is text to our items.
+     * Set the text color to be used on our menu items.
      *
      * @see #getItemTextColor()
      *
@@ -343,18 +343,19 @@
     }
 
     /**
-     * Returns the background drawable for the menu items.
+     * Returns the background drawable for our menu items.
      *
      * @see #setItemBackgroundResource(int)
      *
      * @attr ref R.styleable#NavigationView_itemBackground
      */
+    @Nullable
     public Drawable getItemBackground() {
         return mPresenter.getItemBackground();
     }
 
     /**
-     * Set the background of the menu items to the given resource.
+     * Set the background of our menu items to the given resource.
      *
      * @param resId The identifier of the resource.
      *
@@ -365,12 +366,12 @@
     }
 
     /**
-     * Set the background of the menu items to a given resource. The resource should refer to
-     * a Drawable object or 0 to use the background background.
+     * Set the background of our menu items to a given resource. The resource should refer to
+     * a Drawable object or null to use the default background set on this navigation menu.
      *
      * @attr ref R.styleable#NavigationView_itemBackground
      */
-    public void setItemBackground(Drawable itemBackground) {
+    public void setItemBackground(@Nullable Drawable itemBackground) {
         mPresenter.setItemBackground(itemBackground);
     }
 
diff --git a/design/tests/res/color/color_state_list_lilac.xml b/design/tests/res/color/color_state_list_lilac.xml
new file mode 100644
index 0000000..f0b2791
--- /dev/null
+++ b/design/tests/res/color/color_state_list_lilac.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/lilac_disabled" />
+    <item android:color="@color/lilac_default"/>
+</selector>
+
diff --git a/design/tests/res/color/color_state_list_red_translucent.xml b/design/tests/res/color/color_state_list_red_translucent.xml
new file mode 100644
index 0000000..fdf8b2b
--- /dev/null
+++ b/design/tests/res/color/color_state_list_red_translucent.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/red_translucent"/>
+</selector>
+
diff --git a/design/tests/res/drawable/test_background_blue.xml b/design/tests/res/drawable/test_background_blue.xml
new file mode 100644
index 0000000..fe4bca2
--- /dev/null
+++ b/design/tests/res/drawable/test_background_blue.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid
+        android:color="@color/test_blue" />
+</shape>
\ No newline at end of file
diff --git a/design/tests/res/drawable/test_background_green.xml b/design/tests/res/drawable/test_background_green.xml
new file mode 100644
index 0000000..b90d9bc
--- /dev/null
+++ b/design/tests/res/drawable/test_background_green.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid
+        android:color="@color/test_green" />
+</shape>
\ No newline at end of file
diff --git a/design/tests/res/drawable/test_drawable_blue.xml b/design/tests/res/drawable/test_drawable_blue.xml
new file mode 100644
index 0000000..f228e34
--- /dev/null
+++ b/design/tests/res/drawable/test_drawable_blue.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <size
+        android:width="@dimen/drawable_large_size"
+        android:height="@dimen/drawable_small_size" />
+    <solid
+        android:color="@color/test_blue" />
+</shape>
\ No newline at end of file
diff --git a/design/tests/res/drawable/test_drawable_green.xml b/design/tests/res/drawable/test_drawable_green.xml
new file mode 100644
index 0000000..1d83f0f
--- /dev/null
+++ b/design/tests/res/drawable/test_drawable_green.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <size
+        android:width="@dimen/drawable_medium_size"
+        android:height="@dimen/drawable_large_size" />
+    <solid
+        android:color="@color/test_green" />
+</shape>
\ No newline at end of file
diff --git a/design/tests/res/drawable/test_drawable_red.xml b/design/tests/res/drawable/test_drawable_red.xml
new file mode 100644
index 0000000..58dbe73
--- /dev/null
+++ b/design/tests/res/drawable/test_drawable_red.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <size
+        android:width="@dimen/drawable_small_size"
+        android:height="@dimen/drawable_medium_size" />
+    <solid
+        android:color="@color/test_red" />
+</shape>
\ No newline at end of file
diff --git a/design/tests/res/layout/design_navigation_view.xml b/design/tests/res/layout/design_navigation_view.xml
index 3f4e03b..1789843 100644
--- a/design/tests/res/layout/design_navigation_view.xml
+++ b/design/tests/res/layout/design_navigation_view.xml
@@ -47,7 +47,7 @@
         app:menu="@menu/navigation_view_content"
         app:itemIconTint="@color/emerald_translucent"
         app:itemTextColor="@color/emerald_text"
-        app:itemBackground="@color/sand_fill"
+        app:itemBackground="@color/sand_default"
         app:itemTextAppearance="@style/TextMediumStyle" />
 
 </android.support.v4.widget.DrawerLayout>
diff --git a/design/tests/res/menu/navigation_view_content.xml b/design/tests/res/menu/navigation_view_content.xml
index 24fd830..748b79a 100644
--- a/design/tests/res/menu/navigation_view_content.xml
+++ b/design/tests/res/menu/navigation_view_content.xml
@@ -15,11 +15,14 @@
 -->
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/destination_home"
-          android:title="@string/navigate_home" />
+          android:title="@string/navigate_home"
+          android:icon="@drawable/test_drawable_red" />
     <item android:id="@+id/destination_profile"
-          android:title="@string/navigate_profile" />
+          android:title="@string/navigate_profile"
+          android:icon="@drawable/test_drawable_green" />
     <item android:id="@+id/destination_people"
-          android:title="@string/navigate_people" />
+          android:title="@string/navigate_people"
+          android:icon="@drawable/test_drawable_blue" />
     <item android:id="@+id/destination_settings"
           android:title="@string/navigate_settings" />
 </menu>
diff --git a/design/tests/res/values/colors.xml b/design/tests/res/values/colors.xml
index d1a6a1c..c7fa603 100644
--- a/design/tests/res/values/colors.xml
+++ b/design/tests/res/values/colors.xml
@@ -17,5 +17,16 @@
 <resources>
     <color name="emerald_translucent">#8020A060</color>
     <color name="emerald_text">#30B050</color>
-    <color name="sand_fill">#F0E020</color>
+    <color name="red_translucent">#90FF2040</color>
+
+    <color name="lilac_default">#F080F0</color>
+    <color name="lilac_disabled">#F0A0FF</color>
+    <color name="sand_default">#F0B000</color>
+    <color name="sand_disabled">#FFC080</color>
+    <color name="ocean_default">#50C0FF</color>
+    <color name="ocean_disabled">#90F0FF</color>
+
+    <color name="test_red">#FF6030</color>
+    <color name="test_green">#50E080</color>
+    <color name="test_blue">#3050CF</color>
 </resources>
diff --git a/design/tests/res/values/dimens.xml b/design/tests/res/values/dimens.xml
index c402941..94c2734 100644
--- a/design/tests/res/values/dimens.xml
+++ b/design/tests/res/values/dimens.xml
@@ -19,5 +19,10 @@
     <dimen name="tab_width_limit_large">120dip</dimen>
     <dimen name="bottom_sheet_peek_height">128dp</dimen>
 
+    <dimen name="text_small_size">16sp</dimen>
     <dimen name="text_medium_size">20sp</dimen>
+
+    <dimen name="drawable_small_size">12dip</dimen>
+    <dimen name="drawable_medium_size">16dip</dimen>
+    <dimen name="drawable_large_size">20dip</dimen>
 </resources>
\ No newline at end of file
diff --git a/design/tests/res/values/styles.xml b/design/tests/res/values/styles.xml
index 1fda2e6..4fc946b 100644
--- a/design/tests/res/values/styles.xml
+++ b/design/tests/res/values/styles.xml
@@ -14,6 +14,10 @@
      limitations under the License.
 -->
 <resources>
+    <style name="TextSmallStyle" parent="@android:style/TextAppearance">
+        <item name="android:textSize">@dimen/text_small_size</item>
+    </style>
+
     <style name="TextMediumStyle" parent="@android:style/TextAppearance.Medium">
         <item name="android:textSize">@dimen/text_medium_size</item>
     </style>
diff --git a/design/tests/src/android/support/design/testutils/NavigationViewActions.java b/design/tests/src/android/support/design/testutils/NavigationViewActions.java
new file mode 100644
index 0000000..c2dd02f
--- /dev/null
+++ b/design/tests/src/android/support/design/testutils/NavigationViewActions.java
@@ -0,0 +1,169 @@
+/*
+ * 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 android.support.design.testutils;
+
+import android.content.res.ColorStateList;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+import android.support.annotation.StyleRes;
+import android.support.design.widget.NavigationView;
+import android.support.design.widget.TabLayout;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.view.View;
+import org.hamcrest.Matcher;
+
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
+
+public class NavigationViewActions {
+    /**
+     * Sets item text appearance on the content of the navigation view.
+     */
+    public static ViewAction setItemTextAppearance(final @StyleRes int resId) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return isDisplayed();
+            }
+
+            @Override
+            public String getDescription() {
+                return "Set item text appearance";
+            }
+
+            @Override
+            public void perform(UiController uiController, View view) {
+                uiController.loopMainThreadUntilIdle();
+
+                NavigationView navigationView = (NavigationView) view;
+                navigationView.setItemTextAppearance(resId);
+
+                uiController.loopMainThreadUntilIdle();
+            }
+        };
+    }
+
+    /**
+     * Sets item text color on the content of the navigation view.
+     */
+    public static ViewAction setItemTextColor(final ColorStateList textColor) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return isDisplayed();
+            }
+
+            @Override
+            public String getDescription() {
+                return "Set item text color";
+            }
+
+            @Override
+            public void perform(UiController uiController, View view) {
+                uiController.loopMainThreadUntilIdle();
+
+                NavigationView navigationView = (NavigationView) view;
+                navigationView.setItemTextColor(textColor);
+
+                uiController.loopMainThreadUntilIdle();
+            }
+        };
+    }
+
+    /**
+     * Sets item background on the content of the navigation view.
+     */
+    public static ViewAction setItemBackground(final Drawable itemBackground) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return isDisplayed();
+            }
+
+            @Override
+            public String getDescription() {
+                return "Set item background";
+            }
+
+            @Override
+            public void perform(UiController uiController, View view) {
+                uiController.loopMainThreadUntilIdle();
+
+                NavigationView navigationView = (NavigationView) view;
+                navigationView.setItemBackground(itemBackground);
+
+                uiController.loopMainThreadUntilIdle();
+            }
+        };
+    }
+
+    /**
+     * Sets item background on the content of the navigation view.
+     */
+    public static ViewAction setItemBackgroundResource(final @DrawableRes int resId) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return isDisplayed();
+            }
+
+            @Override
+            public String getDescription() {
+                return "Set item background";
+            }
+
+            @Override
+            public void perform(UiController uiController, View view) {
+                uiController.loopMainThreadUntilIdle();
+
+                NavigationView navigationView = (NavigationView) view;
+                navigationView.setItemBackgroundResource(resId);
+
+                uiController.loopMainThreadUntilIdle();
+            }
+        };
+    }
+
+    /**
+     * Sets item icon tint list on the content of the navigation view.
+     */
+    public static ViewAction setItemIconTintList(final @Nullable ColorStateList tint) {
+        return new ViewAction() {
+            @Override
+            public Matcher<View> getConstraints() {
+                return isDisplayed();
+            }
+
+            @Override
+            public String getDescription() {
+                return "Set item icon tint list";
+            }
+
+            @Override
+            public void perform(UiController uiController, View view) {
+                uiController.loopMainThreadUntilIdle();
+
+                NavigationView navigationView = (NavigationView) view;
+                navigationView.setItemIconTintList(tint);
+
+                uiController.loopMainThreadUntilIdle();
+            }
+        };
+    }
+}
diff --git a/design/tests/src/android/support/design/testutils/TestUtils.java b/design/tests/src/android/support/design/testutils/TestUtils.java
new file mode 100644
index 0000000..3255fb1
--- /dev/null
+++ b/design/tests/src/android/support/design/testutils/TestUtils.java
@@ -0,0 +1,95 @@
+/*
+ * 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 android.support.design.testutils;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
+import android.support.annotation.NonNull;
+import junit.framework.Assert;
+
+public class TestUtils {
+    /**
+     * Checks whether all the pixels in the specified drawable are of the same specified color.
+     *
+     * In case there is a color mismatch, the behavior of this method depends on the
+     * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
+     * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
+     * <code>Assert.fail</code> with detailed description of the mismatch.
+     */
+    public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Drawable drawable,
+            int drawableWidth, int drawableHeight, boolean callSetBounds, @ColorInt int color,
+            int allowedComponentVariance, boolean throwExceptionIfFails) {
+        // Create a bitmap
+        Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight, Bitmap.Config.ARGB_8888);
+        // Create a canvas that wraps the bitmap
+        Canvas canvas = new Canvas(bitmap);
+        if (callSetBounds) {
+            // Configure the drawable to have bounds that match the passed size
+            drawable.setBounds(0, 0, drawableWidth, drawableHeight);
+        }
+        // And ask the drawable to draw itself to the canvas / bitmap
+        drawable.draw(canvas);
+
+        try {
+            int[] rowPixels = new int[drawableWidth];
+            for (int row = 0; row < drawableHeight; row++) {
+                bitmap.getPixels(rowPixels, 0, drawableWidth, 0, row, drawableWidth, 1);
+                for (int column = 0; column < drawableWidth; column++) {
+                    int sourceAlpha = Color.alpha(rowPixels[column]);
+                    int sourceRed = Color.red(rowPixels[column]);
+                    int sourceGreen = Color.green(rowPixels[column]);
+                    int sourceBlue = Color.blue(rowPixels[column]);
+
+                    int expectedAlpha = Color.alpha(color);
+                    int expectedRed = Color.red(color);
+                    int expectedGreen = Color.green(color);
+                    int expectedBlue = Color.blue(color);
+
+                    int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha);
+                    int varianceRed = Math.abs(sourceRed - expectedRed);
+                    int varianceGreen = Math.abs(sourceGreen - expectedGreen);
+                    int varianceBlue = Math.abs(sourceBlue - expectedBlue);
+
+                    boolean isColorMatch = (varianceAlpha <= allowedComponentVariance)
+                            && (varianceRed <= allowedComponentVariance)
+                            && (varianceGreen <= allowedComponentVariance)
+                            && (varianceBlue <= allowedComponentVariance);
+
+                    if (!isColorMatch) {
+                        String mismatchDescription = failMessagePrefix
+                                + ": expected all drawable colors to be ["
+                                + expectedAlpha + "," + expectedRed + ","
+                                + expectedGreen + "," + expectedBlue
+                                + "] but at position (" + row + "," + column + ") found ["
+                                + sourceAlpha + "," + sourceRed + ","
+                                + sourceGreen + "," + sourceBlue + "]";
+                        if (throwExceptionIfFails) {
+                            throw new RuntimeException(mismatchDescription);
+                        } else {
+                            Assert.fail(mismatchDescription);
+                        }
+                    }
+                }
+            }
+        } finally {
+            bitmap.recycle();
+        }
+    }
+}
\ No newline at end of file
diff --git a/design/tests/src/android/support/design/testutils/TestUtilsMatchers.java b/design/tests/src/android/support/design/testutils/TestUtilsMatchers.java
index 049e7a5..a44caff 100644
--- a/design/tests/src/android/support/design/testutils/TestUtilsMatchers.java
+++ b/design/tests/src/android/support/design/testutils/TestUtilsMatchers.java
@@ -16,10 +16,18 @@
 
 package android.support.design.testutils;
 
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
 import android.support.test.espresso.matcher.BoundedMatcher;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.widget.TextViewCompat;
 import android.view.View;
+import android.view.ViewParent;
+import android.widget.TextView;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
 
 public class TestUtilsMatchers {
     /**
@@ -71,4 +79,163 @@
             }
         };
     }
+
+    /**
+     * Returns a matcher that matches TextViews with the specified text size.
+     */
+    public static Matcher withTextSize(final float textSize) {
+        return new BoundedMatcher<View, TextView>(TextView.class) {
+            private String failedCheckDescription;
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText(failedCheckDescription);
+            }
+
+            @Override
+            public boolean matchesSafely(final TextView view) {
+                final float ourTextSize = view.getTextSize();
+                if (Math.abs(textSize - ourTextSize) > 1.0f) {
+                    failedCheckDescription =
+                            "text size " + ourTextSize + " is different than expected " + textSize;
+                    return false;
+                }
+                return true;
+            }
+        };
+    }
+
+    /**
+     * Returns a matcher that matches TextViews with the specified text color.
+     */
+    public static Matcher withTextColor(final @ColorInt int textColor) {
+        return new BoundedMatcher<View, TextView>(TextView.class) {
+            private String failedCheckDescription;
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText(failedCheckDescription);
+            }
+
+            @Override
+            public boolean matchesSafely(final TextView view) {
+                final @ColorInt int ourTextColor = view.getTextColors().getDefaultColor();
+                if (ourTextColor != textColor) {
+                    int ourAlpha = Color.alpha(ourTextColor);
+                    int ourRed = Color.red(ourTextColor);
+                    int ourGreen = Color.green(ourTextColor);
+                    int ourBlue = Color.blue(ourTextColor);
+
+                    int expectedAlpha = Color.alpha(textColor);
+                    int expectedRed = Color.red(textColor);
+                    int expectedGreen = Color.green(textColor);
+                    int expectedBlue = Color.blue(textColor);
+
+                    failedCheckDescription =
+                            "expected color to be ["
+                                    + expectedAlpha + "," + expectedRed + ","
+                                    + expectedGreen + "," + expectedBlue
+                                    + "] but found ["
+                                    + ourAlpha + "," + ourRed + ","
+                                    + ourGreen + "," + ourBlue + "]";
+                    return false;
+                }
+                return true;
+            }
+        };
+    }
+
+    /**
+     * Returns a matcher that matches TextViews whose start drawable is filled with the specified
+     * fill color.
+     */
+    public static Matcher withStartDrawableFilledWith(final @ColorInt int fillColor,
+            final int allowedComponentVariance) {
+        return new BoundedMatcher<View, TextView>(TextView.class) {
+            private String failedCheckDescription;
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText(failedCheckDescription);
+            }
+
+            @Override
+            public boolean matchesSafely(final TextView view) {
+                Drawable[] compoundDrawables = view.getCompoundDrawables();
+                boolean isRtl =
+                        (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL);
+                Drawable startDrawable = isRtl ? compoundDrawables[2] : compoundDrawables[0];
+                if (startDrawable == null) {
+                    failedCheckDescription = "no start drawable";
+                    return false;
+                }
+                try {
+                    TestUtils.assertAllPixelsOfColor("",
+                            startDrawable, startDrawable.getIntrinsicWidth(),
+                            startDrawable.getIntrinsicHeight(), true,
+                            fillColor, allowedComponentVariance, true);
+                } catch (Throwable t) {
+                    failedCheckDescription = t.getMessage();
+                    return false;
+                }
+                return true;
+            }
+        };
+    }
+
+    /**
+     * Returns a matcher that matches Views with the specified background fill color.
+     */
+    public static Matcher withBackgroundFill(final @ColorInt int fillColor) {
+        return new BoundedMatcher<View, View>(View.class) {
+            private String failedCheckDescription;
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText(failedCheckDescription);
+            }
+
+            @Override
+            public boolean matchesSafely(final View view) {
+                Drawable background = view.getBackground();
+                try {
+                    TestUtils.assertAllPixelsOfColor("",
+                            background, view.getWidth(), view.getHeight(), true,
+                            fillColor, 0, true);
+                } catch (Throwable t) {
+                    failedCheckDescription = t.getMessage();
+                    return false;
+                }
+                return true;
+            }
+        };
+    }
+
+    /**
+     * Returns a matcher that matches {@link View}s based on the given parent type.
+     *
+     * @param parentMatcher the type of the parent to match on
+     */
+    public static Matcher<View> isChildOfA(final Matcher<View> parentMatcher) {
+        return new TypeSafeMatcher<View>() {
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("is child of a: ");
+                parentMatcher.describeTo(description);
+            }
+
+            @Override
+            public boolean matchesSafely(View view) {
+                final ViewParent viewParent = view.getParent();
+                if (!(viewParent instanceof View)) {
+                    return false;
+                }
+                if (parentMatcher.matches(viewParent)) {
+                    return true;
+                }
+                return false;
+            }
+        };
+    }
+
 }
diff --git a/design/tests/src/android/support/design/widget/NavigationViewTest.java b/design/tests/src/android/support/design/widget/NavigationViewTest.java
index 0f99cb5..5238e02 100755
--- a/design/tests/src/android/support/design/widget/NavigationViewTest.java
+++ b/design/tests/src/android/support/design/widget/NavigationViewTest.java
@@ -16,15 +16,24 @@
 package android.support.design.widget;
 
 import android.content.res.Resources;
+import android.support.annotation.ColorInt;
 import android.support.design.test.R;
+import android.support.v4.content.res.ResourcesCompat;
 import android.support.v4.view.GravityCompat;
 import android.support.v4.widget.DrawerLayout;
+import android.support.v7.widget.RecyclerView;
 import android.test.suitebuilder.annotation.SmallTest;
+import org.hamcrest.Matcher;
 import org.junit.Before;
 import org.junit.Test;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import static android.support.design.testutils.DrawerLayoutActions.closeDrawer;
 import static android.support.design.testutils.DrawerLayoutActions.openDrawer;
+import static android.support.design.testutils.NavigationViewActions.*;
+import static android.support.design.testutils.TestUtilsMatchers.*;
 import static android.support.test.espresso.Espresso.onView;
 import static android.support.test.espresso.assertion.ViewAssertions.matches;
 import static android.support.test.espresso.matcher.ViewMatchers.*;
@@ -32,6 +41,10 @@
 
 public class NavigationViewTest
         extends BaseInstrumentationTestCase<NavigationViewActivity> {
+    private static final int[] MENU_CONTENT_ITEM_IDS = { R.id.destination_home,
+            R.id.destination_profile, R.id.destination_people, R.id.destination_settings };
+    private Map<Integer, String> mMenuStringContent;
+
     private DrawerLayout mDrawerLayout;
 
     private NavigationView mNavigationView;
@@ -48,6 +61,14 @@
 
         // Close the drawer to reset the state for the next test
         onView(withId(R.id.drawer_layout)).perform(closeDrawer(GravityCompat.START));
+
+        final Resources res = activity.getResources();
+        mMenuStringContent = new HashMap<>(MENU_CONTENT_ITEM_IDS.length);
+        mMenuStringContent.put(R.id.destination_home, res.getString(R.string.navigate_home));
+        mMenuStringContent.put(R.id.destination_profile, res.getString(R.string.navigate_profile));
+        mMenuStringContent.put(R.id.destination_people, res.getString(R.string.navigate_people));
+        mMenuStringContent.put(R.id.destination_settings,
+                res.getString(R.string.navigate_settings));
     }
 
     @Test
@@ -56,16 +77,198 @@
         // Open our drawer
         onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START));
 
-        final Resources res = mActivityTestRule.getActivity().getResources();
-
         // Check that we have the expected menu items in our NavigationView
-        onView(allOf(withText(res.getString(R.string.navigate_home)),
-                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(isDisplayed()));
-        onView(allOf(withText(res.getString(R.string.navigate_profile)),
-                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(isDisplayed()));
-        onView(allOf(withText(res.getString(R.string.navigate_people)),
-                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(isDisplayed()));
-        onView(allOf(withText(res.getString(R.string.navigate_settings)),
-                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(isDisplayed()));
+        for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) {
+            onView(allOf(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i])),
+                    isDescendantOfA(withId(R.id.start_drawer)))).check(matches(isDisplayed()));
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testTextAppearance() {
+        // Open our drawer
+        onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START));
+
+        final Resources res = mActivityTestRule.getActivity().getResources();
+        final int defaultTextSize = res.getDimensionPixelSize(R.dimen.text_medium_size);
+
+        // Check the default style of the menu items in our NavigationView
+        for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) {
+            onView(allOf(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i])),
+                    isDescendantOfA(withId(R.id.start_drawer)))).check(
+                    matches(withTextSize(defaultTextSize)));
+        }
+
+        // Set a new text appearance on our NavigationView
+        onView(withId(R.id.start_drawer)).perform(setItemTextAppearance(R.style.TextSmallStyle));
+
+        // And check that all the menu items have the new style
+        final int newTextSize = res.getDimensionPixelSize(R.dimen.text_small_size);
+        for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) {
+            onView(allOf(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i])),
+                    isDescendantOfA(withId(R.id.start_drawer)))).check(
+                    matches(withTextSize(newTextSize)));
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testTextColor() {
+        // Open our drawer
+        onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START));
+
+        final Resources res = mActivityTestRule.getActivity().getResources();
+        final @ColorInt int defaultTextColor = ResourcesCompat.getColor(res,
+                R.color.emerald_text, null);
+
+        // Check the default text color of the menu items in our NavigationView
+        for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) {
+            onView(allOf(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i])),
+                    isDescendantOfA(withId(R.id.start_drawer)))).check(
+                    matches(withTextColor(defaultTextColor)));
+        }
+
+        // Set a new text color on our NavigationView
+        onView(withId(R.id.start_drawer)).perform(setItemTextColor(
+                ResourcesCompat.getColorStateList(res, R.color.color_state_list_lilac, null)));
+
+        // And check that all the menu items have the new color
+        final @ColorInt int newTextColor = ResourcesCompat.getColor(res,
+                R.color.lilac_default, null);
+        for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) {
+            onView(allOf(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i])),
+                    isDescendantOfA(withId(R.id.start_drawer)))).check(
+                    matches(withTextColor(newTextColor)));
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testBackground() {
+        // Open our drawer
+        onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START));
+
+        final Resources res = mActivityTestRule.getActivity().getResources();
+        final @ColorInt int defaultFillColor = ResourcesCompat.getColor(res,
+                R.color.sand_default, null);
+
+        // Check the default fill color of the menu items in our NavigationView
+        for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) {
+            // Note that here we're tying ourselves to the implementation details of the
+            // internal structure of the NavigationView. Specifically, we're looking at the
+            // direct child of RecyclerView which is expected to have the background set
+            // on it. If the internal implementation of NavigationView changes, the second
+            // Matcher below will need to be tweaked.
+            Matcher menuItemMatcher = allOf(
+                    hasDescendant(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i]))),
+                    isChildOfA(isAssignableFrom(RecyclerView.class)),
+                    isDescendantOfA(withId(R.id.start_drawer)));
+
+            onView(menuItemMatcher).check(matches(withBackgroundFill(defaultFillColor)));
+        }
+
+        // Set a new background (flat fill color) on our NavigationView
+        onView(withId(R.id.start_drawer)).perform(setItemBackgroundResource(
+                R.drawable.test_background_blue));
+
+        // And check that all the menu items have the new fill
+        final @ColorInt int newFillColorBlue = ResourcesCompat.getColor(res,
+                R.color.test_blue, null);
+        for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) {
+            Matcher menuItemMatcher = allOf(
+                    hasDescendant(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i]))),
+                    isChildOfA(isAssignableFrom(RecyclerView.class)),
+                    isDescendantOfA(withId(R.id.start_drawer)));
+
+            onView(menuItemMatcher).check(matches(withBackgroundFill(newFillColorBlue)));
+        }
+
+        // Set another new background on our NavigationView
+        onView(withId(R.id.start_drawer)).perform(setItemBackground(
+                ResourcesCompat.getDrawable(res, R.drawable.test_background_green, null)));
+
+        // And check that all the menu items have the new fill
+        final @ColorInt int newFillColorGreen = ResourcesCompat.getColor(res,
+                R.color.test_green, null);
+        for (int i = 0; i < MENU_CONTENT_ITEM_IDS.length; i++) {
+            Matcher menuItemMatcher = allOf(
+                    hasDescendant(withText(mMenuStringContent.get(MENU_CONTENT_ITEM_IDS[i]))),
+                    isChildOfA(isAssignableFrom(RecyclerView.class)),
+                    isDescendantOfA(withId(R.id.start_drawer)));
+
+            onView(menuItemMatcher).check(matches(withBackgroundFill(newFillColorGreen)));
+        }
+    }
+
+    @Test
+    @SmallTest
+    public void testIconTinting() {
+        // Open our drawer
+        onView(withId(R.id.drawer_layout)).perform(openDrawer(GravityCompat.START));
+
+        final Resources res = mActivityTestRule.getActivity().getResources();
+        final @ColorInt int defaultTintColor = ResourcesCompat.getColor(res,
+                R.color.emerald_translucent, null);
+
+        // We're allowing a margin of error in checking the color of the items' icons.
+        // This is due to the translucent color being used in the icon tinting
+        // and off-by-one discrepancies of SRC_IN when it's compositing
+        // translucent color. Note that all the checks below are written for the current
+        // logic on NavigationView that uses the default SRC_IN tint mode - effectively
+        // replacing all non-transparent pixels in the destination (original icon) with
+        // our translucent tint color.
+        final int allowedComponentVariance = 1;
+
+        // Note that here we're tying ourselves to the implementation details of the
+        // internal structure of the NavigationView. Specifically, we're checking the
+        // start drawable of the text view with the specific text. If the internal
+        // implementation of NavigationView changes, the second Matcher in the lookups
+        // below will need to be tweaked.
+        onView(allOf(withText(mMenuStringContent.get(R.id.destination_home)),
+                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(
+                    withStartDrawableFilledWith(defaultTintColor, allowedComponentVariance)));
+        onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)),
+                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(
+                    withStartDrawableFilledWith(defaultTintColor, allowedComponentVariance)));
+        onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)),
+                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(
+                    withStartDrawableFilledWith(defaultTintColor, allowedComponentVariance)));
+
+        final @ColorInt int newTintColor = ResourcesCompat.getColor(res,
+                R.color.red_translucent, null);
+
+        onView(withId(R.id.start_drawer)).perform(setItemIconTintList(
+                ResourcesCompat.getColorStateList(res, R.color.color_state_list_red_translucent,
+                        null)));
+        // Check that all menu items with icons now have icons tinted with the newly set color
+        onView(allOf(withText(mMenuStringContent.get(R.id.destination_home)),
+                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(
+                    withStartDrawableFilledWith(newTintColor, allowedComponentVariance)));
+        onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)),
+                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(
+                    withStartDrawableFilledWith(newTintColor, allowedComponentVariance)));
+        onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)),
+                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(
+                    withStartDrawableFilledWith(newTintColor, allowedComponentVariance)));
+
+        // And now remove all icon tinting
+        onView(withId(R.id.start_drawer)).perform(setItemIconTintList(null));
+        // And verify that all menu items with icons now have the original colors for their icons.
+        // Note that since there is no tinting at this point, we don't allow any color variance
+        // in these checks.
+        final @ColorInt int redIconColor = ResourcesCompat.getColor(res, R.color.test_red, null);
+        onView(allOf(withText(mMenuStringContent.get(R.id.destination_home)),
+                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(
+                    withStartDrawableFilledWith(redIconColor, 0)));
+        final @ColorInt int greenIconColor = ResourcesCompat.getColor(res, R.color.test_green,
+                null);
+        onView(allOf(withText(mMenuStringContent.get(R.id.destination_profile)),
+                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(
+                    withStartDrawableFilledWith(greenIconColor, 0)));
+        final @ColorInt int blueIconColor = ResourcesCompat.getColor(res, R.color.test_blue, null);
+        onView(allOf(withText(mMenuStringContent.get(R.id.destination_people)),
+                isDescendantOfA(withId(R.id.start_drawer)))).check(matches(
+                    withStartDrawableFilledWith(blueIconColor, 0)));
     }
 }