Add tests for ext package (#11334)
This commit is contained in:
parent
d16c70d8be
commit
4b064afb81
|
@ -97,7 +97,7 @@ class Analytics(
|
|||
}
|
||||
}
|
||||
|
||||
private fun isSentryEnabled() = !BuildConfig.SENTRY_TOKEN.isNullOrEmpty()
|
||||
fun isSentryEnabled() = !BuildConfig.SENTRY_TOKEN.isNullOrEmpty()
|
||||
|
||||
private fun getSentryProjectUrl(): String? {
|
||||
val baseUrl = "https://sentry.prod.mozaws.net/operations"
|
||||
|
|
|
@ -5,26 +5,17 @@
|
|||
package org.mozilla.fenix.ext
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.Intent.ACTION_SEND
|
||||
import android.content.Intent.EXTRA_SUBJECT
|
||||
import android.content.Intent.EXTRA_TEXT
|
||||
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import mozilla.components.browser.search.SearchEngineManager
|
||||
import mozilla.components.support.base.log.Log
|
||||
import mozilla.components.support.base.log.Log.Priority.WARN
|
||||
import mozilla.components.support.locale.LocaleManager
|
||||
import org.mozilla.fenix.BuildConfig
|
||||
import org.mozilla.fenix.Config
|
||||
import org.mozilla.fenix.FenixApplication
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.Components
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.settings.advanced.getSelectedLocale
|
||||
|
@ -65,35 +56,6 @@ fun Context.asFragmentActivity() = (this as? ContextThemeWrapper)?.baseContext a
|
|||
fun Context.getPreferenceKey(@StringRes resourceId: Int): String =
|
||||
resources.getString(resourceId)
|
||||
|
||||
/**
|
||||
* Shares content via [ACTION_SEND] intent.
|
||||
*
|
||||
* @param text the data to be shared [EXTRA_TEXT]
|
||||
* @param subject of the intent [EXTRA_TEXT]
|
||||
* @return true it is able to share false otherwise.
|
||||
*/
|
||||
@Deprecated("We are replacing the system share sheet with a custom version. See: [ShareFragment]")
|
||||
fun Context.share(text: String, subject: String = ""): Boolean {
|
||||
return try {
|
||||
val intent = Intent(ACTION_SEND).apply {
|
||||
type = "text/plain"
|
||||
putExtra(EXTRA_SUBJECT, subject)
|
||||
putExtra(EXTRA_TEXT, text)
|
||||
flags = FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
|
||||
val shareIntent = Intent.createChooser(intent, getString(R.string.menu_share_with)).apply {
|
||||
flags = FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
|
||||
startActivity(shareIntent)
|
||||
true
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Log.log(WARN, message = "No activity to share to found", throwable = e, tag = "Reference-Browser")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Root View with an activity context
|
||||
*
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* 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/. */
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
package org.mozilla.fenix.ext
|
||||
|
||||
import android.util.Log
|
||||
|
@ -12,7 +14,6 @@ import org.mozilla.fenix.Config
|
|||
*
|
||||
* Meant to be used for logs that should not be visible in the production app.
|
||||
*/
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun logDebug(tag: String, message: String) {
|
||||
if (Config.channel.isDebug) Log.d(tag, message)
|
||||
}
|
||||
|
@ -22,7 +23,6 @@ inline fun logDebug(tag: String, message: String) {
|
|||
*
|
||||
* Meant to be used for logs that should not be visible in the production app.
|
||||
*/
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun logWarn(tag: String, message: String) {
|
||||
if (Config.channel.isDebug) Log.w(tag, message)
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ inline fun logWarn(tag: String, message: String) {
|
|||
*
|
||||
* Meant to be used for logs that should not be visible in the production app.
|
||||
*/
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun logWarn(tag: String, message: String, err: Throwable) {
|
||||
if (Config.channel.isDebug) Log.w(tag, message, err)
|
||||
}
|
||||
|
@ -42,7 +41,6 @@ inline fun logWarn(tag: String, message: String, err: Throwable) {
|
|||
*
|
||||
* Meant to be used for logs that should not be visible in the production app.
|
||||
*/
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun logErr(tag: String, message: String, err: Throwable) {
|
||||
if (Config.channel.isDebug) Log.e(tag, message, err)
|
||||
}
|
||||
|
|
|
@ -11,8 +11,12 @@ import androidx.navigation.NavDirections
|
|||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.Navigator
|
||||
import io.sentry.Sentry
|
||||
import org.mozilla.fenix.BuildConfig
|
||||
import org.mozilla.fenix.components.isSentryEnabled
|
||||
|
||||
/**
|
||||
* Navigate from the fragment with [id] using the given [directions].
|
||||
* If the id doesn't match the current destination, an error is recorded.
|
||||
*/
|
||||
fun NavController.nav(@IdRes id: Int?, directions: NavDirections, navOptions: NavOptions? = null) {
|
||||
if (id == null || this.currentDestination?.id == id) {
|
||||
this.navigate(directions, navOptions)
|
||||
|
@ -55,7 +59,7 @@ fun NavController.alreadyOnDestination(@IdRes destId: Int?): Boolean {
|
|||
}
|
||||
|
||||
fun recordIdException(actual: Int?, expected: Int?) {
|
||||
if (!BuildConfig.SENTRY_TOKEN.isNullOrEmpty()) {
|
||||
if (isSentryEnabled()) {
|
||||
Sentry.capture("Fragment id $actual did not match expected $expected")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,7 @@ fun View.increaseTapArea(extraDps: Int) {
|
|||
parent.post {
|
||||
val touchRect = Rect()
|
||||
getHitRect(touchRect)
|
||||
touchRect.top -= dips
|
||||
touchRect.left -= dips
|
||||
touchRect.right += dips
|
||||
touchRect.bottom += dips
|
||||
touchRect.inset(-dips, -dips)
|
||||
parent.touchDelegate = TouchDelegate(touchRect, this)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,4 +31,11 @@ class ImageButtonTest {
|
|||
assertTrue(imageButton.isEnabled)
|
||||
assertEquals(View.VISIBLE, imageButton.visibility)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Remove and disable`() {
|
||||
imageButton.removeAndDisable()
|
||||
assertFalse(imageButton.isEnabled)
|
||||
assertEquals(View.GONE, imageButton.visibility)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,44 +5,71 @@
|
|||
package org.mozilla.fenix.ext
|
||||
|
||||
import android.util.Log
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.verify
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.Config
|
||||
import org.mozilla.fenix.ReleaseChannel
|
||||
|
||||
class LogTest {
|
||||
|
||||
private val numCalls = if (org.mozilla.fenix.Config.channel.isDebug) 1 else 0
|
||||
private val mockThrowable: Throwable = mockk()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockkStatic(Log::class)
|
||||
mockkObject(Config)
|
||||
|
||||
every { Log.d(any(), any()) } returns 0
|
||||
every { Log.w(any(), any<String>()) } returns 0
|
||||
every { Log.d(any(), any(), any()) } returns 0
|
||||
every { Log.d(any(), any(), any()) } returns 0
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test log debug function`() {
|
||||
every { Config.channel } returns ReleaseChannel.FenixDebug
|
||||
logDebug("hi", "hi")
|
||||
verify(exactly = numCalls) { (Log.d("hi", "hi")) }
|
||||
verify { Log.d("hi", "hi") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test log warn function with tag and message args`() {
|
||||
every { Config.channel } returns ReleaseChannel.FenixDebug
|
||||
logWarn("hi", "hi")
|
||||
verify(exactly = numCalls) { (Log.w("hi", "hi")) }
|
||||
verify { Log.w("hi", "hi") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test log warn function with tag, message, and exception args`() {
|
||||
val mockThrowable: Throwable = mockk(relaxed = true)
|
||||
every { Config.channel } returns ReleaseChannel.FenixDebug
|
||||
logWarn("hi", "hi", mockThrowable)
|
||||
verify(exactly = numCalls) { (Log.w("hi", "hi", mockThrowable)) }
|
||||
verify { Log.w("hi", "hi", mockThrowable) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test log error function with tag, message, and exception args`() {
|
||||
val mockThrowable: Throwable = mockk(relaxed = true)
|
||||
every { Config.channel } returns ReleaseChannel.FenixDebug
|
||||
logErr("hi", "hi", mockThrowable)
|
||||
verify(exactly = numCalls) { (Log.e("hi", "hi", mockThrowable)) }
|
||||
verify { Log.e("hi", "hi", mockThrowable) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test no log in production channel`() {
|
||||
every { Config.channel } returns ReleaseChannel.FenixProduction
|
||||
|
||||
logDebug("hi", "hi")
|
||||
logWarn("hi", "hi")
|
||||
logWarn("hi", "hi", mockThrowable)
|
||||
logErr("hi", "hi", mockThrowable)
|
||||
|
||||
verify(exactly = 0) { Log.d(any(), any()) }
|
||||
verify(exactly = 0) { Log.w(any(), any<String>()) }
|
||||
verify(exactly = 0) { Log.d(any(), any(), any()) }
|
||||
verify(exactly = 0) { Log.d(any(), any(), any()) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,81 +10,101 @@ import androidx.navigation.NavDestination
|
|||
import androidx.navigation.NavDirections
|
||||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.Navigator.Extras
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.confirmVerified
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.just
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.verify
|
||||
import io.sentry.Sentry
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.components.isSentryEnabled
|
||||
|
||||
class NavControllerTest {
|
||||
|
||||
private val navController: NavController = mockk(relaxed = true)
|
||||
private val navDirections = mockk<NavDirections>(relaxed = true)
|
||||
private val mockDestination: NavDestination = mockk(relaxed = true)
|
||||
private val mockExtras: Extras = mockk(relaxed = true)
|
||||
private val mockOptions: NavOptions = mockk(relaxed = true)
|
||||
private val mockBundle: Bundle = mockk(relaxed = true)
|
||||
private val currentDestId = 4
|
||||
@MockK(relaxUnitFun = true) private lateinit var navController: NavController
|
||||
@MockK private lateinit var navDirections: NavDirections
|
||||
@MockK private lateinit var mockDestination: NavDestination
|
||||
@MockK private lateinit var mockExtras: Extras
|
||||
@MockK private lateinit var mockOptions: NavOptions
|
||||
@MockK private lateinit var mockBundle: Bundle
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
every { (navController.currentDestination) } returns mockDestination
|
||||
every { (mockDestination.id) } returns 4
|
||||
MockKAnnotations.init(this)
|
||||
mockkStatic("io.sentry.Sentry", "org.mozilla.fenix.components.AnalyticsKt")
|
||||
|
||||
every { navController.currentDestination } returns mockDestination
|
||||
every { mockDestination.id } returns currentDestId
|
||||
every { isSentryEnabled() } returns true
|
||||
every { Sentry.capture(any<String>()) } just Runs
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Nav with id and directions args`() {
|
||||
navController.nav(4, navDirections)
|
||||
verify { (navController.currentDestination) }
|
||||
verify { (navController.navigate(navDirections, null)) }
|
||||
navController.nav(currentDestId, navDirections)
|
||||
verify { navController.currentDestination }
|
||||
verify { navController.navigate(navDirections, null) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Nav with id, directions, and extras args`() {
|
||||
navController.nav(4, navDirections, mockExtras)
|
||||
verify { (navController.currentDestination) }
|
||||
verify { (navController.navigate(navDirections, mockExtras)) }
|
||||
navController.nav(currentDestId, navDirections, mockExtras)
|
||||
verify { navController.currentDestination }
|
||||
verify { navController.navigate(navDirections, mockExtras) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Nav with id, directions, and options args`() {
|
||||
navController.nav(4, navDirections, mockOptions)
|
||||
verify { (navController.currentDestination) }
|
||||
verify { (navController.navigate(navDirections, mockOptions)) }
|
||||
navController.nav(currentDestId, navDirections, mockOptions)
|
||||
verify { navController.currentDestination }
|
||||
verify { navController.navigate(navDirections, mockOptions) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Nav with id, directions, options, and extras args`() {
|
||||
every { navDirections.actionId } returns 5
|
||||
every { navDirections.arguments } returns mockBundle
|
||||
|
||||
navController.nav(currentDestId, navDirections, mockOptions, mockExtras)
|
||||
verify { navController.currentDestination }
|
||||
verify { navController.navigate(5, mockBundle, mockOptions, mockExtras) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Nav with id, destId, bundle, options, and extras args`() {
|
||||
navController.nav(4, 5, mockBundle, mockOptions, mockExtras)
|
||||
verify { (navController.currentDestination) }
|
||||
verify { (navController.navigate(5, mockBundle, mockOptions, mockExtras)) }
|
||||
navController.nav(currentDestId, 5, mockBundle, mockOptions, mockExtras)
|
||||
verify { navController.currentDestination }
|
||||
verify { navController.navigate(5, mockBundle, mockOptions, mockExtras) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test error response for id exception in-block`() {
|
||||
navController.nav(7, navDirections)
|
||||
verify { (recordIdException(mockDestination.id, 7)) }
|
||||
verify { navController.currentDestination }
|
||||
verify { Sentry.capture("Fragment id 4 did not match expected 7") }
|
||||
confirmVerified(navController)
|
||||
}
|
||||
|
||||
// TO-DO Not Working
|
||||
/* @Test
|
||||
@Test
|
||||
fun `Test error response for null current destination`() {
|
||||
every { navController.currentDestination } returns null
|
||||
navController.nav(7, navDirections, mockExtras)
|
||||
verify { navController.currentDestination }
|
||||
verify { Sentry.capture("Fragment id null did not match expected 7") }
|
||||
confirmVerified(navController)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Test record id exception fun`() {
|
||||
mockkStatic(String::class)
|
||||
val actual = 7
|
||||
var expected = 4
|
||||
val expected = 4
|
||||
|
||||
class MySentry() {
|
||||
public fun capture(myString: String) {
|
||||
println(myString) }
|
||||
}
|
||||
|
||||
class MyBuildConfig() {
|
||||
public val SENTRY_TOKEN = "Mozilla"
|
||||
}
|
||||
|
||||
//val Sentry = MySentry()
|
||||
val BuildConfig = MyBuildConfig()
|
||||
every {BuildConfig.SENTRY_TOKEN.isNullOrEmpty()} returns false
|
||||
recordIdException(actual, expected)
|
||||
//verify { Sentry.capture("Fragment id $actual did not match expected $expected")}
|
||||
}*/
|
||||
verify { Sentry.capture("Fragment id 7 did not match expected 4") }
|
||||
}
|
||||
}
|
||||
|
|
69
app/src/test/java/org/mozilla/fenix/ext/ViewTest.kt
Normal file
69
app/src/test/java/org/mozilla/fenix/ext/ViewTest.kt
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* 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.ext
|
||||
|
||||
import android.graphics.Rect
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.just
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.slot
|
||||
import io.mockk.verify
|
||||
import mozilla.components.support.ktx.android.util.dpToPx
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class ViewTest {
|
||||
|
||||
@MockK private lateinit var view: View
|
||||
@MockK private lateinit var parent: FrameLayout
|
||||
@MockK private lateinit var displayMetrics: DisplayMetrics
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockKAnnotations.init(this)
|
||||
mockkStatic("mozilla.components.support.ktx.android.util.DisplayMetricsKt")
|
||||
|
||||
every { view.resources.displayMetrics } returns displayMetrics
|
||||
every { view.parent } returns parent
|
||||
every { parent.touchDelegate = any() } just Runs
|
||||
every { parent.post(any()) } answers {
|
||||
// Immediately run the given Runnable argument
|
||||
val action: Runnable = firstArg()
|
||||
action.run()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test increase touch area`() {
|
||||
val hitRect = Rect(30, 40, 50, 60)
|
||||
val dp = 10
|
||||
val px = 20
|
||||
val outRect = slot<Rect>()
|
||||
every { dp.dpToPx(displayMetrics) } returns px
|
||||
every { view.getHitRect(capture(outRect)) } answers { outRect.captured.set(hitRect) }
|
||||
|
||||
view.increaseTapArea(dp)
|
||||
val expected = Rect(10, 20, 70, 80)
|
||||
assertEquals(expected.left, outRect.captured.left)
|
||||
assertEquals(expected.top, outRect.captured.top)
|
||||
assertEquals(expected.right, outRect.captured.right)
|
||||
assertEquals(expected.bottom, outRect.captured.bottom)
|
||||
verify { parent.touchDelegate = any() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test remove touch delegate`() {
|
||||
view.removeTouchDelegate()
|
||||
verify { parent.touchDelegate = null }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user