Chromium Code Reviews| Index: chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java |
| diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a797cea3881f3d7bcea079507a64b6e4dec1e60e |
| --- /dev/null |
| +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java |
| @@ -0,0 +1,188 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.chrome.browser.searchwidget; |
| + |
| +import android.app.Activity; |
| +import android.app.Instrumentation; |
| +import android.app.Instrumentation.ActivityMonitor; |
| +import android.content.Context; |
| +import android.content.Intent; |
| +import android.support.test.InstrumentationRegistry; |
| +import android.support.test.filters.SmallTest; |
| +import android.util.Pair; |
| +import android.view.View; |
| +import android.widget.FrameLayout; |
| +import android.widget.RemoteViews; |
| +import android.widget.TextView; |
| + |
| +import org.junit.Assert; |
| +import org.junit.Before; |
| +import org.junit.Test; |
| +import org.junit.runner.RunWith; |
| + |
| +import org.chromium.base.ContextUtils; |
| +import org.chromium.base.ThreadUtils; |
| +import org.chromium.base.test.util.AdvancedMockContext; |
| +import org.chromium.chrome.R; |
| +import org.chromium.chrome.browser.util.IntentUtils; |
| +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; |
| + |
| +import java.util.ArrayList; |
| +import java.util.List; |
| + |
| +/** |
| + * Tests for the SearchWidgetProvider. |
| + */ |
| +@RunWith(ChromeJUnit4ClassRunner.class) |
| +public class SearchWidgetProviderTest { |
| + private static final class TestDelegate extends SearchWidgetProvider.Delegate { |
| + public static final int[] ALL_IDS = {11684, 20170525}; |
| + |
| + public final List<Pair<Integer, RemoteViews>> mViews = |
| + new ArrayList<Pair<Integer, RemoteViews>>(); |
|
Ted C
2017/04/18 04:33:02
I think the second part can just be "new ArrayList
gone
2017/04/18 17:14:33
Done.
|
| + |
| + private TestDelegate(Context context) { |
| + super(context); |
| + } |
| + |
| + @Override |
| + protected int[] getAllSearchWidgetIds() { |
| + return ALL_IDS; |
| + } |
| + |
| + @Override |
| + protected void updateAppWidget(int id, RemoteViews views) { |
| + mViews.add(new Pair<Integer, RemoteViews>(id, views)); |
| + } |
| + } |
| + |
| + private static final class TestContext extends AdvancedMockContext { |
| + public TestContext() { |
| + // Wrapping the application context allows the ContextUtils to avoid writing to the real |
| + // SharedPreferences file. |
| + super(InstrumentationRegistry.getInstrumentation() |
| + .getTargetContext() |
|
Ted C
2017/04/18 04:33:02
this indentation looks quite wonky...clang format
gone
2017/04/18 17:14:33
Yep. Rejoice.
|
| + .getApplicationContext()); |
| + } |
| + } |
| + |
| + private static final String TEXT_GENERIC = "Search"; |
| + private static final String TEXT_SEARCH_ENGINE = "Stuff and Thangs"; |
| + private static final String TEXT_SEARCH_ENGINE_FULL = "Search with Stuff and Thangs"; |
| + |
| + private TestContext mContext; |
| + private TestDelegate mDelegate; |
| + |
| + @Before |
| + public void setUp() throws Exception { |
| + SearchActivity.disableForTests(); |
| + |
| + mContext = new TestContext(); |
| + ContextUtils.initApplicationContextForTests(mContext); |
| + |
| + mDelegate = new TestDelegate(mContext); |
| + SearchWidgetProvider.setDelegateForTest(mDelegate); |
| + } |
| + |
| + @Test |
| + @SmallTest |
| + public void testUpdateAll() { |
| + SearchWidgetProvider.handleAction(SearchWidgetProvider.ACTION_UPDATE_ALL_WIDGETS); |
| + |
| + // Without any idea of what the default search engine is, widgets should default to saying |
| + // just "Search". |
| + checkWidgetStates(TEXT_GENERIC, View.VISIBLE); |
| + |
| + // The microphone icon should disappear if voice queries are unavailable. |
| + mDelegate.mViews.clear(); |
| + SearchWidgetProvider.updateCachedVoiceSearchAvailability(false); |
| + checkWidgetStates(TEXT_GENERIC, View.GONE); |
| + |
| + // After recording that the default search engine is "X", it should say "Search with X". |
| + mDelegate.mViews.clear(); |
| + SearchWidgetProvider.updateCachedEngineName(TEXT_SEARCH_ENGINE); |
| + checkWidgetStates(TEXT_SEARCH_ENGINE_FULL, View.GONE); |
| + |
| + // The microphone icon should appear if voice queries are available. |
| + mDelegate.mViews.clear(); |
| + SearchWidgetProvider.updateCachedVoiceSearchAvailability(true); |
| + checkWidgetStates(TEXT_SEARCH_ENGINE_FULL, View.VISIBLE); |
| + } |
| + |
| + private void checkWidgetStates(final String expectedString, final int expectedMicrophoneState) { |
| + // Confirm that all the widgets got updated. |
| + assert mDelegate.mViews.size() == TestDelegate.ALL_IDS.length; |
|
Ted C
2017/04/18 04:33:02
s/assert/assertEquals
gone
2017/04/18 17:14:33
Done.
|
| + for (int i = 0; i < TestDelegate.ALL_IDS.length; i++) { |
| + Assert.assertEquals(TestDelegate.ALL_IDS[i], mDelegate.mViews.get(i).first.intValue()); |
| + } |
| + |
| + ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| + @Override |
| + public void run() { |
| + // Check the contents of the RemoteViews by inflating them. |
| + for (int i = 0; i < mDelegate.mViews.size(); i++) { |
| + FrameLayout parentView = new FrameLayout(mContext); |
| + RemoteViews views = mDelegate.mViews.get(i).second; |
| + View view = views.apply(mContext, parentView); |
| + parentView.addView(view); |
| + |
| + // Confirm that the string is correct. |
| + TextView titleView = (TextView) view.findViewById(R.id.title); |
| + Assert.assertEquals(View.VISIBLE, titleView.getVisibility()); |
| + Assert.assertEquals(expectedString, titleView.getText()); |
| + |
| + // Confirm the visibility of the microphone. |
| + View microphoneView = view.findViewById(R.id.microphone_icon); |
| + Assert.assertEquals(expectedMicrophoneState, microphoneView.getVisibility()); |
| + } |
| + } |
| + }); |
| + } |
| + |
| + @Test |
| + @SmallTest |
| + public void testMicrophoneClick() { |
| + SearchWidgetProvider.handleAction(SearchWidgetProvider.ACTION_UPDATE_ALL_WIDGETS); |
| + for (int i = 0; i < mDelegate.mViews.size(); i++) { |
| + RemoteViews views = mDelegate.mViews.get(i).second; |
| + clickOnWidget(views, R.id.microphone_icon); |
| + } |
| + } |
| + |
| + @Test |
| + @SmallTest |
| + public void testTextClick() { |
| + SearchWidgetProvider.handleAction(SearchWidgetProvider.ACTION_UPDATE_ALL_WIDGETS); |
| + for (int i = 0; i < mDelegate.mViews.size(); i++) { |
| + RemoteViews views = mDelegate.mViews.get(i).second; |
| + clickOnWidget(views, R.id.text_container); |
| + } |
| + } |
| + |
| + private void clickOnWidget(final RemoteViews views, final int clickTarget) { |
| + final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); |
| + final ActivityMonitor monitor = |
| + new ActivityMonitor(SearchActivity.class.getName(), null, false); |
| + instrumentation.addMonitor(monitor); |
| + |
| + // Click on the widget. |
| + ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| + @Override |
| + public void run() { |
| + FrameLayout parentView = new FrameLayout(mContext); |
| + View view = views.apply(mContext, parentView); |
| + parentView.addView(view); |
| + view.findViewById(clickTarget).performClick(); |
| + } |
| + }); |
| + |
| + // Check that the Activity was launched in the right mode. |
| + Activity activity = instrumentation.waitForMonitor(monitor); |
| + Intent intent = activity.getIntent(); |
| + boolean microphoneState = IntentUtils.safeGetBooleanExtra( |
| + intent, SearchWidgetProvider.EXTRA_START_VOICE_SEARCH, false); |
| + Assert.assertEquals(clickTarget == R.id.microphone_icon, microphoneState); |
| + } |
| +} |