@@ -43,6 +43,7 @@ import androidx.lifecycle.Observer
4343import androidx.room.Room
4444import androidx.test.filters.SdkSuppress
4545import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
46+ import app.cash.turbine.test
4647import com.duckduckgo.adclick.api.AdClickManager
4748import com.duckduckgo.app.ValueCaptorObserver
4849import com.duckduckgo.app.accessibility.data.AccessibilitySettingsDataStore
@@ -233,6 +234,7 @@ import com.duckduckgo.common.utils.baseHost
233234import com.duckduckgo.common.utils.device.DeviceInfo
234235import com.duckduckgo.common.utils.plugins.PluginPoint
235236import com.duckduckgo.common.utils.plugins.headers.CustomHeadersProvider
237+ import com.duckduckgo.contentscopescripts.api.ContentScopeScriptsSubscriptionEventPlugin
236238import com.duckduckgo.downloads.api.DownloadStateListener
237239import com.duckduckgo.downloads.api.FileDownloader
238240import com.duckduckgo.downloads.api.FileDownloader.PendingFileDownload
@@ -259,12 +261,8 @@ import com.duckduckgo.feature.toggles.api.Toggle
259261import com.duckduckgo.feature.toggles.api.Toggle.State
260262import com.duckduckgo.history.api.HistoryEntry.VisitedPage
261263import com.duckduckgo.history.api.NavigationHistory
262- import com.duckduckgo.js.messaging.api.AddDocumentStartJavaScriptPlugin
263264import com.duckduckgo.js.messaging.api.JsCallbackData
264- import com.duckduckgo.js.messaging.api.PostMessageWrapperPlugin
265265import com.duckduckgo.js.messaging.api.SubscriptionEventData
266- import com.duckduckgo.js.messaging.api.WebMessagingPlugin
267- import com.duckduckgo.js.messaging.api.WebViewCompatMessageCallback
268266import com.duckduckgo.malicioussiteprotection.api.MaliciousSiteProtection.Feed
269267import com.duckduckgo.malicioussiteprotection.api.MaliciousSiteProtection.Feed.MALWARE
270268import com.duckduckgo.newtabpage.impl.pixels.NewTabPixels
@@ -290,6 +288,7 @@ import com.duckduckgo.savedsites.api.models.SavedSite.Favorite
290288import com.duckduckgo.savedsites.impl.SavedSitesPixelName
291289import com.duckduckgo.serp.logos.api.SerpEasterEggLogosToggles
292290import com.duckduckgo.serp.logos.api.SerpLogo
291+ import com.duckduckgo.settings.api.SettingsPageFeature
293292import com.duckduckgo.site.permissions.api.SitePermissionsManager
294293import com.duckduckgo.site.permissions.api.SitePermissionsManager.LocationPermissionRequest
295294import com.duckduckgo.site.permissions.api.SitePermissionsManager.SitePermissionQueryResponse
@@ -619,6 +618,9 @@ class BrowserTabViewModelTest {
619618
620619 private val mockDeviceAppLookup: DeviceAppLookup = mock()
621620
621+ private lateinit var fakeContentScopeScriptsSubscriptionEventPluginPoint: FakeContentScopeScriptsSubscriptionEventPluginPoint
622+ private var fakeSettingsPageFeature = FakeFeatureToggleFactory .create(SettingsPageFeature ::class .java)
623+
622624 @Before
623625 fun before () =
624626 runTest {
@@ -849,6 +851,8 @@ class BrowserTabViewModelTest {
849851 addressBarTrackersAnimationFeatureToggle = mockAddressBarTrackersAnimationFeatureToggle,
850852 autoconsentPixelManager = mockAutoconsentPixelManager,
851853 omnibarFeatureRepository = mockOmnibarFeatureRepository,
854+ contentScopeScriptsSubscriptionEventPluginPoint = fakeContentScopeScriptsSubscriptionEventPluginPoint,
855+ settingsPageFeature = fakeSettingsPageFeature,
852856 )
853857
854858 testee.loadData(" abc" , null , false , false )
@@ -7944,6 +7948,104 @@ class BrowserTabViewModelTest {
79447948 override fun getPlugins (): Collection <PostMessageWrapperPlugin > = listOf (plugin)
79457949 }
79467950
7951+ class FakeContentScopeScriptsSubscriptionEventPlugin (
7952+ private val eventData : SubscriptionEventData ,
7953+ ) : ContentScopeScriptsSubscriptionEventPlugin {
7954+ override fun getSubscriptionEventData (): SubscriptionEventData = eventData
7955+ }
7956+
7957+ class FakeContentScopeScriptsSubscriptionEventPluginPoint () : PluginPoint<ContentScopeScriptsSubscriptionEventPlugin> {
7958+
7959+ private val plugins: MutableList <ContentScopeScriptsSubscriptionEventPlugin > = mutableListOf ()
7960+
7961+ fun addPlugins (plugins : List <ContentScopeScriptsSubscriptionEventPlugin >) {
7962+ this .plugins.addAll(plugins)
7963+ }
7964+
7965+ override fun getPlugins (): Collection <ContentScopeScriptsSubscriptionEventPlugin > = plugins
7966+ }
7967+
7968+ @Test
7969+ fun whenOnViewResumedWithNoPluginsThenNoSubscriptionEventsSent () = runTest {
7970+ fakeSettingsPageFeature.serpSettingsSync().setRawStoredState(State (enable = true ))
7971+
7972+ testee.onViewResumed()
7973+
7974+ testee.subscriptionEventDataFlow.test {
7975+ expectNoEvents()
7976+ cancelAndIgnoreRemainingEvents()
7977+ }
7978+ }
7979+
7980+ @Test
7981+ fun whenOnViewResumedWithPluginsThenSubscriptionEventsSent () = runTest {
7982+ fakeSettingsPageFeature.serpSettingsSync().setRawStoredState(State (enable = true ))
7983+ val events = mutableListOf<SubscriptionEventData >().apply {
7984+ add(
7985+ SubscriptionEventData (
7986+ featureName = " event1" ,
7987+ subscriptionName = " subscription1" ,
7988+ params = JSONObject ().put(" param1" , " value1" ),
7989+ ),
7990+ )
7991+ add(
7992+ SubscriptionEventData (
7993+ featureName = " event2" ,
7994+ subscriptionName = " subscription2" ,
7995+ params = JSONObject ().put(" param2" , " value2" ),
7996+ ),
7997+ )
7998+ }
7999+
8000+ fakeContentScopeScriptsSubscriptionEventPluginPoint.addPlugins(
8001+ events.map { FakeContentScopeScriptsSubscriptionEventPlugin (it) },
8002+ )
8003+
8004+ testee.onViewResumed()
8005+
8006+ testee.subscriptionEventDataFlow.test {
8007+ for (expectedEvent in events) {
8008+ val emittedEvent = awaitItem()
8009+ assertEquals(expectedEvent.featureName, emittedEvent.featureName)
8010+ assertEquals(expectedEvent.subscriptionName, emittedEvent.subscriptionName)
8011+ assertEquals(expectedEvent.params.toString(), emittedEvent.params.toString())
8012+ }
8013+ cancelAndIgnoreRemainingEvents()
8014+ }
8015+ }
8016+
8017+ @Test
8018+ fun whenOnViewResumedWithPluginsAndSerpSettingsFeatureFlagOffThenNoEventsSent () = runTest {
8019+ fakeSettingsPageFeature.serpSettingsSync().setRawStoredState(State (enable = false ))
8020+ val events = mutableListOf<SubscriptionEventData >().apply {
8021+ add(
8022+ SubscriptionEventData (
8023+ featureName = " event1" ,
8024+ subscriptionName = " subscription1" ,
8025+ params = JSONObject ().put(" param1" , " value1" ),
8026+ ),
8027+ )
8028+ add(
8029+ SubscriptionEventData (
8030+ featureName = " event2" ,
8031+ subscriptionName = " subscription2" ,
8032+ params = JSONObject ().put(" param2" , " value2" ),
8033+ ),
8034+ )
8035+ }
8036+
8037+ fakeContentScopeScriptsSubscriptionEventPluginPoint.addPlugins(
8038+ events.map { FakeContentScopeScriptsSubscriptionEventPlugin (it) },
8039+ )
8040+
8041+ testee.onViewResumed()
8042+
8043+ testee.subscriptionEventDataFlow.test {
8044+ expectNoEvents()
8045+ cancelAndIgnoreRemainingEvents()
8046+ }
8047+ }
8048+
79478049 @Test
79488050 fun whenVpnMenuClickedWithNotSubscribedStateThenPixelFiredWithPillStatus () {
79498051 testee.browserViewState.value = browserViewState().copy(
0 commit comments