[1/2] Add Espresso test for CustomizationPickerActivity

Change-Id: I437eacd0abb7f153c94a826b35aa6c62837f0e29
diff --git a/src/com/android/customization/picker/CustomizationPickerActivity.java b/src/com/android/customization/picker/CustomizationPickerActivity.java
index 80cd7d9..60647d9 100644
--- a/src/com/android/customization/picker/CustomizationPickerActivity.java
+++ b/src/com/android/customization/picker/CustomizationPickerActivity.java
@@ -29,6 +29,7 @@
 import androidx.annotation.IdRes;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 import androidx.fragment.app.FragmentManager;
@@ -86,9 +87,10 @@
         CategoryFragmentHost, ThemeFragmentHost, GridFragmentHost, ClockFragmentHost {
 
     private static final String TAG = "CustomizationPickerActivity";
-    private static final String WALLPAPER_FLAVOR_EXTRA = "com.android.launcher3.WALLPAPER_FLAVOR";
-    private static final String WALLPAPER_FOCUS = "focus_wallpaper";
-    private static final String WALLPAPER_ONLY = "wallpaper_only";
+    @VisibleForTesting static final String WALLPAPER_FLAVOR_EXTRA =
+            "com.android.launcher3.WALLPAPER_FLAVOR";
+    @VisibleForTesting static final String WALLPAPER_FOCUS = "focus_wallpaper";
+    @VisibleForTesting static final String WALLPAPER_ONLY = "wallpaper_only";
 
     private WallpaperPickerDelegate mDelegate;
     private UserEventLogger mUserEventLogger;
diff --git a/tests/src/com/android/customization/picker/CustomizationPickerActivityTest.java b/tests/src/com/android/customization/picker/CustomizationPickerActivityTest.java
new file mode 100644
index 0000000..dd1581a
--- /dev/null
+++ b/tests/src/com/android/customization/picker/CustomizationPickerActivityTest.java
@@ -0,0 +1,160 @@
+package com.android.customization.picker;
+
+import static android.content.Intent.ACTION_SET_WALLPAPER;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.intent.matcher.IntentMatchers.filterEquals;
+import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isSelected;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
+import static com.android.customization.picker.CustomizationPickerActivity.WALLPAPER_FLAVOR_EXTRA;
+import static com.android.customization.picker.CustomizationPickerActivity.WALLPAPER_FOCUS;
+import static com.android.customization.picker.CustomizationPickerActivity.WALLPAPER_ONLY;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Intent;
+import android.text.TextUtils;
+
+import androidx.fragment.app.Fragment;
+import androidx.test.espresso.intent.Intents;
+import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.customization.picker.theme.ThemeFragment;
+import com.android.customization.testing.TestCustomizationInjector;
+import com.android.customization.testing.TestThemeManager;
+import com.android.wallpaper.R;
+import com.android.wallpaper.module.InjectorProvider;
+import com.android.wallpaper.picker.CategoryFragment;
+import com.android.wallpaper.picker.TopLevelPickerActivity;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link CustomizationPickerActivity}.
+ */
+@RunWith(AndroidJUnit4ClassRunner.class)
+public class CustomizationPickerActivityTest {
+
+    @Rule
+    public ActivityTestRule<CustomizationPickerActivity> mActivityRule =
+            new ActivityTestRule<>(CustomizationPickerActivity.class, false, false);
+
+    @Before
+    public void setUp() {
+        Intents.init();
+    }
+
+    @After
+    public void tearDown() {
+        mActivityRule.finishActivity();
+        Intents.release();
+    }
+
+    @Test
+    public void launchActivity_doesNotSupportCustomization_launchesTopLevelPickerActivity() {
+        TestThemeManager.setAvailable(false);
+
+        launchActivity();
+
+        Intents.intended(filterEquals(new Intent(mActivityRule.getActivity(),
+                TopLevelPickerActivity.class)));
+    }
+
+    // ----------------------------------------------------------------------
+    // Tests for customization supports.
+    // ----------------------------------------------------------------------
+
+    @Test
+    public void launchActivity_themeManagerIsAvailable_NavBarShowsStyleAndWallpaperItem() {
+        TestThemeManager.setAvailable(true);
+
+        launchActivity();
+
+        onView(withId(R.id.nav_theme)).check(matches(isCompletelyDisplayed()));
+        onView(withId(R.id.nav_wallpaper)).check(matches(isCompletelyDisplayed()));
+        onView(withId(R.id.nav_clock)).check(doesNotExist());
+        onView(withId(R.id.nav_grid)).check(doesNotExist());
+    }
+
+    @Test
+    public void launchActivity_navigateToTheStyleTabByDefault() {
+        TestThemeManager.setAvailable(true);
+
+        launchActivity();
+
+        onView(withId(R.id.nav_theme)).check(matches(isSelected()));
+        assertTrue(getCurrentShowingFragment() instanceof ThemeFragment);
+    }
+
+    @Test
+    public void launchActivity_withExtraWallpaperOnly_launchesTopLevelPickerActivity() {
+        TestThemeManager.setAvailable(true);
+
+        launchActivityWithFlavorExtra(WALLPAPER_ONLY);
+
+        // While receiving WALLPAPER_ONLY extra, it should launch TopLevelPickerActivity whatever it
+        // supports customization.
+        Intents.intended(filterEquals(new Intent(mActivityRule.getActivity(),
+                TopLevelPickerActivity.class)));
+    }
+
+    @Test
+    public void clickStyleButton_showsThemeFragment() {
+        TestThemeManager.setAvailable(true);
+        launchActivity();
+
+        onView(withId(R.id.nav_theme)).perform(click());
+
+        onView(withId(R.id.nav_theme)).check(matches(isSelected()));
+        assertTrue(getCurrentShowingFragment() instanceof ThemeFragment);
+    }
+
+    @Test
+    public void clickWallpaperButton_showsCategoryFragment() {
+        TestThemeManager.setAvailable(true);
+        launchActivity();
+
+        onView(withId(R.id.nav_wallpaper)).perform(click());
+
+        onView(withId(R.id.nav_wallpaper)).check(matches(isSelected()));
+        assertTrue(getCurrentShowingFragment() instanceof CategoryFragment);
+    }
+
+    @Test
+    public void launchActivity_withExtraWallpaperFocus_navigateToTheWallpaperTab() {
+        TestThemeManager.setAvailable(true);
+
+        launchActivityWithFlavorExtra(WALLPAPER_FOCUS);
+
+        onView(withId(R.id.nav_wallpaper)).check(matches(isSelected()));
+        assertTrue(getCurrentShowingFragment() instanceof CategoryFragment);
+    }
+
+    private void launchActivity() {
+        launchActivityWithFlavorExtra("");
+    }
+
+    private void launchActivityWithFlavorExtra(String extra) {
+        InjectorProvider.setInjector(new TestCustomizationInjector());
+        Intent intent = new Intent(ACTION_SET_WALLPAPER);
+        if (!TextUtils.isEmpty(extra)) {
+            intent.putExtra(WALLPAPER_FLAVOR_EXTRA, extra);
+        }
+        mActivityRule.launchActivity(intent);
+    }
+
+    private Fragment getCurrentShowingFragment() {
+        return mActivityRule.getActivity().getSupportFragmentManager()
+                .findFragmentById(R.id.fragment_container);
+    }
+}
diff --git a/tests/src/com/android/customization/testing/TestCustomizationInjector.java b/tests/src/com/android/customization/testing/TestCustomizationInjector.java
new file mode 100644
index 0000000..10b5934
--- /dev/null
+++ b/tests/src/com/android/customization/testing/TestCustomizationInjector.java
@@ -0,0 +1,74 @@
+package com.android.customization.testing;
+
+import android.content.Context;
+
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.customization.model.theme.OverlayManagerCompat;
+import com.android.customization.model.theme.ThemeBundleProvider;
+import com.android.customization.model.theme.ThemeManager;
+import com.android.customization.module.CustomizationInjector;
+import com.android.customization.module.CustomizationPreferences;
+import com.android.customization.module.ThemesUserEventLogger;
+import com.android.wallpaper.module.DrawableLayerResolver;
+import com.android.wallpaper.module.PackageStatusNotifier;
+import com.android.wallpaper.module.UserEventLogger;
+import com.android.wallpaper.module.WallpaperSetter;
+import com.android.wallpaper.testing.TestInjector;
+
+/**
+ * Test implementation of the dependency injector.
+ */
+public class TestCustomizationInjector extends TestInjector implements CustomizationInjector {
+    private CustomizationPreferences mCustomizationPreferences;
+    private ThemeManager mThemeManager;
+    private PackageStatusNotifier mPackageStatusNotifier;
+    private DrawableLayerResolver mDrawableLayerResolver;
+    private UserEventLogger mUserEventLogger;
+
+    @Override
+    public CustomizationPreferences getCustomizationPreferences(Context context) {
+        if (mCustomizationPreferences == null) {
+            mCustomizationPreferences = new TestDefaultCustomizationPreferences(context);
+        }
+        return mCustomizationPreferences;
+    }
+
+    @Override
+    public ThemeManager getThemeManager(
+            ThemeBundleProvider provider,
+            FragmentActivity activity,
+            WallpaperSetter wallpaperSetter,
+            OverlayManagerCompat overlayManagerCompat,
+            ThemesUserEventLogger logger) {
+        if (mThemeManager == null) {
+            mThemeManager = new TestThemeManager(provider, activity, wallpaperSetter,
+                    overlayManagerCompat, logger);
+        }
+        return mThemeManager;
+    }
+
+    @Override
+    public PackageStatusNotifier getPackageStatusNotifier(Context context) {
+        if (mPackageStatusNotifier == null) {
+            mPackageStatusNotifier =  new TestPackageStatusNotifier();
+        }
+        return mPackageStatusNotifier;
+    }
+
+    @Override
+    public DrawableLayerResolver getDrawableLayerResolver() {
+        if (mDrawableLayerResolver == null) {
+            mDrawableLayerResolver = new TestDrawableLayerResolver();
+        }
+        return mDrawableLayerResolver;
+    }
+
+    @Override
+    public UserEventLogger getUserEventLogger(Context unused) {
+        if (mUserEventLogger == null) {
+            mUserEventLogger = new TestThemesUserEventLogger();
+        }
+        return mUserEventLogger;
+    }
+}
diff --git a/tests/src/com/android/customization/testing/TestDefaultCustomizationPreferences.java b/tests/src/com/android/customization/testing/TestDefaultCustomizationPreferences.java
new file mode 100644
index 0000000..bcf5a5f
--- /dev/null
+++ b/tests/src/com/android/customization/testing/TestDefaultCustomizationPreferences.java
@@ -0,0 +1,41 @@
+package com.android.customization.testing;
+
+import android.content.Context;
+
+import com.android.customization.module.DefaultCustomizationPreferences;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Test implementation of {@link DefaultCustomizationPreferences}.
+ */
+public class TestDefaultCustomizationPreferences extends DefaultCustomizationPreferences {
+
+    private String mCustomThemes;
+    private final Set<String> mTabVisited = new HashSet<>();
+
+    public TestDefaultCustomizationPreferences(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getSerializedCustomThemes() {
+        return mCustomThemes;
+    }
+
+    @Override
+    public void storeCustomThemes(String serializedCustomThemes) {
+        mCustomThemes = serializedCustomThemes;
+    }
+
+    @Override
+    public boolean getTabVisited(String id) {
+        return mTabVisited.contains(id);
+    }
+
+    @Override
+    public void setTabVisited(String id) {
+        mTabVisited.add(id);
+    }
+}
diff --git a/tests/src/com/android/customization/testing/TestDrawableLayerResolver.java b/tests/src/com/android/customization/testing/TestDrawableLayerResolver.java
new file mode 100644
index 0000000..e507221
--- /dev/null
+++ b/tests/src/com/android/customization/testing/TestDrawableLayerResolver.java
@@ -0,0 +1,16 @@
+package com.android.customization.testing;
+
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+
+import com.android.wallpaper.module.DrawableLayerResolver;
+
+/**
+ * Test implementation of {@link DrawableLayerResolver}.
+ */
+public class TestDrawableLayerResolver implements DrawableLayerResolver {
+    @Override
+    public Drawable resolveLayer(LayerDrawable layerDrawable) {
+        return layerDrawable.getDrawable(0);
+    }
+}
diff --git a/tests/src/com/android/customization/testing/TestPackageStatusNotifier.java b/tests/src/com/android/customization/testing/TestPackageStatusNotifier.java
new file mode 100644
index 0000000..1e6a1a2
--- /dev/null
+++ b/tests/src/com/android/customization/testing/TestPackageStatusNotifier.java
@@ -0,0 +1,18 @@
+package com.android.customization.testing;
+
+import com.android.wallpaper.module.PackageStatusNotifier;
+
+/**
+ * Test implementation of {@link PackageStatusNotifier}.
+ */
+public class TestPackageStatusNotifier implements PackageStatusNotifier {
+    @Override
+    public void addListener(Listener listener, String action) {
+        // Do nothing
+    }
+
+    @Override
+    public void removeListener(Listener listener) {
+        // Do nothing
+    }
+}
diff --git a/tests/src/com/android/customization/testing/TestThemeManager.java b/tests/src/com/android/customization/testing/TestThemeManager.java
new file mode 100644
index 0000000..cc8567f
--- /dev/null
+++ b/tests/src/com/android/customization/testing/TestThemeManager.java
@@ -0,0 +1,35 @@
+package com.android.customization.testing;
+
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.customization.model.theme.OverlayManagerCompat;
+import com.android.customization.model.theme.ThemeBundleProvider;
+import com.android.customization.model.theme.ThemeManager;
+import com.android.customization.module.ThemesUserEventLogger;
+import com.android.wallpaper.module.WallpaperSetter;
+
+/**
+ * Test implementation of {@link ThemeManager}.
+ */
+public class TestThemeManager extends ThemeManager {
+
+    private static boolean sIsAvailable;
+
+    public TestThemeManager(
+            ThemeBundleProvider provider,
+            FragmentActivity activity,
+            WallpaperSetter wallpaperSetter,
+            OverlayManagerCompat overlayManagerCompat,
+            ThemesUserEventLogger logger) {
+        super(provider, activity, wallpaperSetter, overlayManagerCompat, logger);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return sIsAvailable;
+    }
+
+    public static void setAvailable(boolean available) {
+        sIsAvailable = available;
+    }
+}
diff --git a/tests/src/com/android/customization/testing/TestThemesUserEventLogger.java b/tests/src/com/android/customization/testing/TestThemesUserEventLogger.java
new file mode 100644
index 0000000..3600192
--- /dev/null
+++ b/tests/src/com/android/customization/testing/TestThemesUserEventLogger.java
@@ -0,0 +1,43 @@
+package com.android.customization.testing;
+
+import com.android.customization.model.clock.Clockface;
+import com.android.customization.model.grid.GridOption;
+import com.android.customization.model.theme.ThemeBundle;
+import com.android.customization.module.ThemesUserEventLogger;
+import com.android.wallpaper.testing.TestUserEventLogger;
+
+/**
+ * Test implementation of {@link ThemesUserEventLogger}.
+ */
+public class TestThemesUserEventLogger extends TestUserEventLogger
+        implements ThemesUserEventLogger {
+    @Override
+    public void logThemeSelected(ThemeBundle theme, boolean isCustomTheme) {
+        // Do nothing.
+    }
+
+    @Override
+    public void logThemeApplied(ThemeBundle theme, boolean isCustomTheme) {
+        // Do nothing.
+    }
+
+    @Override
+    public void logClockSelected(Clockface clock) {
+        // Do nothing.
+    }
+
+    @Override
+    public void logClockApplied(Clockface clock) {
+        // Do nothing.
+    }
+
+    @Override
+    public void logGridSelected(GridOption grid) {
+        // Do nothing.
+    }
+
+    @Override
+    public void logGridApplied(GridOption grid) {
+        // Do nothing.
+    }
+}