@@ -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,242 +44,63 @@ 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 > = listOf (FakePlugin ())
64
-
65
- inner class FakePlugin : WebViewCompatContentScopeJsMessageHandlersPlugin {
66
- override fun getJsMessageHandler (): WebViewCompatMessageHandler =
67
- object : WebViewCompatMessageHandler {
68
- override fun process (jsMessage : JsMessage ): ProcessResult = SendToConsumer
69
-
70
- override val featureName: String = " webCompat"
71
- override val methods: List <String > = listOf (" webShare" , " permissionsQuery" )
72
- }
73
- }
74
- }
75
-
76
- private class FakeGlobalHandlersPluginPoint : PluginPoint <GlobalContentScopeJsMessageHandlersPlugin > {
77
- override fun getPlugins (): Collection <GlobalContentScopeJsMessageHandlersPlugin > = listOf (FakeGlobalHandlerPlugin ())
78
-
79
- inner class FakeGlobalHandlerPlugin : GlobalContentScopeJsMessageHandlersPlugin {
80
- override fun getGlobalJsMessageHandler (): GlobalJsMessageHandler =
81
- object : GlobalJsMessageHandler {
82
- override fun process (jsMessage : JsMessage ): ProcessResult = SendToConsumer
83
-
84
- override val method: String = " addDebugFlag"
85
- }
86
- }
87
- }
88
-
89
54
@Before
90
55
fun setUp () = runTest {
91
- whenever(webViewCompatContentScopeScripts.isEnabled()) .thenReturn(true )
56
+ whenever(mockWebMessagingDelegate.createPlugin(any())) .thenReturn(mockWebMessaging )
92
57
testee = ContentScopeScriptsWebMessaging (
93
58
handlers = handlers,
94
59
globalHandlers = globalHandlers,
95
60
webViewCompatContentScopeScripts = webViewCompatContentScopeScripts,
96
- webViewCompatWrapper = mockWebViewCompatWrapper ,
61
+ webMessagingDelegate = mockWebMessagingDelegate ,
97
62
)
98
63
}
99
64
100
65
@Test
101
- fun `when process and message can be handled then execute callback` () =
102
- runTest {
103
- givenInterfaceIsRegistered()
104
-
105
- val message =
106
- """
107
- {"context":"contentScopeScripts","featureName":"webCompat","id":"myId","method":"webShare","params":{}}
108
- """ .trimIndent()
109
-
110
- testee.process(mockWebView, message, callback, mockReplyProxy)
111
-
112
- assertEquals(1 , callback.counter)
113
- }
114
-
115
- @Test
116
- fun `when processing unknown message do nothing` () =
117
- runTest {
118
- givenInterfaceIsRegistered()
119
-
120
- testee.process(mockWebView, " " , callback, mockReplyProxy)
121
-
122
- assertEquals(0 , callback.counter)
123
- }
124
-
125
- @Test
126
- fun `when feature does not match do nothing` () =
127
- runTest {
128
- givenInterfaceIsRegistered()
129
-
130
- val message =
131
- """
132
- {"context":"contentScopeScripts","featureName":"test","id":"myId","method":"webShare","params":{}}
133
- """ .trimIndent()
134
-
135
- testee.process(mockWebView, message, callback, mockReplyProxy)
136
-
137
- assertEquals(0 , callback.counter)
138
- }
139
-
140
- @Test
141
- fun `when id does not exist do nothing` () =
142
- runTest {
143
- givenInterfaceIsRegistered()
144
-
145
- val message =
146
- """
147
- {"context":"contentScopeScripts","webCompat":"test","method":"webShare","params":{}}
148
- """ .trimIndent()
149
-
150
- testee.process(mockWebView, message, callback, mockReplyProxy)
66
+ fun `when register called then delegate to created plugin` () = runTest {
67
+ testee.register(callback, mockWebView)
151
68
152
- assertEquals(0 , callback.counter)
153
- }
154
-
155
- @Test
156
- fun `when processing addDebugFlag message then process message` () =
157
- runTest {
158
- givenInterfaceIsRegistered()
159
-
160
- val message =
161
- """
162
- {"context":"contentScopeScripts","featureName":"debugFeature","id":"debugId","method":"addDebugFlag","params":{}}
163
- """ .trimIndent()
164
-
165
- testee.process(mockWebView, message, callback, mockReplyProxy)
166
-
167
- assertEquals(1 , callback.counter)
168
- }
169
-
170
- @Test
171
- fun `when registering and adsjs is disabled then do not register` () =
172
- runTest {
173
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(false )
174
-
175
- testee.register(callback, mockWebView)
176
-
177
- verify(mockWebViewCompatWrapper, never())
178
- .addWebMessageListener(any(), any(), any(), any())
179
- }
180
-
181
- @Test
182
- fun `when registering and adsjs is enabled then register` () =
183
- runTest {
184
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(true )
185
-
186
- testee.register(callback, mockWebView)
187
-
188
- verify(mockWebViewCompatWrapper).addWebMessageListener(
189
- eq(mockWebView),
190
- eq(" contentScopeAdsjs" ),
191
- eq(setOf (" *" )),
192
- any(),
193
- )
194
- }
195
-
196
- @Test
197
- fun `when unregistering and adsjs is disabled then do not unregister` () =
198
- runTest {
199
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(false )
200
-
201
- testee.unregister(mockWebView)
202
-
203
- verify(mockWebViewCompatWrapper, never())
204
- .removeWebMessageListener(any(), any())
205
- }
206
-
207
- @Test
208
- fun `when unregistering and adsjs is enabled then unregister` () =
209
- runTest {
210
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(true )
211
-
212
- testee.unregister(mockWebView)
213
-
214
- verify(mockWebViewCompatWrapper).removeWebMessageListener(mockWebView, " contentScopeAdsjs" )
215
- }
216
-
217
- @Test
218
- fun `when posting message and adsjs is disabled then do not post message` () =
219
- runTest {
220
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(false )
221
- val eventData = SubscriptionEventData (" feature" , " subscription" , JSONObject ())
222
- givenInterfaceIsRegistered()
223
-
224
- testee.postMessage(mockWebView, eventData)
225
-
226
- verify(mockWebViewCompatWrapper, never()).postMessage(any(), any(), anyString())
227
- }
69
+ verify(mockWebMessaging).register(callback, mockWebView)
70
+ }
228
71
229
72
@Test
230
- fun `when posting message and adsjs is enabled but webView not registered then do not post message` () =
231
- runTest {
232
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(true )
233
- val eventData = SubscriptionEventData (" feature" , " subscription" , JSONObject ())
73
+ fun `when unregister called then delegate to created plugin` () = runTest {
74
+ testee.unregister(mockWebView)
234
75
235
- testee.postMessage(mockWebView, eventData)
236
-
237
- verify(mockWebViewCompatWrapper, never()).postMessage(any(), any(), anyString())
238
- }
76
+ verify(mockWebMessaging).unregister(mockWebView)
77
+ }
239
78
240
79
@Test
241
- fun `when posting message and adsjs is enabled but initialPing not processes then do not post message` () =
242
- runTest {
243
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(true )
244
- val eventData = SubscriptionEventData (" feature" , " subscription" , JSONObject ())
80
+ fun `when postMessage called then delegate to created plugin` () = runTest {
81
+ val eventData = SubscriptionEventData (" feature" , " subscription" , JSONObject ())
245
82
246
- testee.postMessage(mockWebView, eventData)
83
+ testee.postMessage(mockWebView, eventData)
247
84
248
- verify(mockWebViewCompatWrapper, never()) .postMessage(any(), any(), anyString() )
249
- }
85
+ verify(mockWebMessaging) .postMessage(mockWebView, eventData )
86
+ }
250
87
251
88
@Test
252
- fun `when posting message after getting initialPing and adsjs is enabled then post message` () =
253
- runTest {
254
- whenever(webViewCompatContentScopeScripts.isEnabled()).thenReturn(true )
255
- val eventData = SubscriptionEventData (" feature" , " subscription" , JSONObject ())
256
- givenInterfaceIsRegistered()
257
- val expectedMessage =
258
- """
259
- {"context":"contentScopeScripts","featureName":"feature","params":{},"subscriptionName":"subscription"}
260
- """ .trimIndent()
261
-
262
- verify(mockWebView, never()).postWebMessage(any(), any())
263
-
264
- testee.postMessage(mockWebView, eventData)
265
- verify(mockWebViewCompatWrapper).postMessage(mockWebView, mockReplyProxy, expectedMessage)
266
- }
267
-
268
- private val callback =
269
- object : WebViewCompatMessageCallback {
270
- var counter = 0
271
-
272
- override fun process (
273
- context : String ,
274
- featureName : String ,
275
- method : String ,
276
- id : String? ,
277
- data : JSONObject ? ,
278
- onResponse : suspend (params: JSONObject ) -> Unit ,
279
- ) {
280
- counter++
281
- }
282
- }
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())
92
+ }
283
93
284
- private fun givenInterfaceIsRegistered () =
285
- runTest {
286
- testee.register(callback, mockWebView)
287
- val initialPingMessage =
288
- """
289
- {"context":"contentScopeScripts","featureName":"messaging","id":"debugId","method":"initialPing","params":{}}
290
- """ .trimIndent()
291
- testee.process(mockWebView, initialPingMessage, callback, mockReplyProxy)
94
+ private val callback = object : WebViewCompatMessageCallback {
95
+ override fun process (
96
+ context : String ,
97
+ featureName : String ,
98
+ method : String ,
99
+ id : String? ,
100
+ data : JSONObject ? ,
101
+ onResponse : suspend (params: JSONObject ) -> Unit ,
102
+ ) {
103
+ // NOOP for delegation tests
292
104
}
105
+ }
293
106
}
0 commit comments