Add tests for widget
parent
434a737abf
commit
96d2307df0
|
@ -17,6 +17,7 @@ import android.view.View
|
|||
import android.widget.RemoteViews
|
||||
import androidx.annotation.Dimension
|
||||
import androidx.annotation.Dimension.DP
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
|
@ -27,7 +28,6 @@ import org.mozilla.fenix.home.intent.StartSearchIntentProcessor
|
|||
import org.mozilla.fenix.widget.VoiceSearchActivity
|
||||
import org.mozilla.fenix.widget.VoiceSearchActivity.Companion.SPEECH_PROCESSING
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class SearchWidgetProvider : AppWidgetProvider() {
|
||||
// Implementation note:
|
||||
// This class name (SearchWidgetProvider) and package name (org.mozilla.gecko.search) should
|
||||
|
@ -79,31 +79,9 @@ class SearchWidgetProvider : AppWidgetProvider() {
|
|||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
}
|
||||
|
||||
private fun getLayoutSize(@Dimension(unit = DP) dp: Int) = when {
|
||||
dp >= DP_LARGE -> SearchWidgetProviderSize.LARGE
|
||||
dp >= DP_MEDIUM -> SearchWidgetProviderSize.MEDIUM
|
||||
dp >= DP_SMALL -> SearchWidgetProviderSize.SMALL
|
||||
dp >= DP_EXTRA_SMALL -> SearchWidgetProviderSize.EXTRA_SMALL_V2
|
||||
else -> SearchWidgetProviderSize.EXTRA_SMALL_V1
|
||||
}
|
||||
|
||||
private fun getLayout(size: SearchWidgetProviderSize, showMic: Boolean) = when (size) {
|
||||
SearchWidgetProviderSize.LARGE -> R.layout.search_widget_large
|
||||
SearchWidgetProviderSize.MEDIUM -> R.layout.search_widget_medium
|
||||
SearchWidgetProviderSize.SMALL -> {
|
||||
if (showMic) R.layout.search_widget_small
|
||||
else R.layout.search_widget_small_no_mic
|
||||
}
|
||||
SearchWidgetProviderSize.EXTRA_SMALL_V2 -> R.layout.search_widget_extra_small_v2
|
||||
SearchWidgetProviderSize.EXTRA_SMALL_V1 -> R.layout.search_widget_extra_small_v1
|
||||
}
|
||||
|
||||
private fun getText(layout: SearchWidgetProviderSize, context: Context) = when (layout) {
|
||||
SearchWidgetProviderSize.MEDIUM -> context.getString(R.string.search_widget_text_short)
|
||||
SearchWidgetProviderSize.LARGE -> context.getString(R.string.search_widget_text_long)
|
||||
else -> null
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds pending intent that opens the browser and starts a new text search.
|
||||
*/
|
||||
private fun createTextSearchIntent(context: Context): PendingIntent {
|
||||
return Intent(context, IntentReceiverActivity::class.java)
|
||||
.let { intent ->
|
||||
|
@ -114,6 +92,9 @@ class SearchWidgetProvider : AppWidgetProvider() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds pending intent that starts a new voice search.
|
||||
*/
|
||||
private fun createVoiceSearchIntent(context: Context): PendingIntent? {
|
||||
val voiceIntent = Intent(context, VoiceSearchActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
|
@ -156,7 +137,7 @@ class SearchWidgetProvider : AppWidgetProvider() {
|
|||
// Unlike "small" widget, "medium" and "large" sizes do not have separate layouts
|
||||
// that exclude the microphone icon, which is why we must hide it accordingly here.
|
||||
if (voiceSearchIntent == null) {
|
||||
this.setViewVisibility(R.id.button_search_widget_voice, View.GONE)
|
||||
setViewVisibility(R.id.button_search_widget_voice, View.GONE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -187,6 +168,40 @@ class SearchWidgetProvider : AppWidgetProvider() {
|
|||
private const val DP_LARGE = 256
|
||||
private const val REQUEST_CODE_NEW_TAB = 0
|
||||
private const val REQUEST_CODE_VOICE = 1
|
||||
|
||||
@VisibleForTesting
|
||||
internal fun getLayoutSize(@Dimension(unit = DP) dp: Int) = when {
|
||||
dp >= DP_LARGE -> SearchWidgetProviderSize.LARGE
|
||||
dp >= DP_MEDIUM -> SearchWidgetProviderSize.MEDIUM
|
||||
dp >= DP_SMALL -> SearchWidgetProviderSize.SMALL
|
||||
dp >= DP_EXTRA_SMALL -> SearchWidgetProviderSize.EXTRA_SMALL_V2
|
||||
else -> SearchWidgetProviderSize.EXTRA_SMALL_V1
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the layout resource to use for the search widget.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal fun getLayout(size: SearchWidgetProviderSize, showMic: Boolean) = when (size) {
|
||||
SearchWidgetProviderSize.LARGE -> R.layout.search_widget_large
|
||||
SearchWidgetProviderSize.MEDIUM -> R.layout.search_widget_medium
|
||||
SearchWidgetProviderSize.SMALL -> {
|
||||
if (showMic) R.layout.search_widget_small
|
||||
else R.layout.search_widget_small_no_mic
|
||||
}
|
||||
SearchWidgetProviderSize.EXTRA_SMALL_V2 -> R.layout.search_widget_extra_small_v2
|
||||
SearchWidgetProviderSize.EXTRA_SMALL_V1 -> R.layout.search_widget_extra_small_v1
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text to place in the search widget
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal fun getText(layout: SearchWidgetProviderSize, context: Context) = when (layout) {
|
||||
SearchWidgetProviderSize.MEDIUM -> context.getString(R.string.search_widget_text_short)
|
||||
SearchWidgetProviderSize.LARGE -> context.getString(R.string.search_widget_text_long)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.widget
|
||||
|
||||
import android.content.Context
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.gecko.search.SearchWidgetProvider
|
||||
import org.mozilla.gecko.search.SearchWidgetProviderSize
|
||||
|
||||
class SearchWidgetProviderTest {
|
||||
|
||||
@Test
|
||||
fun testGetLayoutSize() {
|
||||
val sizes = mapOf(
|
||||
0 to SearchWidgetProviderSize.EXTRA_SMALL_V1,
|
||||
10 to SearchWidgetProviderSize.EXTRA_SMALL_V1,
|
||||
63 to SearchWidgetProviderSize.EXTRA_SMALL_V1,
|
||||
64 to SearchWidgetProviderSize.EXTRA_SMALL_V2,
|
||||
99 to SearchWidgetProviderSize.EXTRA_SMALL_V2,
|
||||
100 to SearchWidgetProviderSize.SMALL,
|
||||
191 to SearchWidgetProviderSize.SMALL,
|
||||
192 to SearchWidgetProviderSize.MEDIUM,
|
||||
255 to SearchWidgetProviderSize.MEDIUM,
|
||||
256 to SearchWidgetProviderSize.LARGE,
|
||||
1000 to SearchWidgetProviderSize.LARGE
|
||||
)
|
||||
|
||||
for ((dp, layoutSize) in sizes) {
|
||||
assertEquals(layoutSize, SearchWidgetProvider.getLayoutSize(dp))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetLargeLayout() {
|
||||
assertEquals(
|
||||
R.layout.search_widget_large,
|
||||
SearchWidgetProvider.getLayout(SearchWidgetProviderSize.LARGE, showMic = false)
|
||||
)
|
||||
assertEquals(
|
||||
R.layout.search_widget_large,
|
||||
SearchWidgetProvider.getLayout(SearchWidgetProviderSize.LARGE, showMic = true)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetMediumLayout() {
|
||||
assertEquals(
|
||||
R.layout.search_widget_medium,
|
||||
SearchWidgetProvider.getLayout(SearchWidgetProviderSize.MEDIUM, showMic = false)
|
||||
)
|
||||
assertEquals(
|
||||
R.layout.search_widget_medium,
|
||||
SearchWidgetProvider.getLayout(SearchWidgetProviderSize.MEDIUM, showMic = true)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetSmallLayout() {
|
||||
assertEquals(
|
||||
R.layout.search_widget_small_no_mic,
|
||||
SearchWidgetProvider.getLayout(SearchWidgetProviderSize.SMALL, showMic = false)
|
||||
)
|
||||
assertEquals(
|
||||
R.layout.search_widget_small,
|
||||
SearchWidgetProvider.getLayout(SearchWidgetProviderSize.SMALL, showMic = true)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetExtraSmall2Layout() {
|
||||
assertEquals(
|
||||
R.layout.search_widget_extra_small_v2,
|
||||
SearchWidgetProvider.getLayout(SearchWidgetProviderSize.EXTRA_SMALL_V2, showMic = false)
|
||||
)
|
||||
assertEquals(
|
||||
R.layout.search_widget_extra_small_v2,
|
||||
SearchWidgetProvider.getLayout(SearchWidgetProviderSize.EXTRA_SMALL_V2, showMic = true)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetExtraSmall1Layout() {
|
||||
assertEquals(
|
||||
R.layout.search_widget_extra_small_v1,
|
||||
SearchWidgetProvider.getLayout(SearchWidgetProviderSize.EXTRA_SMALL_V1, showMic = false)
|
||||
)
|
||||
assertEquals(
|
||||
R.layout.search_widget_extra_small_v1,
|
||||
SearchWidgetProvider.getLayout(SearchWidgetProviderSize.EXTRA_SMALL_V1, showMic = true)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetText() {
|
||||
val context = mockk<Context>()
|
||||
every { context.getString(R.string.search_widget_text_short) } returns "Search"
|
||||
every { context.getString(R.string.search_widget_text_long) } returns "Search the web"
|
||||
|
||||
assertEquals(
|
||||
"Search the web",
|
||||
SearchWidgetProvider.getText(SearchWidgetProviderSize.LARGE, context)
|
||||
)
|
||||
assertEquals(
|
||||
"Search",
|
||||
SearchWidgetProvider.getText(SearchWidgetProviderSize.MEDIUM, context)
|
||||
)
|
||||
assertNull(SearchWidgetProvider.getText(SearchWidgetProviderSize.SMALL, context))
|
||||
assertNull(SearchWidgetProvider.getText(SearchWidgetProviderSize.EXTRA_SMALL_V1, context))
|
||||
assertNull(SearchWidgetProvider.getText(SearchWidgetProviderSize.EXTRA_SMALL_V2, context))
|
||||
}
|
||||
}
|
|
@ -73,6 +73,32 @@ class VoiceSearchActivityTest {
|
|||
assertTrue(activity.isFinishing)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `process null intent`() {
|
||||
val controller = Robolectric.buildActivity(VoiceSearchActivity::class.java, null)
|
||||
val activity = controller.get()
|
||||
|
||||
controller.create()
|
||||
|
||||
assertTrue(activity.isFinishing)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `save previous intent to instance state`() {
|
||||
val previousIntent = Intent().apply {
|
||||
putExtra(SPEECH_PROCESSING, true)
|
||||
}
|
||||
val savedInstanceState = Bundle().apply {
|
||||
putParcelable(PREVIOUS_INTENT, previousIntent)
|
||||
}
|
||||
val outState = Bundle()
|
||||
|
||||
controller.create(savedInstanceState)
|
||||
controller.saveInstanceState(outState)
|
||||
|
||||
assertEquals(previousIntent, outState.getParcelable(PREVIOUS_INTENT) as Intent)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `process intent with speech processing in previous intent set to true`() {
|
||||
val savedInstanceState = Bundle()
|
||||
|
@ -107,4 +133,18 @@ class VoiceSearchActivityTest {
|
|||
assertEquals("hello world", browserIntent.getStringExtra(SPEECH_PROCESSING))
|
||||
assertTrue(browserIntent.getBooleanExtra(OPEN_TO_BROWSER_AND_LOAD, false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `handle invalid result code`() {
|
||||
controller.create()
|
||||
|
||||
val resultIntent = Intent()
|
||||
shadow.receiveResult(
|
||||
shadow.peekNextStartedActivityForResult().intent,
|
||||
Activity.RESULT_CANCELED,
|
||||
resultIntent
|
||||
)
|
||||
|
||||
assertTrue(activity.isFinishing)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue