package io.github.hidroh.materialistic; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; import android.net.ConnectivityManager; import android.net.Uri; import android.preference.PreferenceManager; import android.support.v4.widget.NestedScrollView; import android.view.View; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.ViewSwitcher; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.fakes.RoboMenuItem; import org.robolectric.internal.ShadowExtractor; import org.robolectric.res.builder.RobolectricPackageManager; import org.robolectric.shadows.ShadowNetworkInfo; import org.robolectric.shadows.ShadowPopupMenu; import org.robolectric.shadows.ShadowToast; import org.robolectric.shadows.support.v4.ShadowLocalBroadcastManager; import org.robolectric.util.ActivityController; import javax.inject.Inject; import io.github.hidroh.materialistic.data.FavoriteManager; import io.github.hidroh.materialistic.data.Item; import io.github.hidroh.materialistic.data.ReadabilityClient; import io.github.hidroh.materialistic.data.WebItem; import io.github.hidroh.materialistic.test.TestRunner; import io.github.hidroh.materialistic.test.WebActivity; import io.github.hidroh.materialistic.test.shadow.ShadowNestedScrollView; import io.github.hidroh.materialistic.test.shadow.ShadowWebView; import static io.github.hidroh.materialistic.test.shadow.CustomShadows.customShadowOf; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; import static org.assertj.android.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; @SuppressWarnings("ConstantConditions") @Config(shadows = {ShadowWebView.class}) @RunWith(TestRunner.class) public class WebFragmentTest { private WebActivity activity; private ActivityController<WebActivity> controller; private WebItem item; @Inject FavoriteManager favoriteManager; @Inject ReadabilityClient readabilityClient; private Intent intent; @Before public void setUp() { MockitoAnnotations.initMocks(this); TestApplication.applicationGraph.inject(this); reset(favoriteManager); item = mock(WebItem.class); when(item.getType()).thenReturn(Item.STORY_TYPE); when(item.getUrl()).thenReturn("http://example.com"); intent = new Intent(); intent.putExtra(WebActivity.EXTRA_ITEM, item); controller = Robolectric.buildActivity(WebActivity.class); shadowOf((ConnectivityManager) RuntimeEnvironment.application .getSystemService(Context.CONNECTIVITY_SERVICE)) .setActiveNetworkInfo(ShadowNetworkInfo.newInstance(null, ConnectivityManager.TYPE_WIFI, 0, true, true)); activity = controller.get(); PreferenceManager.getDefaultSharedPreferences(activity) .edit() .putBoolean(activity.getString(R.string.pref_ad_block), true) .putBoolean(activity.getString(R.string.pref_lazy_load), false) .apply(); controller.withIntent(intent).create().start().resume().visible(); } @Test public void testProgressChanged() { ProgressBar progressBar = (ProgressBar) activity.findViewById(R.id.progress); WebView webView = (WebView) activity.findViewById(R.id.web_view); shadowOf(webView).getWebChromeClient().onProgressChanged(webView, 50); assertThat(progressBar).isVisible(); shadowOf(webView).getWebChromeClient().onProgressChanged(webView, 100); assertThat(progressBar).isNotVisible(); } @Test public void testDownloadPDF() { ResolveInfo resolverInfo = new ResolveInfo(); resolverInfo.activityInfo = new ActivityInfo(); resolverInfo.activityInfo.applicationInfo = new ApplicationInfo(); resolverInfo.activityInfo.applicationInfo.packageName = ListActivity.class.getPackage().getName(); resolverInfo.activityInfo.name = ListActivity.class.getName(); RobolectricPackageManager rpm = (RobolectricPackageManager) RuntimeEnvironment.application.getPackageManager(); rpm.addResolveInfoForIntent(new Intent(Intent.ACTION_VIEW, Uri.parse("http://example.com/file.pdf")), resolverInfo); WebView webView = (WebView) activity.findViewById(R.id.web_view); ShadowWebView shadowWebView = (ShadowWebView) ShadowExtractor.extract(webView); shadowWebView.getDownloadListener().onDownloadStart("http://example.com/file.pdf", "", "", "", 0l); assertThat(activity.findViewById(R.id.empty)).isVisible(); activity.findViewById(R.id.download_button).performClick(); assertNotNull(shadowOf(activity).getNextStartedActivity()); } @Config(shadows = ShadowNestedScrollView.class) @Test public void testScrollToTop() { NestedScrollView scrollView = (NestedScrollView) activity.findViewById(R.id.nested_scroll_view); scrollView.smoothScrollTo(0, 1); assertThat(customShadowOf(scrollView).getSmoothScrollY()).isEqualTo(1); activity.fragment.scrollToTop(); assertThat(customShadowOf(scrollView).getSmoothScrollY()).isEqualTo(0); } @Test public void testFullscreenScrollToTop() { activity.findViewById(R.id.toolbar_web).performClick(); assertEquals(-1, ((ShadowWebView) ShadowExtractor.extract(activity.findViewById(R.id.web_view))) .getScrollY()); } @SuppressWarnings("deprecation") @SuppressLint("NewApi") @Test public void testAdBlocker() { WebView webView = (WebView) activity.findViewById(R.id.web_view); WebViewClient client = shadowOf(webView).getWebViewClient(); assertNull(client.shouldInterceptRequest(webView, "http://google.com")); assertNull(client.shouldInterceptRequest(webView, "http://google.com")); assertNotNull(client.shouldInterceptRequest(webView, "http://page2.g.doubleclick.net")); assertNotNull(client.shouldInterceptRequest(webView, "http://page2.g.doubleclick.net")); } @SuppressWarnings("deprecation") @SuppressLint("NewApi") @Test public void testAdBlockerDisabled() { controller.pause().stop().destroy(); PreferenceManager.getDefaultSharedPreferences(activity) .edit() .putBoolean(activity.getString(R.string.pref_ad_block), false) .apply(); controller = Robolectric.buildActivity(WebActivity.class); activity = controller.get(); controller.withIntent(intent).create().start().resume(); WebView webView = (WebView) activity.findViewById(R.id.web_view); WebViewClient client = shadowOf(webView).getWebViewClient(); assertNull(client.shouldInterceptRequest(webView, "http://google.com")); assertNull(client.shouldInterceptRequest(webView, "http://page2.g.doubleclick.net")); } @Test public void testFullscreen() { ShadowLocalBroadcastManager.getInstance(activity) .sendBroadcast(new Intent(WebFragment.ACTION_FULLSCREEN) .putExtra(WebFragment.EXTRA_FULLSCREEN, true)); assertThat(activity.findViewById(R.id.control_switcher)).isVisible(); shadowOf(activity).recreate(); assertThat(activity.findViewById(R.id.control_switcher)).isVisible(); activity.findViewById(R.id.button_exit).performClick(); assertThat(activity.findViewById(R.id.control_switcher)).isNotVisible(); } @Test public void testSearch() { ShadowLocalBroadcastManager.getInstance(activity) .sendBroadcast(new Intent(WebFragment.ACTION_FULLSCREEN) .putExtra(WebFragment.EXTRA_FULLSCREEN, true)); activity.findViewById(R.id.button_find).performClick(); ViewSwitcher controlSwitcher = (ViewSwitcher) activity.findViewById(R.id.control_switcher); assertThat(controlSwitcher.getDisplayedChild()).isEqualTo(1); ShadowWebView shadowWebView = (ShadowWebView) ShadowExtractor .extract(activity.findViewById(R.id.web_view)); // no query EditText editText = (EditText) activity.findViewById(R.id.edittext); shadowOf(editText).getOnEditorActionListener().onEditorAction(null, 0, null); assertThat(activity.findViewById(R.id.button_next)).isDisabled(); // with results shadowWebView.setFindCount(1); editText.setText("abc"); shadowOf(editText).getOnEditorActionListener().onEditorAction(null, 0, null); assertThat(activity.findViewById(R.id.button_next)).isEnabled(); activity.findViewById(R.id.button_next).performClick(); assertThat(shadowWebView.getFindIndex()).isEqualTo(1); activity.findViewById(R.id.button_clear).performClick(); assertThat(editText).isEmpty(); assertThat(controlSwitcher.getDisplayedChild()).isEqualTo(0); // with no results shadowWebView.setFindCount(0); editText.setText("abc"); shadowOf(editText).getOnEditorActionListener().onEditorAction(null, 0, null); assertThat(activity.findViewById(R.id.button_next)).isDisabled(); assertThat(ShadowToast.getTextOfLatestToast()).contains(activity.getString(R.string.no_matches)); } @Test public void testRefresh() { ShadowLocalBroadcastManager.getInstance(activity) .sendBroadcast(new Intent(WebFragment.ACTION_FULLSCREEN) .putExtra(WebFragment.EXTRA_FULLSCREEN, true)); ShadowWebView.lastGlobalLoadedUrl = null; ShadowWebView shadowWebView = (ShadowWebView) ShadowExtractor .extract(activity.findViewById(R.id.web_view)); shadowWebView.setProgress(20); activity.findViewById(R.id.button_refresh).performClick(); assertThat(ShadowWebView.getLastGlobalLoadedUrl()).isNullOrEmpty(); shadowWebView.setProgress(100); activity.findViewById(R.id.button_refresh).performClick(); assertThat(ShadowWebView.getLastGlobalLoadedUrl()).isEqualTo(ShadowWebView.RELOADED); } @SuppressLint("NewApi") @Test public void testWebControls() { ShadowLocalBroadcastManager.getInstance(activity) .sendBroadcast(new Intent(WebFragment.ACTION_FULLSCREEN) .putExtra(WebFragment.EXTRA_FULLSCREEN, true)); ShadowWebView shadowWebView = (ShadowWebView) ShadowExtractor .extract(activity.findViewById(R.id.web_view)); activity.findViewById(R.id.button_more).performClick(); shadowOf(ShadowPopupMenu.getLatestPopupMenu()).getOnMenuItemClickListener() .onMenuItemClick(new RoboMenuItem(R.id.menu_zoom_in)); assertThat(shadowWebView.getZoomDegree()).isEqualTo(1); activity.findViewById(R.id.button_more).performClick(); shadowOf(ShadowPopupMenu.getLatestPopupMenu()).getOnMenuItemClickListener() .onMenuItemClick(new RoboMenuItem(R.id.menu_zoom_out)); assertThat(shadowWebView.getZoomDegree()).isEqualTo(0); activity.findViewById(R.id.button_forward).performClick(); assertThat(shadowWebView.getPageIndex()).isEqualTo(1); activity.findViewById(R.id.button_back).performClick(); assertThat(shadowWebView.getPageIndex()).isEqualTo(0); } @Config(shadows = ShadowNestedScrollView.class) @Test public void testScroll() { ShadowNestedScrollView shadowScrollView = customShadowOf((NestedScrollView) activity.findViewById(R.id.nested_scroll_view)); WebFragment fragment = (WebFragment) activity.getSupportFragmentManager() .findFragmentByTag(WebFragment.class.getName()); fragment.scrollToNext(); assertThat(shadowScrollView.getLastScrollDirection()).isEqualTo(View.FOCUS_DOWN); fragment.scrollToPrevious(); assertThat(shadowScrollView.getLastScrollDirection()).isEqualTo(View.FOCUS_UP); fragment.scrollToTop(); assertThat(shadowScrollView.getSmoothScrollY()).isEqualTo(0); } @Test public void testFullScroll() { ShadowLocalBroadcastManager.getInstance(activity) .sendBroadcast(new Intent(WebFragment.ACTION_FULLSCREEN) .putExtra(WebFragment.EXTRA_FULLSCREEN, true)); ShadowWebView shadowWebView = (ShadowWebView) ShadowExtractor .extract(activity.findViewById(R.id.web_view)); WebFragment fragment = (WebFragment) activity.getSupportFragmentManager() .findFragmentByTag(WebFragment.class.getName()); fragment.scrollToTop(); assertEquals(0, shadowWebView.getScrollY()); fragment.scrollToNext(); assertEquals(1, shadowWebView.getScrollY()); fragment.scrollToPrevious(); assertEquals(0, shadowWebView.getScrollY()); } @Test public void testBackPressed() { WebView webView = (WebView) activity.findViewById(R.id.web_view); shadowOf(webView).getWebViewClient().onPageFinished(webView, "http://example.com"); shadowOf(webView).setCanGoBack(true); assertTrue(activity.fragment.onBackPressed()); shadowOf(webView).setCanGoBack(false); assertFalse(activity.fragment.onBackPressed()); } @Test public void testReadabilityToggle() { activity.fragment.onOptionsItemSelected(new RoboMenuItem(R.id.menu_readability)); verify(readabilityClient).parse(any(), eq("http://example.com"), any()); } @After public void tearDown() { controller.pause().stop().destroy(); } }