From 5cce4b5f15ffcbfa70079318f284c67de6d8bb6b Mon Sep 17 00:00:00 2001 From: Arturo Mejia Date: Mon, 3 Oct 2022 15:46:53 -0400 Subject: [PATCH] For #3709: Add save to PDF UI. --- app/metrics.yaml | 16 ++ .../java/org/mozilla/fenix/FeatureFlags.kt | 5 + .../toolbar/BrowserToolbarMenuController.kt | 1 + .../SessionControlController.kt | 1 + .../fenix/share/SaveToPDFInteractor.kt | 16 ++ .../org/mozilla/fenix/share/SaveToPDFItem.kt | 70 +++++++ .../mozilla/fenix/share/ShareController.kt | 16 +- .../org/mozilla/fenix/share/ShareFragment.kt | 19 ++ .../mozilla/fenix/share/ShareInteractor.kt | 6 +- app/src/main/res/layout/fragment_share.xml | 29 ++- app/src/main/res/navigation/nav_graph.xml | 2 +- app/src/main/res/values/strings.xml | 2 + ...DefaultBrowserToolbarMenuControllerTest.kt | 2 + .../fenix/share/ShareControllerTest.kt | 171 +++++++++++++++--- .../fenix/share/ShareInteractorTest.kt | 7 + 15 files changed, 324 insertions(+), 39 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/share/SaveToPDFInteractor.kt create mode 100644 app/src/main/java/org/mozilla/fenix/share/SaveToPDFItem.kt diff --git a/app/metrics.yaml b/app/metrics.yaml index 2ff109a3f..bc00d8713 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -449,6 +449,22 @@ events: notification_emails: - android-probes@mozilla.com expires: 113 + save_to_pdf_tapped: + type: event + description: | + A user tapped the save to pdf option in the share sheet. + bugs: + - https://github.com/mozilla-mobile/fenix/issues/3709 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/27257 + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + expires: 122 + metadata: + tags: + - Sharing onboarding: syn_cfr_shown: diff --git a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt index 5f5f1b4f3..d98b03cf5 100644 --- a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt +++ b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt @@ -118,4 +118,9 @@ object FeatureFlags { * Enables the wallpaper v2 enhancements. */ const val wallpaperV2Enabled = true + + /** + * Enables the save to PDF feature. + */ + val saveToPDF = Config.channel.isNightlyOrDebug } diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt index 6fdb31fd7..ff31317c1 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarMenuController.kt @@ -211,6 +211,7 @@ class DefaultBrowserToolbarMenuController( } is ToolbarMenu.Item.Share -> { val directions = NavGraphDirections.actionGlobalShareFragment( + sessionId = currentSession?.id, data = arrayOf( ShareData( url = getProperUrl(currentSession), diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt index 6ff7d30fe..1b768d44d 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt @@ -583,6 +583,7 @@ class DefaultSessionControlController( private fun showShareFragment(shareSubject: String, data: List) { val directions = HomeFragmentDirections.actionGlobalShareFragment( + sessionId = store.state.selectedTabId, shareSubject = shareSubject, data = data.toTypedArray(), ) diff --git a/app/src/main/java/org/mozilla/fenix/share/SaveToPDFInteractor.kt b/app/src/main/java/org/mozilla/fenix/share/SaveToPDFInteractor.kt new file mode 100644 index 000000000..5bfcb7516 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/share/SaveToPDFInteractor.kt @@ -0,0 +1,16 @@ +/* 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.share + +/** + * Callbacks for possible user interactions on the [SaveToPDFItem] + */ +interface SaveToPDFInteractor { + /** + * Generates a PDF from the given [tabId]. + * @param tabId The ID of the tab to save as PDF. + */ + fun onSaveToPDF(tabId: String?) +} diff --git a/app/src/main/java/org/mozilla/fenix/share/SaveToPDFItem.kt b/app/src/main/java/org/mozilla/fenix/share/SaveToPDFItem.kt new file mode 100644 index 000000000..728a4d627 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/share/SaveToPDFItem.kt @@ -0,0 +1,70 @@ +/* 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.share + +import android.content.res.Configuration +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.material.Icon +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import org.mozilla.fenix.R +import org.mozilla.fenix.theme.FirefoxTheme + +/** + * A save to PDF item. + * + * @param onClick event handler when the save to PDF item is clicked. + */ +@Composable +fun SaveToPDFItem( + onClick: () -> Unit, +) { + Row( + modifier = Modifier + .height(56.dp) + .fillMaxWidth() + .clickable(onClick = onClick), + verticalAlignment = Alignment.CenterVertically, + ) { + Spacer(Modifier.width(16.dp)) + + Icon( + painter = painterResource(R.drawable.ic_download), + contentDescription = stringResource( + R.string.content_description_close_button, + ), + tint = FirefoxTheme.colors.iconPrimary, + ) + + Spacer(Modifier.width(32.dp)) + + Text( + color = FirefoxTheme.colors.textPrimary, + text = stringResource(R.string.share_save_to_pdf), + style = FirefoxTheme.typography.subtitle1, + ) + } +} + +@Composable +@Preview +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO) +private fun SaveToPDFItemPreview() { + FirefoxTheme { + SaveToPDFItem {} + } +} diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareController.kt b/app/src/main/java/org/mozilla/fenix/share/ShareController.kt index 054e5d0bc..72cd1ff08 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareController.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareController.kt @@ -29,9 +29,11 @@ import mozilla.components.concept.engine.prompt.ShareData import mozilla.components.concept.sync.Device import mozilla.components.concept.sync.TabData import mozilla.components.feature.accounts.push.SendTabUseCases +import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.share.RecentAppsStorage import mozilla.components.service.glean.private.NoExtras import mozilla.components.support.ktx.kotlin.isExtensionUrl +import org.mozilla.fenix.GleanMetrics.Events import org.mozilla.fenix.GleanMetrics.SyncAccount import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar @@ -47,6 +49,11 @@ interface ShareController { fun handleReauth() fun handleShareClosed() fun handleShareToApp(app: AppShareOption) + + /** + * Handles when a save to PDF action was requested. + */ + fun handleSaveToPDF(tabId: String?) fun handleAddNewDevice() fun handleShareToDevice(device: Device) fun handleShareToAllDevices(devices: List) @@ -68,12 +75,13 @@ interface ShareController { * @param navController - [NavController] used for navigation. * @param dismiss - callback signalling sharing can be closed. */ -@Suppress("TooManyFunctions") +@Suppress("TooManyFunctions", "LongParameterList") class DefaultShareController( private val context: Context, private val shareSubject: String?, private val shareData: List, private val sendTabUseCases: SendTabUseCases, + private val saveToPdfUseCase: SessionUseCases.SaveToPdfUseCase, private val snackbar: FenixSnackbar, private val navController: NavController, private val recentAppsStorage: RecentAppsStorage, @@ -130,6 +138,12 @@ class DefaultShareController( dismiss(result) } + override fun handleSaveToPDF(tabId: String?) { + Events.saveToPdfTapped.record(NoExtras()) + handleShareClosed() + saveToPdfUseCase.invoke(tabId) + } + override fun handleAddNewDevice() { val directions = ShareFragmentDirections.actionShareFragmentToAddNewDeviceFragment() navController.navigate(directions) diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt index 6a871d490..0574448ac 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt @@ -10,6 +10,8 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AppCompatDialogFragment +import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.core.view.isVisible import androidx.fragment.app.clearFragmentResult import androidx.fragment.app.setFragmentResult import androidx.fragment.app.viewModels @@ -22,11 +24,13 @@ import mozilla.components.browser.state.selector.findTabOrCustomTab import mozilla.components.concept.engine.prompt.PromptRequest import mozilla.components.feature.accounts.push.SendTabUseCases import mozilla.components.feature.share.RecentAppsStorage +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.databinding.FragmentShareBinding import org.mozilla.fenix.ext.getRootView import org.mozilla.fenix.ext.requireComponents +import org.mozilla.fenix.theme.FirefoxTheme class ShareFragment : AppCompatDialogFragment() { @@ -80,6 +84,7 @@ class ShareFragment : AppCompatDialogFragment() { ), navController = findNavController(), sendTabUseCases = SendTabUseCases(accountManager), + saveToPdfUseCase = requireComponents.useCases.sessionUseCases.saveToPdf, recentAppsStorage = RecentAppsStorage(requireContext()), viewLifecycleScope = viewLifecycleOwner.lifecycleScope, ) { result -> @@ -111,6 +116,20 @@ class ShareFragment : AppCompatDialogFragment() { } shareToAppsView = ShareToAppsView(binding.appsShareLayout, shareInteractor) + if (FeatureFlags.saveToPDF) { + binding.dividerLineAppsShareAndPdfSection.isVisible = true + binding.savePdf.apply { + isVisible = true + setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) + setContent { + FirefoxTheme { + SaveToPDFItem { + shareInteractor.onSaveToPDF(tabId = args.sessionId) + } + } + } + } + } return binding.root } diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareInteractor.kt b/app/src/main/java/org/mozilla/fenix/share/ShareInteractor.kt index fe6897d51..bd945b5ce 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareInteractor.kt @@ -12,7 +12,7 @@ import org.mozilla.fenix.share.listadapters.AppShareOption */ class ShareInteractor( private val controller: ShareController, -) : ShareCloseInteractor, ShareToAccountDevicesInteractor, ShareToAppsInteractor { +) : ShareCloseInteractor, ShareToAccountDevicesInteractor, ShareToAppsInteractor, SaveToPDFInteractor { override fun onReauth() { controller.handleReauth() } @@ -40,4 +40,8 @@ class ShareInteractor( override fun onShareToApp(appToShareTo: AppShareOption) { controller.handleShareToApp(appToShareTo) } + + override fun onSaveToPDF(tabId: String?) { + controller.handleSaveToPDF(tabId) + } } diff --git a/app/src/main/res/layout/fragment_share.xml b/app/src/main/res/layout/fragment_share.xml index edf766367..f7a284739 100644 --- a/app/src/main/res/layout/fragment_share.xml +++ b/app/src/main/res/layout/fragment_share.xml @@ -34,18 +34,18 @@ android:background="@drawable/bottom_sheet_dialog_fragment_background" app:layout_constraintBottom_toBottomOf="parent"> - - + + + + + + Share + + Save as PDF Send to device diff --git a/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt b/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt index 3e8a41354..82f505f02 100644 --- a/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/toolbar/DefaultBrowserToolbarMenuControllerTest.kt @@ -623,6 +623,7 @@ class DefaultBrowserToolbarMenuControllerTest { navController.navigate( directionsEq( NavGraphDirections.actionGlobalShareFragment( + sessionId = browserStore.state.selectedTabId, data = arrayOf(ShareData(url = "https://mozilla.org", title = "Mozilla")), showPage = true, ), @@ -656,6 +657,7 @@ class DefaultBrowserToolbarMenuControllerTest { navController.navigate( directionsEq( NavGraphDirections.actionGlobalShareFragment( + sessionId = browserStore.state.selectedTabId, data = arrayOf(ShareData(url = "https://mozilla.org", title = "Mozilla")), showPage = true, ), diff --git a/app/src/test/java/org/mozilla/fenix/share/ShareControllerTest.kt b/app/src/test/java/org/mozilla/fenix/share/ShareControllerTest.kt index 40319abb0..bba52f217 100644 --- a/app/src/test/java/org/mozilla/fenix/share/ShareControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/share/ShareControllerTest.kt @@ -24,6 +24,7 @@ import mozilla.components.concept.sync.Device import mozilla.components.concept.sync.DeviceType import mozilla.components.concept.sync.TabData import mozilla.components.feature.accounts.push.SendTabUseCases +import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.share.RecentAppsStorage import mozilla.components.service.glean.testing.GleanTestRule import mozilla.components.support.test.robolectric.testContext @@ -37,6 +38,7 @@ import org.junit.Assert.assertTrue import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mozilla.fenix.GleanMetrics.Events import org.mozilla.fenix.GleanMetrics.SyncAccount import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar @@ -61,6 +63,7 @@ class ShareControllerTest { ) private val textToShare = "${shareData[0].url}\n\n${shareData[1].url}" private val sendTabUseCases = mockk(relaxed = true) + private val saveToPdfUseCase = mockk(relaxed = true) private val snackbar = mockk(relaxed = true) private val navController = mockk(relaxed = true) private val dismiss = mockk<(ShareController.Result) -> Unit>(relaxed = true) @@ -74,7 +77,7 @@ class ShareControllerTest { private val testDispatcher = coroutinesTestRule.testDispatcher private val testCoroutineScope = coroutinesTestRule.scope private val controller = DefaultShareController( - context, shareSubject, shareData, sendTabUseCases, snackbar, navController, + context, shareSubject, shareData, sendTabUseCases, saveToPdfUseCase, snackbar, navController, recentAppStorage, testCoroutineScope, testDispatcher, dismiss, ) @@ -96,7 +99,7 @@ class ShareControllerTest { // need to use an Activity Context. val activityContext: Context = mockk() val testController = DefaultShareController( - activityContext, shareSubject, shareData, mockk(), + activityContext, shareSubject, shareData, mockk(), mockk(), mockk(), mockk(), recentAppStorage, testCoroutineScope, testDispatcher, dismiss, ) every { activityContext.startActivity(capture(shareIntent)) } just Runs @@ -133,8 +136,17 @@ class ShareControllerTest { // need to use an Activity Context. val activityContext: Context = mockk() val testController = DefaultShareController( - activityContext, shareSubject, shareData, mockk(), - snackbar, mockk(), recentAppStorage, testCoroutineScope, testDispatcher, dismiss, + context = activityContext, + shareSubject = shareSubject, + shareData = shareData, + sendTabUseCases = mockk(), + saveToPdfUseCase = mockk(), + snackbar = snackbar, + navController = mockk(), + recentAppsStorage = recentAppStorage, + viewLifecycleScope = testCoroutineScope, + dispatcher = testDispatcher, + dismiss = dismiss, ) every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs every { activityContext.startActivity(capture(shareIntent)) } throws SecurityException() @@ -161,8 +173,17 @@ class ShareControllerTest { // need to use an Activity Context. val activityContext: Context = mockk() val testController = DefaultShareController( - activityContext, shareSubject, shareData, mockk(), - snackbar, mockk(), recentAppStorage, testCoroutineScope, testDispatcher, dismiss, + context = activityContext, + shareSubject = shareSubject, + shareData = shareData, + sendTabUseCases = mockk(), + saveToPdfUseCase = mockk(), + snackbar = snackbar, + navController = mockk(), + recentAppsStorage = recentAppStorage, + viewLifecycleScope = testCoroutineScope, + dispatcher = testDispatcher, + dismiss = dismiss, ) every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs every { activityContext.startActivity(capture(shareIntent)) } throws ActivityNotFoundException() @@ -178,12 +199,47 @@ class ShareControllerTest { } } + @Test + fun `WHEN handleSaveToPDF THEN send telemetry, close the dialog and save the page to pdf`() { + val testController = DefaultShareController( + context = mockk(), + shareSubject = shareSubject, + shareData = shareData, + sendTabUseCases = mockk(), + saveToPdfUseCase = saveToPdfUseCase, + snackbar = snackbar, + navController = mockk(), + recentAppsStorage = recentAppStorage, + viewLifecycleScope = testCoroutineScope, + dispatcher = testDispatcher, + dismiss = dismiss, + ) + + testController.handleSaveToPDF("tabID") + + verify { + saveToPdfUseCase.invoke("tabID") + dismiss(ShareController.Result.DISMISSED) + } + + assertNotNull(Events.saveToPdfTapped.testGetValue()) + } + @Test fun `getShareSubject should return the shareSubject when shareSubject is not null`() { val activityContext: Context = mockk() val testController = DefaultShareController( - activityContext, shareSubject, shareData, mockk(), - mockk(), mockk(), recentAppStorage, testCoroutineScope, testDispatcher, dismiss, + context = activityContext, + shareSubject = shareSubject, + shareData = shareData, + sendTabUseCases = mockk(), + saveToPdfUseCase = mockk(), + snackbar = mockk(), + navController = mockk(), + recentAppsStorage = recentAppStorage, + viewLifecycleScope = testCoroutineScope, + dispatcher = testDispatcher, + dismiss = dismiss, ) assertEquals(shareSubject, testController.getShareSubject()) @@ -193,8 +249,17 @@ class ShareControllerTest { fun `getShareSubject should return a combination of non-null titles when shareSubject is null`() { val activityContext: Context = mockk() val testController = DefaultShareController( - activityContext, null, shareData, mockk(), - mockk(), mockk(), recentAppStorage, testCoroutineScope, testDispatcher, dismiss, + context = activityContext, + shareSubject = null, + shareData = shareData, + sendTabUseCases = mockk(), + saveToPdfUseCase = mockk(), + snackbar = mockk(), + navController = mockk(), + recentAppsStorage = recentAppStorage, + viewLifecycleScope = testCoroutineScope, + dispatcher = testDispatcher, + dismiss = dismiss, ) assertEquals("title0, title1", testController.getShareSubject()) @@ -208,8 +273,17 @@ class ShareControllerTest { ShareData(url = "url1", title = "title1"), ) val testController = DefaultShareController( - activityContext, null, partialTitlesShareData, mockk(), - mockk(), mockk(), recentAppStorage, testCoroutineScope, testDispatcher, dismiss, + context = activityContext, + shareSubject = null, + shareData = partialTitlesShareData, + sendTabUseCases = mockk(), + saveToPdfUseCase = mockk(), + snackbar = mockk(), + navController = mockk(), + recentAppsStorage = recentAppStorage, + viewLifecycleScope = testCoroutineScope, + dispatcher = testDispatcher, + dismiss = dismiss, ) assertEquals("title1", testController.getShareSubject()) @@ -223,8 +297,17 @@ class ShareControllerTest { ShareData(url = "url1", title = null), ) val testController = DefaultShareController( - activityContext, null, noTitleShareData, mockk(), - mockk(), mockk(), recentAppStorage, testCoroutineScope, testDispatcher, dismiss, + context = activityContext, + shareSubject = null, + shareData = noTitleShareData, + sendTabUseCases = mockk(), + saveToPdfUseCase = mockk(), + snackbar = mockk(), + navController = mockk(), + recentAppsStorage = recentAppStorage, + viewLifecycleScope = testCoroutineScope, + dispatcher = testDispatcher, + dismiss = dismiss, ) assertEquals("", testController.getShareSubject()) @@ -238,8 +321,17 @@ class ShareControllerTest { ShareData(url = "url1", title = ""), ) val testController = DefaultShareController( - activityContext, null, noTitleShareData, mockk(), - mockk(), mockk(), recentAppStorage, testCoroutineScope, testDispatcher, dismiss, + context = activityContext, + shareSubject = null, + shareData = noTitleShareData, + sendTabUseCases = mockk(), + saveToPdfUseCase = mockk(), + snackbar = mockk(), + navController = mockk(), + recentAppsStorage = recentAppStorage, + viewLifecycleScope = testCoroutineScope, + dispatcher = testDispatcher, + dismiss = dismiss, ) assertEquals("", testController.getShareSubject()) @@ -384,16 +476,17 @@ class ShareControllerTest { @Test fun `getSuccessMessage should return different strings depending on the number of shared tabs`() { val controllerWithOneSharedTab = DefaultShareController( - context, - shareSubject, - listOf(ShareData(url = "url0", title = "title0")), - mockk(), - mockk(), - mockk(), - mockk(), - mockk(), - mockk(), - mockk(), + context = context, + shareSubject = shareSubject, + shareData = listOf(ShareData(url = "url0", title = "title0")), + sendTabUseCases = mockk(), + saveToPdfUseCase = mockk(), + snackbar = mockk(), + navController = mockk(), + recentAppsStorage = mockk(), + viewLifecycleScope = mockk(), + dispatcher = mockk(), + dismiss = mockk(), ) val controllerWithMoreSharedTabs = controller val expectedTabSharedMessage = context.getString(R.string.sync_sent_tab_snackbar) @@ -420,8 +513,17 @@ class ShareControllerTest { ShareData(url = "url1"), ) val controller = DefaultShareController( - context, shareSubject, shareData, sendTabUseCases, snackbar, navController, - recentAppStorage, testCoroutineScope, testDispatcher, dismiss, + context = context, + shareSubject = shareSubject, + shareData = shareData, + sendTabUseCases = sendTabUseCases, + saveToPdfUseCase = mockk(), + snackbar = snackbar, + navController = navController, + recentAppsStorage = recentAppStorage, + viewLifecycleScope = testCoroutineScope, + dispatcher = testDispatcher, + dismiss = dismiss, ) val expectedShareText = "${shareData[0].url}\n\nurl0\n\n${shareData[2].url}" @@ -436,8 +538,17 @@ class ShareControllerTest { @Test fun `getShareSubject will return a concatenation of tab titles if 'shareSubject' is null`() { val controller = DefaultShareController( - context, null, shareData, sendTabUseCases, snackbar, navController, - recentAppStorage, testCoroutineScope, testDispatcher, dismiss, + context = context, + shareSubject = null, + shareData = shareData, + sendTabUseCases = sendTabUseCases, + saveToPdfUseCase = mockk(), + snackbar = snackbar, + navController = navController, + recentAppsStorage = recentAppStorage, + viewLifecycleScope = testCoroutineScope, + dispatcher = testDispatcher, + dismiss = dismiss, ) assertEquals("title0, title1", controller.getShareSubject()) diff --git a/app/src/test/java/org/mozilla/fenix/share/ShareInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/share/ShareInteractorTest.kt index 3afac05d6..c9d94ee2a 100644 --- a/app/src/test/java/org/mozilla/fenix/share/ShareInteractorTest.kt +++ b/app/src/test/java/org/mozilla/fenix/share/ShareInteractorTest.kt @@ -68,4 +68,11 @@ class ShareInteractorTest { verify { controller.handleShareToApp(app) } } + + @Test + fun `WHEN onSaveToPDF is call THEN call handleSaveToPDF`() { + interactor.onSaveToPDF("tabID") + + verify { controller.handleSaveToPDF("tabID") } + } }