@@ -18,30 +18,22 @@ package com.duckduckgo.contentscopescripts.impl.messaging
18
18
19
19
import android.webkit.WebView
20
20
import androidx.test.ext.junit.runners.AndroidJUnit4
21
- import androidx.webkit.JavaScriptReplyProxy
22
- import com.duckduckgo.browser.api.webviewcompat.WebViewCompatWrapper
23
21
import com.duckduckgo.common.test.CoroutineTestRule
24
22
import com.duckduckgo.common.utils.plugins.PluginPoint
25
23
import com.duckduckgo.contentscopescripts.api.WebViewCompatContentScopeJsMessageHandlersPlugin
26
24
import com.duckduckgo.contentscopescripts.impl.WebViewCompatContentScopeScripts
27
- import com.duckduckgo.js.messaging.api.JsMessage
28
- import com.duckduckgo.js.messaging.api.ProcessResult
29
- import com.duckduckgo.js.messaging.api.ProcessResult.SendToConsumer
30
25
import com.duckduckgo.js.messaging.api.SubscriptionEventData
26
+ import com.duckduckgo.js.messaging.api.WebMessaging
27
+ import com.duckduckgo.js.messaging.api.WebMessagingDelegate
31
28
import com.duckduckgo.js.messaging.api.WebViewCompatMessageCallback
32
- import com.duckduckgo.js.messaging.api.WebViewCompatMessageHandler
33
- import junit.framework.TestCase.assertEquals
34
29
import kotlinx.coroutines.test.runTest
35
30
import org.json.JSONObject
36
31
import org.junit.Before
37
32
import org.junit.Rule
38
33
import org.junit.Test
39
34
import org.junit.runner.RunWith
40
- import org.mockito.ArgumentMatchers.anyString
41
35
import org.mockito.kotlin.any
42
- import org.mockito.kotlin.eq
43
36
import org.mockito.kotlin.mock
44
- import org.mockito.kotlin.never
45
37
import org.mockito.kotlin.verify
46
38
import org.mockito.kotlin.whenever
47
39
@@ -52,221 +44,54 @@ class ContentScopeScriptsWebMessagingTest {
52
44
val coroutineRule = CoroutineTestRule ()
53
45
54
46
private val webViewCompatContentScopeScripts: WebViewCompatContentScopeScripts = mock()
55
- private val handlers: PluginPoint <WebViewCompatContentScopeJsMessageHandlersPlugin > = FakePluginPoint ()
56
- private val mockReplyProxy: JavaScriptReplyProxy = mock()
57
- private val globalHandlers: PluginPoint <GlobalContentScopeJsMessageHandlersPlugin > = FakeGlobalHandlersPluginPoint ()
58
- private val mockWebViewCompatWrapper: WebViewCompatWrapper = mock()
47
+ private val handlers: PluginPoint <WebViewCompatContentScopeJsMessageHandlersPlugin > = mock()
48
+ private val globalHandlers: PluginPoint <GlobalContentScopeJsMessageHandlersPlugin > = mock()
59
49
private val mockWebView: WebView = mock()
50
+ private val mockWebMessagingDelegate: WebMessagingDelegate = mock()
51
+ private val mockWebMessaging: WebMessaging = mock()
60
52
private lateinit var testee: ContentScopeScriptsWebMessaging
61
53
62
- private class FakePluginPoint : PluginPoint <WebViewCompatContentScopeJsMessageHandlersPlugin > {
63
- override fun getPlugins (): Collection <WebViewCompatContentScopeJsMessageHandlersPlugin > {
64
- return listOf (FakePlugin ())
65
- }
66
-
67
- inner class FakePlugin : WebViewCompatContentScopeJsMessageHandlersPlugin {
68
- override fun getJsMessageHandler (): WebViewCompatMessageHandler {
69
- return object : WebViewCompatMessageHandler {
70
- override fun process (
71
- jsMessage : JsMessage ,
72
- ): ProcessResult {
73
- return SendToConsumer
74
- }
75
-
76
- override val featureName: String = " webCompat"
77
- override val methods: List <String > = listOf (" webShare" , " permissionsQuery" )
78
- }
79
- }
80
- }
81
- }
82
-
83
- private class FakeGlobalHandlersPluginPoint : PluginPoint <GlobalContentScopeJsMessageHandlersPlugin > {
84
- override fun getPlugins (): Collection <GlobalContentScopeJsMessageHandlersPlugin > {
85
- return listOf (FakeGlobalHandlerPlugin ())
86
- }
87
-
88
- inner class FakeGlobalHandlerPlugin : GlobalContentScopeJsMessageHandlersPlugin {
89
-
90
- override fun getGlobalJsMessageHandler (): GlobalJsMessageHandler {
91
- return object : GlobalJsMessageHandler {
92
-
93
- override fun process (
94
- jsMessage : JsMessage ,
95
- ): ProcessResult {
96
- return SendToConsumer
97
- }
98
-
99
- override val method: String = " addDebugFlag"
100
- }
101
- }
102
- }
103
- }
104
-
105
54
@Before
106
55
fun setUp () = runTest {
107
- whenever(webViewCompatContentScopeScripts.isEnabled()) .thenReturn(true )
56
+ whenever(mockWebMessagingDelegate.createPlugin(any())) .thenReturn(mockWebMessaging )
108
57
testee = ContentScopeScriptsWebMessaging (
109
58
handlers = handlers,
110
59
globalHandlers = globalHandlers,
111
60
webViewCompatContentScopeScripts = webViewCompatContentScopeScripts,
112
- webViewCompatWrapper = mockWebViewCompatWrapper,
113
- dispatcherProvider = coroutineRule.testDispatcherProvider,
114
- appCoroutineScope = coroutineRule.testScope,
61
+ webMessagingDelegate = mockWebMessagingDelegate,
115
62
)
116
63
}
117
64
118
65
@Test
119
- fun `when process and message can be handled then execute callback` () = runTest {
120
- givenInterfaceIsRegistered()
121
-
122
- val message = """
123
- {"context":"contentScopeScripts","featureName":"webCompat","id":"myId","method":"webShare","params":{}}
124
- """ .trimIndent()
125
-
126
- testee.process(message, callback, mockReplyProxy)
127
-
128
- assertEquals(1 , callback.counter)
129
- }
130
-
131
- @Test
132
- fun `when processing unknown message do nothing` () = runTest {
133
- givenInterfaceIsRegistered()
134
-
135
- testee.process(" " , callback, mockReplyProxy)
136
-
137
- assertEquals(0 , callback.counter)
138
- }
139
-
140
- @Test
141
- fun `when feature does not match do nothing` () = runTest {
142
- givenInterfaceIsRegistered()
143
-
144
- val message = """
145
- {"context":"contentScopeScripts","featureName":"test","id":"myId","method":"webShare","params":{}}
146
- """ .trimIndent()
147
-
148
- testee.process(message, callback, mockReplyProxy)
149
-
150
- assertEquals(0 , callback.counter)
151
- }
152
-
153
- @Test
154
- fun `when id does not exist do nothing` () = runTest {
155
- givenInterfaceIsRegistered()
156
-
157
- val message = """
158
- {"context":"contentScopeScripts","webCompat":"test","method":"webShare","params":{}}
159
- """ .trimIndent()
160
-
161
- testee.process(message, callback, mockReplyProxy)
162
-
163
- assertEquals(0 , callback.counter)
164
- }
165
-
166
- @Test
167
- fun `when processing addDebugFlag message then process message` () = runTest {
168
- givenInterfaceIsRegistered()
169
-
170
- val message = """
171
- {"context":"contentScopeScripts","featureName":"debugFeature","id":"debugId","method":"addDebugFlag","params":{}}
172
- """ .trimIndent()
173
-
174
- testee.process(message, callback, mockReplyProxy)
175
-
176
- assertEquals(1 , callback.counter)
177
- }
178
-
179
- @Test
180
- fun `when registering and adsjs is disabled then do not register` () = runTest {
181
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(false )
182
-
183
- testee.register(callback, mockWebView)
184
-
185
- verify(mockWebViewCompatWrapper, never())
186
- .addWebMessageListener(any(), any(), any(), any())
187
- }
188
-
189
- @Test
190
- fun `when registering and adsjs is enabled then register` () = runTest {
191
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(true )
192
-
66
+ fun `when register called then delegate to created plugin` () = runTest {
193
67
testee.register(callback, mockWebView)
194
68
195
- verify(mockWebViewCompatWrapper).addWebMessageListener(
196
- eq(mockWebView),
197
- eq(" contentScopeAdsjs" ),
198
- eq(setOf (" *" )),
199
- any(),
200
- )
201
- }
202
-
203
- @Test
204
- fun `when unregistering and adsjs is disabled then do not unregister` () = runTest {
205
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(false )
206
-
207
- testee.unregister(mockWebView)
208
-
209
- verify(mockWebViewCompatWrapper, never())
210
- .removeWebMessageListener(any(), any())
69
+ verify(mockWebMessaging).register(callback, mockWebView)
211
70
}
212
71
213
72
@Test
214
- fun `when unregistering and adsjs is enabled then unregister` () = runTest {
215
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(true )
216
-
73
+ fun `when unregister called then delegate to created plugin` () = runTest {
217
74
testee.unregister(mockWebView)
218
75
219
- verify(mockWebViewCompatWrapper).removeWebMessageListener (mockWebView, " contentScopeAdsjs " )
76
+ verify(mockWebMessaging).unregister (mockWebView)
220
77
}
221
78
222
79
@Test
223
- fun `when posting message and adsjs is disabled then do not post message` () = runTest {
224
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(false )
80
+ fun `when postMessage called then delegate to created plugin` () = runTest {
225
81
val eventData = SubscriptionEventData (" feature" , " subscription" , JSONObject ())
226
- givenInterfaceIsRegistered()
227
82
228
83
testee.postMessage(eventData)
229
84
230
- verify(mockReplyProxy, never()) .postMessage(anyString() )
85
+ verify(mockWebMessaging) .postMessage(eventData )
231
86
}
232
87
233
88
@Test
234
- fun `when posting message and adsjs is enabled but webView not registered then do not post message` () = runTest {
235
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(true )
236
- val eventData = SubscriptionEventData (" feature" , " subscription" , JSONObject ())
237
-
238
- testee.postMessage(eventData)
239
-
240
- verify(mockReplyProxy, never()).postMessage(anyString())
241
- }
242
-
243
- @Test
244
- fun `when posting message and adsjs is enabled but initialPing not processes then do not post message` () = runTest {
245
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(true )
246
- val eventData = SubscriptionEventData (" feature" , " subscription" , JSONObject ())
247
-
248
- testee.postMessage(eventData)
249
-
250
- verify(mockReplyProxy, never()).postMessage(anyString())
251
- }
252
-
253
- @Test
254
- fun `when posting message after getting initialPing and adsjs is enabled then post message` () = runTest {
255
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(true )
256
- val eventData = SubscriptionEventData (" feature" , " subscription" , JSONObject ())
257
- givenInterfaceIsRegistered()
258
- val expectedMessage = """
259
- {"context":"contentScopeScripts","featureName":"feature","params":{},"subscriptionName":"subscription"}
260
- """ .trimIndent()
261
-
262
- verify(mockWebView, never()).postWebMessage(any(), any())
263
-
264
- testee.postMessage(eventData)
265
- verify(mockReplyProxy).postMessage(expectedMessage)
89
+ fun `when constructed then create plugin with correct strategy` () = runTest {
90
+ // Verify that the delegate's createPlugin method was called with a strategy
91
+ verify(mockWebMessagingDelegate).createPlugin(any())
266
92
}
267
93
268
94
private val callback = object : WebViewCompatMessageCallback {
269
- var counter = 0
270
95
override fun process (
271
96
context : String ,
272
97
featureName : String ,
@@ -275,16 +100,7 @@ class ContentScopeScriptsWebMessagingTest {
275
100
data : JSONObject ? ,
276
101
onResponse : (params: JSONObject ) -> Unit ,
277
102
) {
278
- counter ++
103
+ // NOOP for delegation tests
279
104
}
280
105
}
281
-
282
- private fun givenInterfaceIsRegistered () = runTest {
283
- testee.register(callback, mockWebView)
284
- val initialPingMessage =
285
- """
286
- {"context":"contentScopeScripts","featureName":"messaging","id":"debugId","method":"initialPing","params":{}}
287
- """ .trimIndent()
288
- testee.process(initialPingMessage, callback, mockReplyProxy)
289
- }
290
106
}
0 commit comments