commit 233c97df8abc6eef46716129e21da9c5343a2836
parent bc4dae42f9df10e46aa3dd74e6dc1a16ec2bb0b7
Author: mcarare <48995920+mcarare@users.noreply.github.com>
Date: Wed, 31 Dec 2025 09:12:57 +0000
Bug 2007669 - Refactor ShareController and tests to use modern coroutine testing tools. r=android-reviewers,giorga
This change updates `ShareController` and its corresponding tests to improve coroutine handling and test reliability.
- Replaced `MainCoroutineRule` and `runTestOnMain` with `StandardTestDispatcher` and `runTest` in `ShareControllerTest`.
- Updated `ShareController` to accept both `mainDispatcher` and `ioDispatcher` for better control over execution contexts.
- Updated all test cases to use the new `runTest(testDispatcher)` pattern and explicit scheduler advancement where necessary.
- Simplified test setup by removing unnecessary `spyk` on `testContext`.
Differential Revision: https://phabricator.services.mozilla.com/D277510
Diffstat:
2 files changed, 758 insertions(+), 469 deletions(-)
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/ShareController.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/share/ShareController.kt
@@ -87,7 +87,8 @@ interface ShareController {
* @param navController [NavController] used for navigation.
* @param recentAppsStorage Instance of [RecentAppsStorage] for storing and retrieving the most recent apps.
* @param viewLifecycleScope [CoroutineScope] used for retrieving the most recent apps in the background.
- * @param dispatcher Dispatcher used to execute suspending functions.
+ * @param mainDispatcher Dispatcher for executing tasks on the Main thread.
+ * @param ioDispatcher Dispatcher for executing I/O-bound tasks, like updating local storage.
* @param fxaEntrypoint The entrypoint if we need to authenticate, it will be reported in telemetry.
* @param dismiss Callback signalling sharing can be closed.
*/
@@ -104,7 +105,8 @@ class DefaultShareController(
private val navController: NavController,
private val recentAppsStorage: RecentAppsStorage,
private val viewLifecycleScope: CoroutineScope,
- private val dispatcher: CoroutineDispatcher = Dispatchers.IO,
+ private val mainDispatcher: CoroutineDispatcher = Dispatchers.Main,
+ private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
private val fxaEntrypoint: FxAEntryPoint = FenixFxAEntryPoint.ShareMenu,
private val dismiss: (ShareController.Result) -> Unit,
) : ShareController {
@@ -135,7 +137,7 @@ class DefaultShareController(
return
}
- viewLifecycleScope.launch(dispatcher) {
+ viewLifecycleScope.launch(ioDispatcher) {
recentAppsStorage.updateRecentApp(app.activityName)
}
@@ -218,7 +220,7 @@ class DefaultShareController(
shareOperation: () -> Deferred<Boolean>,
) {
// Use GlobalScope to allow the continuation of this method even if the share fragment is closed.
- GlobalScope.launch(Dispatchers.Main) {
+ GlobalScope.launch(mainDispatcher) {
val result = if (shareOperation.invoke().await()) {
showSuccess(destination)
ShareController.Result.SUCCESS
diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/share/ShareControllerTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/share/ShareControllerTest.kt
@@ -17,12 +17,11 @@ import io.mockk.just
import io.mockk.mockk
import io.mockk.runs
import io.mockk.slot
-import io.mockk.spyk
import io.mockk.verify
import io.mockk.verifyOrder
import kotlinx.coroutines.CompletableDeferred
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.runTest
import mozilla.components.concept.engine.prompt.ShareData
import mozilla.components.concept.sync.Device
import mozilla.components.concept.sync.DeviceType
@@ -31,8 +30,6 @@ import mozilla.components.feature.accounts.push.SendTabUseCases
import mozilla.components.feature.session.SessionUseCases
import mozilla.components.feature.share.RecentAppsStorage
import mozilla.components.support.test.robolectric.testContext
-import mozilla.components.support.test.rule.MainCoroutineRule
-import mozilla.components.support.test.rule.runTestOnMain
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
@@ -52,8 +49,6 @@ import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class ShareControllerTest {
- // Need a valid context to retrieve Strings for example, but we also need it to return our "metrics"
- private val context: Context = spyk(testContext)
private val appStore: AppStore = mockk(relaxed = true)
private val shareSubject = "shareSubject"
private val shareData = listOf(
@@ -82,525 +77,760 @@ class ShareControllerTest {
@get:Rule
val gleanTestRule = FenixGleanTestRule(testContext)
- @get:Rule
- val coroutinesTestRule = MainCoroutineRule()
- private val testDispatcher = coroutinesTestRule.testDispatcher
- private val testCoroutineScope = coroutinesTestRule.scope
- private val controller = DefaultShareController(
- context, appStore, shareSubject, shareData, sendTabUseCases, saveToPdfUseCase, printUseCase, sentFromFirefoxManager,
- navController, recentAppStorage, testCoroutineScope, testDispatcher, FenixFxAEntryPoint.ShareMenu, dismiss,
- )
+ private val testDispatcher = StandardTestDispatcher()
@Test
- fun `handleShareClosed should call a passed in delegate to close this`() {
- controller.handleShareClosed()
+ fun `handleShareClosed should call a passed in delegate to close this`() =
+ runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ testContext,
+ appStore,
+ shareSubject,
+ shareData,
+ sendTabUseCases,
+ saveToPdfUseCase,
+ printUseCase,
+ sentFromFirefoxManager,
+ navController,
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
- verify { dismiss(ShareController.Result.DISMISSED) }
- }
+ controller.handleShareClosed()
- @OptIn(ExperimentalCoroutinesApi::class) // advanceUntilIdle
- @Test
- fun `handleShareToApp should start a new sharing activity and close this`() = runTestOnMain {
- assertNull(Events.shareToApp.testGetValue())
-
- val appPackageName = "package"
- val appClassName = "activity"
- val appShareOption = AppShareOption("app", mockk(), appPackageName, appClassName)
- val shareIntent = slot<Intent>()
- // Our share Intent uses `FLAG_ACTIVITY_NEW_TASK` but when resolving the startActivity call
- // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
- // need to use an Activity Context.
- val activityContext: Context = mockk<Activity>()
- val testController = DefaultShareController(
- activityContext, appStore, shareSubject, shareData, mockk(), mockk(),
- mockk(), sentFromFirefoxManager, mockk(), recentAppStorage, testCoroutineScope, testDispatcher,
- FenixFxAEntryPoint.ShareMenu, dismiss,
- )
- every { activityContext.startActivity(capture(shareIntent)) } just Runs
- every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs
- every { sentFromFirefoxManager.maybeAppendShareText(any(), any()) } returns textToShare
-
- testController.handleShareToApp(appShareOption)
- advanceUntilIdle()
-
- assertEquals("shareToApp event only called once", 1, Events.shareToApp.testGetValue()?.size)
- assertEquals("other", Events.shareToApp.testGetValue()?.last()?.extra?.getValue("app_package"))
-
- // Check that the Intent used for querying apps has the expected structure
- assertTrue(shareIntent.isCaptured)
- assertEquals(Intent.ACTION_SEND, shareIntent.captured.action)
- @Suppress("DEPRECATION")
- assertEquals(shareSubject, shareIntent.captured.extras!![Intent.EXTRA_SUBJECT])
- @Suppress("DEPRECATION")
- assertEquals(textToShare, shareIntent.captured.extras!![Intent.EXTRA_TEXT])
- assertEquals("text/plain", shareIntent.captured.type)
- assertEquals(Intent.FLAG_ACTIVITY_NEW_DOCUMENT + Intent.FLAG_ACTIVITY_MULTIPLE_TASK, shareIntent.captured.flags)
- assertEquals(appPackageName, shareIntent.captured.component!!.packageName)
- assertEquals(appClassName, shareIntent.captured.component!!.className)
-
- verify { recentAppStorage.updateRecentApp(appShareOption.activityName) }
- verifyOrder {
- activityContext.startActivity(shareIntent.captured)
- dismiss(ShareController.Result.SUCCESS)
+ verify { dismiss(ShareController.Result.DISMISSED) }
}
- }
@Test
- fun `handleShareToApp should record to telemetry packages which are in allowed list`() {
- assertNull(Events.shareToApp.testGetValue())
-
- val appPackageName = "com.android.bluetooth"
- val appClassName = "activity"
- val appShareOption = AppShareOption("app", mockk(), appPackageName, appClassName)
- val shareIntent = slot<Intent>()
- // Our share Intent uses `FLAG_ACTIVITY_NEW_TASK` but when resolving the startActivity call
- // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
- // need to use an Activity Context.
- val activityContext: Context = mockk<Activity>()
- val testController = DefaultShareController(
- activityContext, appStore, shareSubject, shareData, mockk(), mockk(),
- mockk(), sentFromFirefoxManager, mockk(), recentAppStorage, testCoroutineScope, testDispatcher,
- FenixFxAEntryPoint.ShareMenu, dismiss,
- )
+ fun `handleShareToApp should start a new sharing activity and close this`() =
+ runTest(testDispatcher) {
+ assertNull(Events.shareToApp.testGetValue())
+
+ val appPackageName = "package"
+ val appClassName = "activity"
+ val appShareOption = AppShareOption("app", mockk(), appPackageName, appClassName)
+ val shareIntent = slot<Intent>()
+ // Our share Intent uses `FLAG_ACTIVITY_NEW_TASK` but when resolving the startActivity call
+ // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
+ // need to use an Activity Context.
+ val activityContext: Context = mockk<Activity>()
+ val testController = DefaultShareController(
+ activityContext,
+ appStore,
+ shareSubject,
+ shareData,
+ mockk(),
+ mockk(),
+ mockk(),
+ sentFromFirefoxManager,
+ mockk(),
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
+ every { activityContext.startActivity(capture(shareIntent)) } just Runs
+ every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs
+ every { sentFromFirefoxManager.maybeAppendShareText(any(), any()) } returns textToShare
- every { activityContext.startActivity(capture(shareIntent)) } just Runs
- every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs
+ testController.handleShareToApp(appShareOption)
+ testDispatcher.scheduler.advanceUntilIdle()
- testController.handleShareToApp(appShareOption)
+ assertEquals(
+ "shareToApp event only called once",
+ 1,
+ Events.shareToApp.testGetValue()?.size,
+ )
+ assertEquals(
+ "other",
+ Events.shareToApp.testGetValue()?.last()?.extra?.getValue("app_package"),
+ )
- assertEquals("shareToApp event only called once", 1, Events.shareToApp.testGetValue()?.size)
- assertEquals("com.android.bluetooth", Events.shareToApp.testGetValue()?.last()?.extra?.getValue("app_package"))
- }
+ // Check that the Intent used for querying apps has the expected structure
+ assertTrue(shareIntent.isCaptured)
+ assertEquals(Intent.ACTION_SEND, shareIntent.captured.action)
+ @Suppress("DEPRECATION")
+ assertEquals(shareSubject, shareIntent.captured.extras!![Intent.EXTRA_SUBJECT])
+ @Suppress("DEPRECATION")
+ assertEquals(textToShare, shareIntent.captured.extras!![Intent.EXTRA_TEXT])
+ assertEquals("text/plain", shareIntent.captured.type)
+ assertEquals(
+ Intent.FLAG_ACTIVITY_NEW_DOCUMENT + Intent.FLAG_ACTIVITY_MULTIPLE_TASK,
+ shareIntent.captured.flags,
+ )
+ assertEquals(appPackageName, shareIntent.captured.component!!.packageName)
+ assertEquals(appClassName, shareIntent.captured.component!!.className)
+
+ verify { recentAppStorage.updateRecentApp(appShareOption.activityName) }
+ verifyOrder {
+ activityContext.startActivity(shareIntent.captured)
+ dismiss(ShareController.Result.SUCCESS)
+ }
+ }
@Test
- fun `handleShareToApp should record to telemetry as other when app package not in allowed list`() {
- assertNull(Events.shareToApp.testGetValue())
-
- val appPackageName = "com.package.record.not.allowed"
- val appClassName = "activity"
- val appShareOption = AppShareOption("app", mockk(), appPackageName, appClassName)
- val shareIntent = slot<Intent>()
- // Our share Intent uses `FLAG_ACTIVITY_NEW_TASK` but when resolving the startActivity call
- // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
- // need to use an Activity Context.
- val activityContext: Context = mockk<Activity>()
- val testController = DefaultShareController(
- activityContext, appStore, shareSubject, shareData, mockk(), mockk(),
- mockk(), sentFromFirefoxManager, mockk(), recentAppStorage, testCoroutineScope, testDispatcher,
- FenixFxAEntryPoint.ShareMenu, dismiss,
- )
+ fun `handleShareToApp should record to telemetry packages which are in allowed list`() =
+ runTest(testDispatcher) {
+ assertNull(Events.shareToApp.testGetValue())
+
+ val appPackageName = "com.android.bluetooth"
+ val appClassName = "activity"
+ val appShareOption = AppShareOption("app", mockk(), appPackageName, appClassName)
+ val shareIntent = slot<Intent>()
+ // Our share Intent uses `FLAG_ACTIVITY_NEW_TASK` but when resolving the startActivity call
+ // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
+ // need to use an Activity Context.
+ val activityContext: Context = mockk<Activity>()
+ val testController = DefaultShareController(
+ activityContext,
+ appStore,
+ shareSubject,
+ shareData,
+ mockk(),
+ mockk(),
+ mockk(),
+ sentFromFirefoxManager,
+ mockk(),
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
- every { activityContext.startActivity(capture(shareIntent)) } just Runs
- every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs
+ every { activityContext.startActivity(capture(shareIntent)) } just Runs
+ every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs
- testController.handleShareToApp(appShareOption)
+ testController.handleShareToApp(appShareOption)
- // Only called once and package is not in the allowed telemetry list so this should record "other"
- assertEquals("shareToApp event only called once", 1, Events.shareToApp.testGetValue()?.size)
- assertEquals("other", Events.shareToApp.testGetValue()?.last()?.extra?.getValue("app_package"))
- }
+ assertEquals(
+ "shareToApp event only called once",
+ 1,
+ Events.shareToApp.testGetValue()?.size,
+ )
+ assertEquals(
+ "com.android.bluetooth",
+ Events.shareToApp.testGetValue()?.last()?.extra?.getValue("app_package"),
+ )
+ }
@Test
- fun `handleShareToApp should dismiss with an error start when a security exception occurs`() {
- val appPackageName = "package"
- val appClassName = "activity"
- val appShareOption = AppShareOption("app", mockk(), appPackageName, appClassName)
- val shareIntent = slot<Intent>()
- // Our share Intent uses `FLAG_ACTIVITY_NEW_TASK` but when resolving the startActivity call
- // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
- // need to use an Activity Context.
- val activityContext: Context = mockk<Activity>()
- val testController = DefaultShareController(
- context = activityContext,
- appStore = appStore,
- shareSubject = shareSubject,
- shareData = shareData,
- sendTabUseCases = mockk(),
- saveToPdfUseCase = mockk(),
- printUseCase = mockk(),
- sentFromFirefoxManager = sentFromFirefoxManager,
- navController = mockk(),
- recentAppsStorage = recentAppStorage,
- viewLifecycleScope = testCoroutineScope,
- dispatcher = testDispatcher,
- dismiss = dismiss,
- )
- every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs
- every { activityContext.startActivity(capture(shareIntent)) } throws SecurityException()
- every { activityContext.getString(R.string.share_error_snackbar) } returns "Cannot share to this app"
+ fun `handleShareToApp should record to telemetry as other when app package not in allowed list`() =
+ runTest(testDispatcher) {
+ assertNull(Events.shareToApp.testGetValue())
+
+ val appPackageName = "com.package.record.not.allowed"
+ val appClassName = "activity"
+ val appShareOption = AppShareOption("app", mockk(), appPackageName, appClassName)
+ val shareIntent = slot<Intent>()
+ // Our share Intent uses `FLAG_ACTIVITY_NEW_TASK` but when resolving the startActivity call
+ // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
+ // need to use an Activity Context.
+ val activityContext: Context = mockk<Activity>()
+ val testController = DefaultShareController(
+ activityContext,
+ appStore,
+ shareSubject,
+ shareData,
+ mockk(),
+ mockk(),
+ mockk(),
+ sentFromFirefoxManager,
+ mockk(),
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
+
+ every { activityContext.startActivity(capture(shareIntent)) } just Runs
+ every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs
- testController.handleShareToApp(appShareOption)
+ testController.handleShareToApp(appShareOption)
- verifyOrder {
- activityContext.startActivity(shareIntent.captured)
- appStore.dispatch(ShareAction.ShareToAppFailed)
- dismiss(ShareController.Result.SHARE_ERROR)
+ // Only called once and package is not in the allowed telemetry list so this should record "other"
+ assertEquals(
+ "shareToApp event only called once",
+ 1,
+ Events.shareToApp.testGetValue()?.size,
+ )
+ assertEquals(
+ "other",
+ Events.shareToApp.testGetValue()?.last()?.extra?.getValue("app_package"),
+ )
}
- }
@Test
- fun `handleShareToApp should dismiss with an error start when a ActivityNotFoundException occurs`() {
- val appPackageName = "package"
- val appClassName = "activity"
- val appShareOption = AppShareOption("app", mockk(), appPackageName, appClassName)
- val shareIntent = slot<Intent>()
- // Our share Intent uses `FLAG_ACTIVITY_NEW_TASK` but when resolving the startActivity call
- // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
- // need to use an Activity Context.
- val activityContext: Context = mockk<Activity>()
- val testController = DefaultShareController(
- context = activityContext,
- appStore = appStore,
- shareSubject = shareSubject,
- shareData = shareData,
- sendTabUseCases = mockk(),
- saveToPdfUseCase = mockk(),
- printUseCase = mockk(),
- sentFromFirefoxManager = sentFromFirefoxManager,
- navController = mockk(),
- recentAppsStorage = recentAppStorage,
- viewLifecycleScope = testCoroutineScope,
- dispatcher = testDispatcher,
- dismiss = dismiss,
- )
- every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs
- every { activityContext.startActivity(capture(shareIntent)) } throws ActivityNotFoundException()
- every { activityContext.getString(R.string.share_error_snackbar) } returns "Cannot share to this app"
+ fun `handleShareToApp should dismiss with an error start when a security exception occurs`() =
+ runTest(testDispatcher) {
+ val appPackageName = "package"
+ val appClassName = "activity"
+ val appShareOption = AppShareOption("app", mockk(), appPackageName, appClassName)
+ val shareIntent = slot<Intent>()
+ // Our share Intent uses `FLAG_ACTIVITY_NEW_TASK` but when resolving the startActivity call
+ // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
+ // need to use an Activity Context.
+ val activityContext: Context = mockk<Activity>()
+ val testController = DefaultShareController(
+ context = activityContext,
+ appStore = appStore,
+ shareSubject = shareSubject,
+ shareData = shareData,
+ sendTabUseCases = mockk(),
+ saveToPdfUseCase = mockk(),
+ printUseCase = mockk(),
+ sentFromFirefoxManager = sentFromFirefoxManager,
+ navController = mockk(),
+ recentAppsStorage = recentAppStorage,
+ viewLifecycleScope = this,
+ ioDispatcher = testDispatcher,
+ dismiss = dismiss,
+ )
+ every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs
+ every { activityContext.startActivity(capture(shareIntent)) } throws SecurityException()
+ every { activityContext.getString(R.string.share_error_snackbar) } returns "Cannot share to this app"
- testController.handleShareToApp(appShareOption)
+ testController.handleShareToApp(appShareOption)
- verifyOrder {
- activityContext.startActivity(shareIntent.captured)
- appStore.dispatch(ShareAction.ShareToAppFailed)
- dismiss(ShareController.Result.SHARE_ERROR)
+ verifyOrder {
+ activityContext.startActivity(shareIntent.captured)
+ appStore.dispatch(ShareAction.ShareToAppFailed)
+ dismiss(ShareController.Result.SHARE_ERROR)
+ }
}
- }
@Test
- fun `WHEN handleSaveToPDF close the dialog and save the page to pdf`() {
- val testController = DefaultShareController(
- context = mockk(),
- appStore = appStore,
- shareSubject = shareSubject,
- shareData = shareData,
- sendTabUseCases = mockk(),
- saveToPdfUseCase = saveToPdfUseCase,
- printUseCase = mockk(),
- sentFromFirefoxManager = sentFromFirefoxManager,
- navController = mockk(),
- recentAppsStorage = recentAppStorage,
- viewLifecycleScope = testCoroutineScope,
- dispatcher = testDispatcher,
- dismiss = dismiss,
- )
+ fun `handleShareToApp should dismiss with an error start when a ActivityNotFoundException occurs`() =
+ runTest(testDispatcher) {
+ val appPackageName = "package"
+ val appClassName = "activity"
+ val appShareOption = AppShareOption("app", mockk(), appPackageName, appClassName)
+ val shareIntent = slot<Intent>()
+ // Our share Intent uses `FLAG_ACTIVITY_NEW_TASK` but when resolving the startActivity call
+ // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
+ // need to use an Activity Context.
+ val activityContext: Context = mockk<Activity>()
+ val testController = DefaultShareController(
+ context = activityContext,
+ appStore = appStore,
+ shareSubject = shareSubject,
+ shareData = shareData,
+ sendTabUseCases = mockk(),
+ saveToPdfUseCase = mockk(),
+ printUseCase = mockk(),
+ sentFromFirefoxManager = sentFromFirefoxManager,
+ navController = mockk(),
+ recentAppsStorage = recentAppStorage,
+ viewLifecycleScope = this,
+ ioDispatcher = testDispatcher,
+ dismiss = dismiss,
+ )
+ every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs
+ every { activityContext.startActivity(capture(shareIntent)) } throws ActivityNotFoundException()
+ every { activityContext.getString(R.string.share_error_snackbar) } returns "Cannot share to this app"
- testController.handleSaveToPDF("tabID")
+ testController.handleShareToApp(appShareOption)
- verify {
- saveToPdfUseCase.invoke("tabID")
- dismiss(ShareController.Result.DISMISSED)
+ verifyOrder {
+ activityContext.startActivity(shareIntent.captured)
+ appStore.dispatch(ShareAction.ShareToAppFailed)
+ dismiss(ShareController.Result.SHARE_ERROR)
+ }
}
- }
@Test
- fun `WHEN handlePrint close the dialog and print the page AND send tapped telemetry`() {
- val testController = DefaultShareController(
- context = mockk(),
- appStore = appStore,
- shareSubject = shareSubject,
- shareData = shareData,
- sendTabUseCases = mockk(),
- saveToPdfUseCase = mockk(),
- printUseCase = printUseCase,
- sentFromFirefoxManager = sentFromFirefoxManager,
- navController = mockk(),
- recentAppsStorage = recentAppStorage,
- viewLifecycleScope = testCoroutineScope,
- dispatcher = testDispatcher,
- dismiss = dismiss,
- )
+ fun `WHEN handleSaveToPDF close the dialog and save the page to pdf`() =
+ runTest(testDispatcher) {
+ val testController = DefaultShareController(
+ context = mockk(),
+ appStore = appStore,
+ shareSubject = shareSubject,
+ shareData = shareData,
+ sendTabUseCases = mockk(),
+ saveToPdfUseCase = saveToPdfUseCase,
+ printUseCase = mockk(),
+ sentFromFirefoxManager = sentFromFirefoxManager,
+ navController = mockk(),
+ recentAppsStorage = recentAppStorage,
+ viewLifecycleScope = this,
+ ioDispatcher = testDispatcher,
+ dismiss = dismiss,
+ )
- testController.handlePrint("tabID")
+ testController.handleSaveToPDF("tabID")
- verify {
- printUseCase.invoke("tabID")
- dismiss(ShareController.Result.DISMISSED)
+ verify {
+ saveToPdfUseCase.invoke("tabID")
+ dismiss(ShareController.Result.DISMISSED)
+ }
}
- assertNotNull(Events.shareMenuAction.testGetValue())
- val printTapped = Events.shareMenuAction.testGetValue()!!
- assertEquals(1, printTapped.size)
- assertEquals("print", printTapped.single().extra?.getValue("item"))
- }
-
@Test
- fun `getShareSubject should return the shareSubject when shareSubject is not null`() {
- val activityContext: Context = mockk<Activity>()
- val testController = DefaultShareController(
- context = activityContext,
- appStore = appStore,
- shareSubject = shareSubject,
- shareData = shareData,
- sendTabUseCases = mockk(),
- saveToPdfUseCase = mockk(),
- printUseCase = mockk(),
- sentFromFirefoxManager = sentFromFirefoxManager,
- navController = mockk(),
- recentAppsStorage = recentAppStorage,
- viewLifecycleScope = testCoroutineScope,
- dispatcher = testDispatcher,
- dismiss = dismiss,
- )
+ fun `WHEN handlePrint close the dialog and print the page AND send tapped telemetry`() =
+ runTest(testDispatcher) {
+ val testController = DefaultShareController(
+ context = mockk(),
+ appStore = appStore,
+ shareSubject = shareSubject,
+ shareData = shareData,
+ sendTabUseCases = mockk(),
+ saveToPdfUseCase = mockk(),
+ printUseCase = printUseCase,
+ sentFromFirefoxManager = sentFromFirefoxManager,
+ navController = mockk(),
+ recentAppsStorage = recentAppStorage,
+ viewLifecycleScope = this,
+ ioDispatcher = testDispatcher,
+ dismiss = dismiss,
+ )
- assertEquals(shareSubject, testController.getShareSubject())
- }
+ testController.handlePrint("tabID")
- @Test
- fun `getShareSubject should return a combination of non-null titles when shareSubject is null`() {
- val activityContext: Context = mockk<Activity>()
- val testController = DefaultShareController(
- context = activityContext,
- appStore = appStore,
- shareSubject = null,
- shareData = shareData,
- sendTabUseCases = mockk(),
- saveToPdfUseCase = mockk(),
- printUseCase = mockk(),
- sentFromFirefoxManager = sentFromFirefoxManager,
- navController = mockk(),
- recentAppsStorage = recentAppStorage,
- viewLifecycleScope = testCoroutineScope,
- dispatcher = testDispatcher,
- dismiss = dismiss,
- )
+ verify {
+ printUseCase.invoke("tabID")
+ dismiss(ShareController.Result.DISMISSED)
+ }
- assertEquals("title0, title1", testController.getShareSubject())
- }
+ assertNotNull(Events.shareMenuAction.testGetValue())
+ val printTapped = Events.shareMenuAction.testGetValue()!!
+ assertEquals(1, printTapped.size)
+ assertEquals("print", printTapped.single().extra?.getValue("item"))
+ }
@Test
- fun `getShareSubject should return just the not null titles string when shareSubject is null`() {
- val activityContext: Context = mockk<Activity>()
- val partialTitlesShareData = listOf(
- ShareData(url = "url0", title = null),
- ShareData(url = "url1", title = "title1"),
- )
- val testController = DefaultShareController(
- context = activityContext,
- appStore = appStore,
- shareSubject = null,
- shareData = partialTitlesShareData,
- sendTabUseCases = mockk(),
- saveToPdfUseCase = mockk(),
- printUseCase = mockk(),
- sentFromFirefoxManager = sentFromFirefoxManager,
- navController = mockk(),
- recentAppsStorage = recentAppStorage,
- viewLifecycleScope = testCoroutineScope,
- dispatcher = testDispatcher,
- dismiss = dismiss,
- )
+ fun `getShareSubject should return the shareSubject when shareSubject is not null`() =
+ runTest(testDispatcher) {
+ val activityContext: Context = mockk<Activity>()
+ val testController = DefaultShareController(
+ context = activityContext,
+ appStore = appStore,
+ shareSubject = shareSubject,
+ shareData = shareData,
+ sendTabUseCases = mockk(),
+ saveToPdfUseCase = mockk(),
+ printUseCase = mockk(),
+ sentFromFirefoxManager = sentFromFirefoxManager,
+ navController = mockk(),
+ recentAppsStorage = recentAppStorage,
+ viewLifecycleScope = this,
+ ioDispatcher = testDispatcher,
+ dismiss = dismiss,
+ )
- assertEquals("title1", testController.getShareSubject())
- }
+ assertEquals(shareSubject, testController.getShareSubject())
+ }
@Test
- fun `getShareSubject should return empty string when shareSubject and all titles are null`() {
- val activityContext: Context = mockk<Activity>()
- val noTitleShareData = listOf(
- ShareData(url = "url0", title = null),
- ShareData(url = "url1", title = null),
- )
- val testController = DefaultShareController(
- context = activityContext,
- appStore = appStore,
- shareSubject = null,
- shareData = noTitleShareData,
- sendTabUseCases = mockk(),
- saveToPdfUseCase = mockk(),
- printUseCase = mockk(),
- sentFromFirefoxManager = sentFromFirefoxManager,
- navController = mockk(),
- recentAppsStorage = recentAppStorage,
- viewLifecycleScope = testCoroutineScope,
- dispatcher = testDispatcher,
- dismiss = dismiss,
- )
+ fun `getShareSubject should return a combination of non-null titles when shareSubject is null`() =
+ runTest(testDispatcher) {
+ val activityContext: Context = mockk<Activity>()
+ val testController = DefaultShareController(
+ context = activityContext,
+ appStore = appStore,
+ shareSubject = null,
+ shareData = shareData,
+ sendTabUseCases = mockk(),
+ saveToPdfUseCase = mockk(),
+ printUseCase = mockk(),
+ sentFromFirefoxManager = sentFromFirefoxManager,
+ navController = mockk(),
+ recentAppsStorage = recentAppStorage,
+ viewLifecycleScope = this,
+ ioDispatcher = testDispatcher,
+ dismiss = dismiss,
+ )
- assertEquals("", testController.getShareSubject())
- }
+ assertEquals("title0, title1", testController.getShareSubject())
+ }
@Test
- fun `getShareSubject should return empty string when shareSubject is null and and all titles are empty`() {
- val activityContext: Context = mockk<Activity>()
- val noTitleShareData = listOf(
- ShareData(url = "url0", title = ""),
- ShareData(url = "url1", title = ""),
- )
- val testController = DefaultShareController(
- appStore = appStore,
- context = activityContext,
- shareSubject = null,
- shareData = noTitleShareData,
- sendTabUseCases = mockk(),
- saveToPdfUseCase = mockk(),
- printUseCase = mockk(),
- sentFromFirefoxManager = sentFromFirefoxManager,
- navController = mockk(),
- recentAppsStorage = recentAppStorage,
- viewLifecycleScope = testCoroutineScope,
- dispatcher = testDispatcher,
- dismiss = dismiss,
- )
+ fun `getShareSubject should return just the not null titles string when shareSubject is null`() =
+ runTest(testDispatcher) {
+ val activityContext: Context = mockk<Activity>()
+ val partialTitlesShareData = listOf(
+ ShareData(url = "url0", title = null),
+ ShareData(url = "url1", title = "title1"),
+ )
+ val testController = DefaultShareController(
+ context = activityContext,
+ appStore = appStore,
+ shareSubject = null,
+ shareData = partialTitlesShareData,
+ sendTabUseCases = mockk(),
+ saveToPdfUseCase = mockk(),
+ printUseCase = mockk(),
+ sentFromFirefoxManager = sentFromFirefoxManager,
+ navController = mockk(),
+ recentAppsStorage = recentAppStorage,
+ viewLifecycleScope = this,
+ ioDispatcher = testDispatcher,
+ dismiss = dismiss,
+ )
- assertEquals("", testController.getShareSubject())
- }
+ assertEquals("title1", testController.getShareSubject())
+ }
@Test
- @Suppress("DeferredResultUnused")
- fun `handleShareToDevice should share to account device, inform callbacks and dismiss`() {
- val deviceToShareTo = Device(
- "deviceId",
- "deviceName",
- DeviceType.UNKNOWN,
- false,
- 0L,
- emptyList(),
- false,
- null,
- )
- val deviceId = slot<String>()
- val tabsShared = slot<List<TabData>>()
-
- every { sendTabUseCases.sendToDeviceAsync(any(), any<List<TabData>>()) } returns CompletableDeferred(true)
- every { navController.currentDestination?.id } returns R.id.shareFragment
+ fun `getShareSubject should return empty string when shareSubject and all titles are null`() =
+ runTest(testDispatcher) {
+ val activityContext: Context = mockk<Activity>()
+ val noTitleShareData = listOf(
+ ShareData(url = "url0", title = null),
+ ShareData(url = "url1", title = null),
+ )
+ val testController = DefaultShareController(
+ context = activityContext,
+ appStore = appStore,
+ shareSubject = null,
+ shareData = noTitleShareData,
+ sendTabUseCases = mockk(),
+ saveToPdfUseCase = mockk(),
+ printUseCase = mockk(),
+ sentFromFirefoxManager = sentFromFirefoxManager,
+ navController = mockk(),
+ recentAppsStorage = recentAppStorage,
+ viewLifecycleScope = this,
+ ioDispatcher = testDispatcher,
+ dismiss = dismiss,
+ )
- controller.handleShareToDevice(deviceToShareTo)
+ assertEquals("", testController.getShareSubject())
+ }
- assertNotNull(SyncAccount.sendTab.testGetValue())
- assertEquals(1, SyncAccount.sendTab.testGetValue()!!.size)
- assertNull(SyncAccount.sendTab.testGetValue()!!.single().extra)
+ @Test
+ fun `getShareSubject should return empty string when shareSubject is null and and all titles are empty`() =
+ runTest(testDispatcher) {
+ val activityContext: Context = mockk<Activity>()
+ val noTitleShareData = listOf(
+ ShareData(url = "url0", title = ""),
+ ShareData(url = "url1", title = ""),
+ )
+ val testController = DefaultShareController(
+ appStore = appStore,
+ context = activityContext,
+ shareSubject = null,
+ shareData = noTitleShareData,
+ sendTabUseCases = mockk(),
+ saveToPdfUseCase = mockk(),
+ printUseCase = mockk(),
+ sentFromFirefoxManager = sentFromFirefoxManager,
+ navController = mockk(),
+ recentAppsStorage = recentAppStorage,
+ viewLifecycleScope = this,
+ ioDispatcher = testDispatcher,
+ dismiss = dismiss,
+ )
- verifyOrder {
- sendTabUseCases.sendToDeviceAsync(capture(deviceId), capture(tabsShared))
- dismiss(ShareController.Result.SUCCESS)
+ assertEquals("", testController.getShareSubject())
}
- assertTrue(deviceId.isCaptured)
- assertEquals(deviceToShareTo.id, deviceId.captured)
- assertTrue(tabsShared.isCaptured)
- assertEquals(tabsData, tabsShared.captured)
- }
-
@Test
- @Suppress("DeferredResultUnused")
- fun `handleShareToAllDevices calls handleShareToDevice multiple times`() {
- every { sendTabUseCases.sendToAllAsync(any<List<TabData>>()) } returns CompletableDeferred(true)
- every { navController.currentDestination?.id } returns R.id.shareFragment
-
- val devicesToShareTo = listOf(
- Device(
- "deviceId0",
- "deviceName0",
+ fun `handleShareToDevice should share to account device, inform callbacks and dismiss`() =
+ runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ testContext,
+ appStore,
+ shareSubject,
+ shareData,
+ sendTabUseCases,
+ saveToPdfUseCase,
+ printUseCase,
+ sentFromFirefoxManager,
+ navController,
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
+
+ val deviceToShareTo = Device(
+ "deviceId",
+ "deviceName",
DeviceType.UNKNOWN,
false,
0L,
emptyList(),
false,
null,
- ),
- Device(
- "deviceId1",
- "deviceName1",
- DeviceType.UNKNOWN,
- true,
- 1L,
- emptyList(),
- false,
- null,
- ),
- )
- val tabsShared = slot<List<TabData>>()
-
- controller.handleShareToAllDevices(devicesToShareTo)
-
- verifyOrder {
- sendTabUseCases.sendToAllAsync(capture(tabsShared))
- dismiss(ShareController.Result.SUCCESS)
+ )
+ val deviceId = slot<String>()
+ val tabsShared = slot<List<TabData>>()
+
+ every {
+ sendTabUseCases.sendToDeviceAsync(
+ any(),
+ any<List<TabData>>(),
+ )
+ } returns CompletableDeferred(true)
+ every { navController.currentDestination?.id } returns R.id.shareFragment
+
+ controller.handleShareToDevice(deviceToShareTo)
+ testDispatcher.scheduler.advanceUntilIdle()
+
+ assertNotNull(SyncAccount.sendTab.testGetValue())
+ assertEquals(1, SyncAccount.sendTab.testGetValue()!!.size)
+ assertNull(SyncAccount.sendTab.testGetValue()!!.single().extra)
+
+ verifyOrder {
+ sendTabUseCases.sendToDeviceAsync(capture(deviceId), capture(tabsShared))
+ dismiss(ShareController.Result.SUCCESS)
+ }
+
+ assertTrue(deviceId.isCaptured)
+ assertEquals(deviceToShareTo.id, deviceId.captured)
+ assertTrue(tabsShared.isCaptured)
+ assertEquals(tabsData, tabsShared.captured)
}
- // SendTabUseCases should send a the `shareTabs` mapped to tabData
- assertTrue(tabsShared.isCaptured)
- assertEquals(tabsData, tabsShared.captured)
- }
-
@Test
- fun `handleSignIn should navigate to the Sync Fragment and dismiss this one`() {
- controller.handleSignIn()
-
- assertNotNull(SyncAccount.signInToSendTab.testGetValue())
- assertEquals(1, SyncAccount.signInToSendTab.testGetValue()!!.size)
- assertNull(SyncAccount.signInToSendTab.testGetValue()!!.single().extra)
+ fun `handleShareToAllDevices calls handleShareToDevice multiple times`() =
+ runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ testContext,
+ appStore,
+ shareSubject,
+ shareData,
+ sendTabUseCases,
+ saveToPdfUseCase,
+ printUseCase,
+ sentFromFirefoxManager,
+ navController,
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
- verifyOrder {
- navController.navigate(
- ShareFragmentDirections.actionGlobalTurnOnSync(
- entrypoint = FenixFxAEntryPoint.ShareMenu,
+ every { sendTabUseCases.sendToAllAsync(any<List<TabData>>()) } returns CompletableDeferred(
+ true,
+ )
+ every { navController.currentDestination?.id } returns R.id.shareFragment
+
+ val devicesToShareTo = listOf(
+ Device(
+ "deviceId0",
+ "deviceName0",
+ DeviceType.UNKNOWN,
+ false,
+ 0L,
+ emptyList(),
+ false,
+ null,
+ ),
+ Device(
+ "deviceId1",
+ "deviceName1",
+ DeviceType.UNKNOWN,
+ true,
+ 1L,
+ emptyList(),
+ false,
+ null,
),
- null,
)
- dismiss(ShareController.Result.DISMISSED)
+ val tabsShared = slot<List<TabData>>()
+
+ controller.handleShareToAllDevices(devicesToShareTo)
+ testDispatcher.scheduler.advanceUntilIdle()
+
+ verifyOrder {
+ sendTabUseCases.sendToAllAsync(capture(tabsShared))
+ dismiss(ShareController.Result.SUCCESS)
+ }
+
+ // SendTabUseCases should send a the `shareTabs` mapped to tabData
+ assertTrue(tabsShared.isCaptured)
+ assertEquals(tabsData, tabsShared.captured)
}
- }
@Test
- fun `handleReauth should navigate to the Account Problem Fragment and dismiss this one`() {
- controller.handleReauth()
+ fun `handleSignIn should navigate to the Sync Fragment and dismiss this one`() =
+ runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ testContext,
+ appStore,
+ shareSubject,
+ shareData,
+ sendTabUseCases,
+ saveToPdfUseCase,
+ printUseCase,
+ sentFromFirefoxManager,
+ navController,
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
- verifyOrder {
- navController.navigate(
- ShareFragmentDirections.actionGlobalAccountProblemFragment(
- entrypoint = FenixFxAEntryPoint.ShareMenu,
- ),
- null,
+ controller.handleSignIn()
+
+ assertNotNull(SyncAccount.signInToSendTab.testGetValue())
+ assertEquals(1, SyncAccount.signInToSendTab.testGetValue()!!.size)
+ assertNull(SyncAccount.signInToSendTab.testGetValue()!!.single().extra)
+
+ verifyOrder {
+ navController.navigate(
+ ShareFragmentDirections.actionGlobalTurnOnSync(
+ entrypoint = FenixFxAEntryPoint.ShareMenu,
+ ),
+ null,
+ )
+ dismiss(ShareController.Result.DISMISSED)
+ }
+ }
+
+ @Test
+ fun `handleReauth should navigate to the Account Problem Fragment and dismiss this one`() =
+ runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ testContext,
+ appStore,
+ shareSubject,
+ shareData,
+ sendTabUseCases,
+ saveToPdfUseCase,
+ printUseCase,
+ sentFromFirefoxManager,
+ navController,
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
)
- dismiss(ShareController.Result.DISMISSED)
+
+ controller.handleReauth()
+
+ verifyOrder {
+ navController.navigate(
+ ShareFragmentDirections.actionGlobalAccountProblemFragment(
+ entrypoint = FenixFxAEntryPoint.ShareMenu,
+ ),
+ null,
+ )
+ dismiss(ShareController.Result.DISMISSED)
+ }
}
- }
@Test
- fun `showSuccess should update AppStore with a success action`() {
+ fun `showSuccess should update AppStore with a success action`() = runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ testContext,
+ appStore,
+ shareSubject,
+ shareData,
+ sendTabUseCases,
+ saveToPdfUseCase,
+ printUseCase,
+ sentFromFirefoxManager,
+ navController,
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
+
val destinations = listOf("a", "b")
val expectedTabsShared = with(controller) { shareData.toTabData() }
controller.showSuccess(destinations)
- verify { appStore.dispatch(ShareAction.SharedTabsSuccessfully(destinations, expectedTabsShared)) }
+ verify {
+ appStore.dispatch(
+ ShareAction.SharedTabsSuccessfully(
+ destinations,
+ expectedTabsShared,
+ ),
+ )
+ }
}
@Test
- fun `showFailureWithRetryOption should update AppStore with a failure action`() {
- val destinations = listOf("a", "b")
- val expectedTabsShared = with(controller) { shareData.toTabData() }
+ fun `showFailureWithRetryOption should update AppStore with a failure action`() =
+ runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ testContext,
+ appStore,
+ shareSubject,
+ shareData,
+ sendTabUseCases,
+ saveToPdfUseCase,
+ printUseCase,
+ sentFromFirefoxManager,
+ navController,
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
- controller.showFailureWithRetryOption(destinations)
+ val destinations = listOf("a", "b")
+ val expectedTabsShared = with(controller) { shareData.toTabData() }
- verify { appStore.dispatch(ShareAction.ShareTabsFailed(destinations, expectedTabsShared)) }
- }
+ controller.showFailureWithRetryOption(destinations)
+
+ verify {
+ appStore.dispatch(
+ ShareAction.ShareTabsFailed(
+ destinations,
+ expectedTabsShared,
+ ),
+ )
+ }
+ }
@Test
- fun `getShareText should respect concatenate shared tabs urls`() {
+ fun `getShareText should respect concatenate shared tabs urls`() = runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ testContext,
+ appStore,
+ shareSubject,
+ shareData,
+ sendTabUseCases,
+ saveToPdfUseCase,
+ printUseCase,
+ sentFromFirefoxManager,
+ navController,
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
+
assertEquals(textToShare, controller.getShareText())
}
@Test
- fun `getShareText attempts to use original URL for reader pages`() {
+ fun `getShareText attempts to use original URL for reader pages`() = runTest(testDispatcher) {
val shareData = listOf(
ShareData(url = "moz-extension://eb8df45a-895b-4f3a-896a-c0c71ae4/page.html"),
ShareData(url = "moz-extension://eb8df45a-895b-4f3a-896a-c0c71ae5/page.html?url=url0"),
ShareData(url = "url1"),
)
val controller = DefaultShareController(
- context = context,
+ context = testContext,
appStore = appStore,
shareSubject = shareSubject,
shareData = shareData,
@@ -610,8 +840,8 @@ class ShareControllerTest {
sentFromFirefoxManager = sentFromFirefoxManager,
navController = navController,
recentAppsStorage = recentAppStorage,
- viewLifecycleScope = testCoroutineScope,
- dispatcher = testDispatcher,
+ viewLifecycleScope = this,
+ ioDispatcher = testDispatcher,
dismiss = dismiss,
)
@@ -620,33 +850,71 @@ class ShareControllerTest {
}
@Test
- fun `getShareSubject will return 'shareSubject' if that is non null`() {
- assertEquals(shareSubject, controller.getShareSubject())
- }
+ fun `getShareSubject will return 'shareSubject' if that is non null`() =
+ runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ testContext,
+ appStore,
+ shareSubject,
+ shareData,
+ sendTabUseCases,
+ saveToPdfUseCase,
+ printUseCase,
+ sentFromFirefoxManager,
+ navController,
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
+
+ assertEquals(shareSubject, controller.getShareSubject())
+ }
@Test
- fun `getShareSubject will return a concatenation of tab titles if 'shareSubject' is null`() {
- val controller = DefaultShareController(
- context = context,
- appStore = appStore,
- shareSubject = null,
- shareData = shareData,
- sendTabUseCases = sendTabUseCases,
- saveToPdfUseCase = mockk(),
- printUseCase = mockk(),
- sentFromFirefoxManager = sentFromFirefoxManager,
- navController = navController,
- recentAppsStorage = recentAppStorage,
- viewLifecycleScope = testCoroutineScope,
- dispatcher = testDispatcher,
- dismiss = dismiss,
- )
+ fun `getShareSubject will return a concatenation of tab titles if 'shareSubject' is null`() =
+ runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ context = testContext,
+ appStore = appStore,
+ shareSubject = null,
+ shareData = shareData,
+ sendTabUseCases = sendTabUseCases,
+ saveToPdfUseCase = mockk(),
+ printUseCase = mockk(),
+ sentFromFirefoxManager = sentFromFirefoxManager,
+ navController = navController,
+ recentAppsStorage = recentAppStorage,
+ viewLifecycleScope = this,
+ ioDispatcher = testDispatcher,
+ dismiss = dismiss,
+ )
- assertEquals("title0, title1", controller.getShareSubject())
- }
+ assertEquals("title0, title1", controller.getShareSubject())
+ }
@Test
- fun `ShareTab#toTabData maps a list of ShareTab to a TabData list`() {
+ fun `ShareTab#toTabData maps a list of ShareTab to a TabData list`() = runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ testContext,
+ appStore,
+ shareSubject,
+ shareData,
+ sendTabUseCases,
+ saveToPdfUseCase,
+ printUseCase,
+ sentFromFirefoxManager,
+ navController,
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
+
var tabData: List<TabData>
with(controller) {
@@ -657,20 +925,39 @@ class ShareControllerTest {
}
@Test
- fun `ShareTab#toTabData creates a data url from text if no url is specified`() {
- var tabData: List<TabData>
- val expected = listOf(
- TabData(title = "title0", url = ""),
- TabData(title = "title1", url = "data:,Hello%2C%20World!"),
- )
+ fun `ShareTab#toTabData creates a data url from text if no url is specified`() =
+ runTest(testDispatcher) {
+ val controller = DefaultShareController(
+ testContext,
+ appStore,
+ shareSubject,
+ shareData,
+ sendTabUseCases,
+ saveToPdfUseCase,
+ printUseCase,
+ sentFromFirefoxManager,
+ navController,
+ recentAppStorage,
+ this,
+ testDispatcher,
+ testDispatcher,
+ FenixFxAEntryPoint.ShareMenu,
+ dismiss,
+ )
- with(controller) {
- tabData = listOf(
- ShareData(title = "title0"),
- ShareData(title = "title1", text = "Hello, World!"),
- ).toTabData()
- }
+ var tabData: List<TabData>
+ val expected = listOf(
+ TabData(title = "title0", url = ""),
+ TabData(title = "title1", url = "data:,Hello%2C%20World!"),
+ )
- assertEquals(expected, tabData)
- }
+ with(controller) {
+ tabData = listOf(
+ ShareData(title = "title0"),
+ ShareData(title = "title1", text = "Hello, World!"),
+ ).toTabData()
+ }
+
+ assertEquals(expected, tabData)
+ }
}