1
0
Fork 0

For #6558 - cleanup + added unit tests

master
Mihai Branescu 2020-04-22 11:46:40 +03:00 committed by Jeff Boek
parent f03d65b13d
commit c4d76dce5a
16 changed files with 393 additions and 76 deletions

View File

@ -2007,11 +2007,12 @@ browser.search:
description: > description: >
Records counts of SERP pages with adverts displayed. The key format is <provider-name>. Records counts of SERP pages with adverts displayed. The key format is <provider-name>.
send_in_pings: send_in_pings:
- baseline
- metrics - metrics
bugs: bugs:
- https://github.com/mozilla-mobile/fenix/issues/6558 - https://github.com/mozilla-mobile/fenix/issues/6558
data_reviews: data_reviews:
- https://github.com/mozilla-mobile/fenix/issues/6558 - https://github.com/mozilla-mobile/fenix/pull/10112
notification_emails: notification_emails:
- fenix-core@mozilla.com - fenix-core@mozilla.com
expires: "2020-09-01" expires: "2020-09-01"
@ -2020,11 +2021,12 @@ browser.search:
description: > description: >
Records clicks of adverts on SERP pages. The key format is <provider-name>. Records clicks of adverts on SERP pages. The key format is <provider-name>.
send_in_pings: send_in_pings:
- baseline
- metrics - metrics
bugs: bugs:
- https://github.com/mozilla-mobile/fenix/issues/6558 - https://github.com/mozilla-mobile/fenix/issues/6558
data_reviews: data_reviews:
- https://github.com/mozilla-mobile/fenix/issues/6558 - https://github.com/mozilla-mobile/fenix/pull/10112
notification_emails: notification_emails:
- fenix-core@mozilla.com - fenix-core@mozilla.com
expires: "2020-09-01" expires: "2020-09-01"

View File

@ -1,4 +1,10 @@
function collect_urls(urls) { /* 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/. */
const ADLINK_CHECK_TIMEOUT_MS = 1000;
function collectLinks(urls) {
let anchors = document.getElementsByTagName("a"); let anchors = document.getElementsByTagName("a");
for (let anchor of anchors) { for (let anchor of anchors) {
if (!anchor.href) { if (!anchor.href) {
@ -7,11 +13,30 @@ function collect_urls(urls) {
urls.push(anchor.href); urls.push(anchor.href);
} }
} }
let urls = [];
collect_urls(urls)
let message = { function sendLinks() {
'url': document.location.href, let urls = [];
'urls': urls collectLinks(urls);
let message = {
'url': document.location.href,
'urls': urls
};
browser.runtime.sendNativeMessage("MozacBrowserAds", message);
} }
browser.runtime.sendNativeMessage("MozacBrowserAds", message);
var timeout;
window.onload = function() {
timeout = setTimeout(sendLinks, ADLINK_CHECK_TIMEOUT_MS);
};
window.onpageshow = function(event) {
if (event.persisted) {
timeout = setTimeout(sendLinks, ADLINK_CHECK_TIMEOUT_MS);
}
};
window.onunload = function() {
clearTimeout(timeout);
};

View File

@ -1,10 +0,0 @@
package org.mozilla.fenix.ads
data class SearchProviderCookie(
val extraCodeParam: String,
val extraCodePrefixes: List<String>,
val host: String,
val name: String,
val codeParam: String,
val codePrefixes: List<String>
)

View File

@ -1,10 +1,14 @@
/* 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.browser package org.mozilla.fenix.browser
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
import org.mozilla.fenix.ads.AdsTelemetry
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry
class TelemetrySessionObserver( class TelemetrySessionObserver(
private val metrics: MetricController, private val metrics: MetricController,

View File

@ -9,7 +9,7 @@ import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager import mozilla.components.browser.session.SessionManager
import org.mozilla.fenix.ads.AdsTelemetry import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry
import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.metrics import org.mozilla.fenix.ext.metrics

View File

@ -42,7 +42,7 @@ import org.mozilla.fenix.AppRequestInterceptor
import org.mozilla.fenix.Config import org.mozilla.fenix.Config
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ads.AdsTelemetry import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.media.MediaService import org.mozilla.fenix.media.MediaService

View File

@ -1,6 +1,10 @@
/* 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 package org.mozilla.fenix.ext
import org.mozilla.fenix.ads.SearchProviderModel import org.mozilla.fenix.search.telemetry.SearchProviderModel
fun SearchProviderModel.containsAds(urlList: List<String>): Boolean { fun SearchProviderModel.containsAds(urlList: List<String>): Boolean {
return urlList.containsAds(this.extraAdServersRegexps) return urlList.containsAds(this.extraAdServersRegexps)

View File

@ -1,12 +0,0 @@
package org.mozilla.fenix.ext
import org.json.JSONArray
@Suppress("UNCHECKED_CAST")
fun <T> JSONArray.toList(): List<T> {
val result = ArrayList<T>()
for (i in 0 until length()) {
result.add(get(i) as T)
}
return result
}

View File

@ -0,0 +1,14 @@
/* 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.search.telemetry
data class SearchProviderCookie(
val extraCodeParam: String,
val extraCodePrefixes: List<String>,
val host: String,
val name: String,
val codeParam: String,
val codePrefixes: List<String>
)

View File

@ -1,4 +1,8 @@
package org.mozilla.fenix.ads /* 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.search.telemetry
data class SearchProviderModel( data class SearchProviderModel(
val name: String, val name: String,

View File

@ -1,5 +1,10 @@
package org.mozilla.fenix.ads /* 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.search.telemetry.ads
import androidx.annotation.VisibleForTesting
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
@ -11,16 +16,19 @@ import mozilla.components.concept.engine.webextension.MessageHandler
import mozilla.components.concept.engine.webextension.WebExtension import mozilla.components.concept.engine.webextension.WebExtension
import mozilla.components.lib.state.ext.flowScoped import mozilla.components.lib.state.ext.flowScoped
import mozilla.components.support.base.log.logger.Logger import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.ktx.android.org.json.toList
import mozilla.components.support.ktx.kotlinx.coroutines.flow.filterChanged import mozilla.components.support.ktx.kotlinx.coroutines.flow.filterChanged
import org.json.JSONObject import org.json.JSONObject
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.ext.containsAds import org.mozilla.fenix.ext.containsAds
import org.mozilla.fenix.ext.toList import org.mozilla.fenix.search.telemetry.SearchProviderCookie
import org.mozilla.fenix.search.telemetry.SearchProviderModel
class AdsTelemetry(private val metrics: MetricController) { class AdsTelemetry(private val metrics: MetricController) {
private val providerList = listOf( @VisibleForTesting
internal val providerList = listOf(
SearchProviderModel( SearchProviderModel(
name = "google", name = "google",
regexp = "^https:\\/\\/www\\.google\\.(?:.+)\\/search", regexp = "^https:\\/\\/www\\.google\\.(?:.+)\\/search",
@ -38,7 +46,8 @@ class AdsTelemetry(private val metrics: MetricController) {
codePrefixes = listOf("ff"), codePrefixes = listOf("ff"),
followOnParams = listOf("oq", "ved", "ei"), followOnParams = listOf("oq", "ved", "ei"),
extraAdServersRegexps = listOf( extraAdServersRegexps = listOf(
"^https:\\/\\/duckduckgo.com\\/y\\.js" "^https:\\/\\/duckduckgo.com\\/y\\.js",
"^https:\\/\\/www\\.amazon\\.(?:[a-z.]{2,24}).*(?:tag=duckduckgo-)"
) )
), ),
SearchProviderModel( SearchProviderModel(
@ -48,7 +57,7 @@ class AdsTelemetry(private val metrics: MetricController) {
), ),
SearchProviderModel( SearchProviderModel(
name = "baidu", name = "baidu",
regexp = "^https:\\/\\/www\\.baidu\\.com\\/(?:s|baidu)", regexp = "^https:\\/\\/www\\.baidu\\.com\\/from=844b\\/(?:s|baidu)",
queryParam = "wd", queryParam = "wd",
codeParam = "tn", codeParam = "tn",
codePrefixes = listOf("34046034_", "monline_"), codePrefixes = listOf("34046034_", "monline_"),
@ -108,7 +117,8 @@ class AdsTelemetry(private val metrics: MetricController) {
} }
} }
private fun getProviderForUrl(url: String): SearchProviderModel? { @VisibleForTesting
internal fun getProviderForUrl(url: String): SearchProviderModel? {
for (provider in providerList) { for (provider in providerList) {
if (Regex(provider.regexp).containsMatchIn(url)) { if (Regex(provider.regexp).containsMatchIn(url)) {
return provider return provider
@ -138,7 +148,8 @@ class AdsTelemetry(private val metrics: MetricController) {
} }
} }
private inner class AdsTelemetryContentMessageHandler : MessageHandler { @VisibleForTesting
internal inner class AdsTelemetryContentMessageHandler : MessageHandler {
override fun onMessage(message: Any, source: EngineSession?): Any? { override fun onMessage(message: Any, source: EngineSession?): Any? {
if (message is JSONObject) { if (message is JSONObject) {
@ -164,10 +175,14 @@ class AdsTelemetry(private val metrics: MetricController) {
} }
companion object { companion object {
private const val ADS_EXTENSION_ID = "mozacBrowserAds" @VisibleForTesting
private const val ADS_EXTENSION_RESOURCE_URL = "resource://android/assets/extensions/ads/" internal const val ADS_EXTENSION_ID = "mozacBrowserAds"
@VisibleForTesting
internal const val ADS_EXTENSION_RESOURCE_URL = "resource://android/assets/extensions/ads/"
@VisibleForTesting
internal const val ADS_MESSAGE_SESSION_URL_KEY = "url"
@VisibleForTesting
internal const val ADS_MESSAGE_DOCUMENT_URLS_KEY = "urls"
private const val ADS_MESSAGE_ID = "MozacBrowserAds" private const val ADS_MESSAGE_ID = "MozacBrowserAds"
private const val ADS_MESSAGE_SESSION_URL_KEY = "url"
private const val ADS_MESSAGE_DOCUMENT_URLS_KEY = "urls"
} }
} }

View File

@ -0,0 +1,120 @@
/* 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.browser
import androidx.lifecycle.LifecycleOwner
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry
class TelemetrySessionObserverTest {
private val owner: LifecycleOwner = mockk(relaxed = true)
private val sessionManager: SessionManager = mockk(relaxed = true)
private val metrics: MetricController = mockk(relaxed = true)
private val ads: AdsTelemetry = mockk(relaxed = true)
private lateinit var singleSessionObserver: TelemetrySessionObserver
@Before
fun setup() {
singleSessionObserver =
UriOpenedObserver(owner, sessionManager, metrics, ads).singleSessionObserver
}
@Test
fun `tracks that a url was loaded`() {
val session: Session = mockk(relaxed = true)
every { session.url } returns "https://mozilla.com"
singleSessionObserver.onLoadingStateChanged(session, loading = false)
verify(exactly = 0) { metrics.track(Event.UriOpened) }
singleSessionObserver.onLoadingStateChanged(session, loading = true)
singleSessionObserver.onLoadingStateChanged(session, loading = false)
verify { metrics.track(Event.UriOpened) }
}
@Test
fun `add originSessionUrl on first link of redirect chain and start chain`() {
val session: Session = mockk(relaxed = true)
val sessionUrl = "https://www.google.com/search"
val url = "www.aaa.com"
every { session.url } returns sessionUrl
singleSessionObserver.onLoadRequest(
session,
url,
triggeredByRedirect = false,
triggeredByWebContent = false
)
Assert.assertEquals(sessionUrl, singleSessionObserver.originSessionUrl)
Assert.assertEquals(url, singleSessionObserver.redirectChain[0])
}
@Test
fun `add to redirect chain on subsequent onLoadRequests`() {
val session: Session = mockk(relaxed = true)
val url = "https://www.google.com/search"
val newUrl = "www.aaa.com"
every { session.url } returns url
singleSessionObserver.originSessionUrl = url
singleSessionObserver.redirectChain.add(url)
singleSessionObserver.onLoadRequest(
session,
newUrl,
triggeredByRedirect = false,
triggeredByWebContent = false
)
Assert.assertEquals(url, singleSessionObserver.originSessionUrl)
Assert.assertEquals(url, singleSessionObserver.redirectChain[0])
Assert.assertEquals(newUrl, singleSessionObserver.redirectChain[1])
}
@Test
fun `do nothing onLoadRequest when it's the first url of the session`() {
val session: Session = mockk(relaxed = true)
val url = "https://www.google.com/search"
every { session.url } returns url
singleSessionObserver.onLoadRequest(
session,
url,
triggeredByRedirect = false,
triggeredByWebContent = false
)
Assert.assertNull(singleSessionObserver.originSessionUrl)
Assert.assertEquals(0, singleSessionObserver.redirectChain.size)
}
@Test
fun `check if metric for ad clicked should be sent`() {
val session: Session = mockk(relaxed = true)
val sessionUrl = "doesn't matter"
val originSessionUrl = "https://www.google.com/search"
val url = "www.aaa.com"
every { session.url } returns sessionUrl
val redirectChain = mutableListOf(url)
singleSessionObserver.redirectChain = redirectChain
singleSessionObserver.originSessionUrl = originSessionUrl
singleSessionObserver.onUrlChanged(session, url)
verify {
ads.trackAdClickedMetric(
originSessionUrl,
redirectChain
)
}
Assert.assertNull(singleSessionObserver.originSessionUrl)
Assert.assertEquals(0, singleSessionObserver.redirectChain.size)
}
}

View File

@ -4,42 +4,36 @@
package org.mozilla.fenix.browser package org.mozilla.fenix.browser
import android.content.Context
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import io.mockk.verify import io.mockk.verify
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager import mozilla.components.browser.session.SessionManager
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry
import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.components.metrics.MetricController
class UriOpenedObserverTest { class UriOpenedObserverTest {
private lateinit var context: Context private val owner: LifecycleOwner = mockk(relaxed = true)
private lateinit var owner: LifecycleOwner private val sessionManager: SessionManager = mockk(relaxed = true)
private lateinit var sessionManager: SessionManager private val metrics: MetricController = mockk()
private lateinit var metrics: MetricController private val ads: AdsTelemetry = mockk()
private lateinit var observer: UriOpenedObserver
@Before @Before
fun setup() { fun setup() {
context = mockk(relaxed = true) observer = UriOpenedObserver(owner, sessionManager, metrics, ads)
owner = mockk(relaxed = true)
sessionManager = mockk(relaxed = true)
metrics = mockk(relaxed = true)
} }
@Test @Test
fun `registers self as observer`() { fun `registers self as observer`() {
val observer = UriOpenedObserver(context, owner, sessionManager, metrics)
verify { sessionManager.register(observer, owner) } verify { sessionManager.register(observer, owner) }
} }
@Test @Test
fun `registers single session observer`() { fun `registers single session observer`() {
val observer = UriOpenedObserver(context, owner, sessionManager, metrics)
val session: Session = mockk(relaxed = true) val session: Session = mockk(relaxed = true)
observer.onSessionAdded(session) observer.onSessionAdded(session)
@ -48,18 +42,4 @@ class UriOpenedObserverTest {
observer.onSessionRemoved(session) observer.onSessionRemoved(session)
verify { session.unregister(observer.singleSessionObserver) } verify { session.unregister(observer.singleSessionObserver) }
} }
@Test
fun `tracks that a url was loaded`() {
val observer = UriOpenedObserver(context, owner, sessionManager, metrics).singleSessionObserver
val session: Session = mockk(relaxed = true)
every { session.url } returns "https://mozilla.com"
observer.onLoadingStateChanged(session, loading = false)
verify(exactly = 0) { metrics.track(Event.UriOpened) }
observer.onLoadingStateChanged(session, loading = true)
observer.onLoadingStateChanged(session, loading = false)
verify { metrics.track(Event.UriOpened) }
}
} }

View File

@ -0,0 +1,41 @@
/* 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 org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.mozilla.fenix.search.telemetry.SearchProviderModel
class AdsTest {
private val testSearchProvider =
SearchProviderModel(
name = "test",
regexp = "test",
queryParam = "test",
codeParam = "test",
codePrefixes = listOf(),
followOnParams = listOf(),
extraAdServersRegexps = listOf(
"^https:\\/\\/www\\.bing\\.com\\/acli?c?k",
"^https:\\/\\/www\\.bing\\.com\\/fd\\/ls\\/GLinkPingPost\\.aspx.*acli?c?k"
)
)
@Test
fun `test search provider contains ads`() {
val ad = "https://www.bing.com/aclick"
val nonAd = "https://www.bing.com/notanad"
assertTrue(testSearchProvider.containsAds(listOf(ad, nonAd)))
}
@Test
fun `test search provider does not contain ads`() {
val nonAd1 = "https://www.yahoo.com/notanad"
val nonAd2 = "https://www.google.com/"
assertFalse(testSearchProvider.containsAds(listOf(nonAd1, nonAd2)))
}
}

View File

@ -0,0 +1,128 @@
/* 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.search.telemetry.ads
import io.mockk.mockk
import io.mockk.slot
import io.mockk.spyk
import io.mockk.verify
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.Engine
import org.json.JSONArray
import org.json.JSONObject
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry.Companion.ADS_EXTENSION_ID
import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry.Companion.ADS_EXTENSION_RESOURCE_URL
import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry.Companion.ADS_MESSAGE_DOCUMENT_URLS_KEY
import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry.Companion.ADS_MESSAGE_SESSION_URL_KEY
@RunWith(FenixRobolectricTestRunner::class)
class AdsTelemetryTest {
private val metrics: MetricController = mockk(relaxed = true)
private lateinit var ads: AdsTelemetry
private lateinit var adsMessageHandler: AdsTelemetry.AdsTelemetryContentMessageHandler
@Before
fun setUp() {
ads = spyk(AdsTelemetry(metrics))
adsMessageHandler = ads.AdsTelemetryContentMessageHandler()
}
@Test
fun `don't track with null session url`() {
ads.trackAdClickedMetric(null, listOf())
verify(exactly = 0) { ads.getProviderForUrl(any()) }
}
@Test
fun `don't track when no ads are in the redirect path`() {
val sessionUrl = "https://www.google.com/search?q=aaa"
ads.trackAdClickedMetric(sessionUrl, listOf("https://www.aaa.com"))
verify(exactly = 0) { metrics.track(any()) }
}
@Test
fun `track when ads are in the redirect path`() {
val metricEvent = slot<Event.SearchAdClicked>()
val sessionUrl = "https://www.google.com/search?q=aaa"
ads.trackAdClickedMetric(
sessionUrl,
listOf("https://www.google.com/aclk", "https://www.aaa.com")
)
verify { metrics.track(capture(metricEvent)) }
assertEquals(ads.providerList[0].name, metricEvent.captured.label)
}
@Test
fun install() {
val engine = mockk<Engine>(relaxed = true)
val store = mockk<BrowserStore>(relaxed = true)
ads.install(engine, store)
verify {
engine.installWebExtension(
id = ADS_EXTENSION_ID,
url = ADS_EXTENSION_RESOURCE_URL,
allowContentMessaging = true,
onSuccess = any(),
onError = any()
)
}
}
@Test
fun `message handler processes the document urls and reports an ad`() {
val metricEvent = slot<Event.SearchWithAds>()
val first = "https://www.google.com/aclk"
val second = "https://www.google.com/aaa"
val array = JSONArray()
array.put(first)
array.put(second)
val message = JSONObject()
message.put(ADS_MESSAGE_DOCUMENT_URLS_KEY, array)
message.put(ADS_MESSAGE_SESSION_URL_KEY, "https://www.google.com/search?q=aaa")
assertEquals("", adsMessageHandler.onMessage(message, mockk()))
verify { metrics.track(capture(metricEvent)) }
assertEquals(ads.providerList[0].name, metricEvent.captured.label)
}
@Test
fun `message handler processes the document urls and doesn't find ads`() {
val first = "https://www.google.com/aaaaaa"
val second = "https://www.google.com/aaa"
val array = JSONArray()
array.put(first)
array.put(second)
val message = JSONObject()
message.put(ADS_MESSAGE_DOCUMENT_URLS_KEY, array)
message.put(ADS_MESSAGE_SESSION_URL_KEY, "https://www.google.com/search?q=aaa")
assertEquals("", adsMessageHandler.onMessage(message, mockk()))
verify(exactly = 0) { metrics.track(any()) }
}
@Test(expected = IllegalStateException::class)
fun `message handler finds no json object`() {
val message = "message"
adsMessageHandler.onMessage(message, mockk())
}
}

File diff suppressed because one or more lines are too long