WebPushEngineIntegrationTest.kt 5.89 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/* 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.push

import android.util.Base64
import io.mockk.Called
import io.mockk.CapturingSlot
import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.just
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.slot
import io.mockk.unmockkStatic
import io.mockk.verify
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.runBlockingTest
import mozilla.components.concept.engine.Engine
import mozilla.components.concept.engine.webpush.WebPushDelegate
import mozilla.components.concept.engine.webpush.WebPushHandler
import mozilla.components.concept.engine.webpush.WebPushSubscription
import mozilla.components.feature.push.AutoPushFeature
import mozilla.components.feature.push.AutoPushSubscription
import org.junit.After
import org.junit.Before
import org.junit.Test

@ExperimentalCoroutinesApi
class WebPushEngineIntegrationTest {

    private val scope = TestCoroutineScope()
    @MockK private lateinit var engine: Engine
    @MockK private lateinit var pushFeature: AutoPushFeature
    @MockK(relaxed = true) private lateinit var handler: WebPushHandler
    private lateinit var delegate: CapturingSlot<WebPushDelegate>
    private lateinit var integration: WebPushEngineIntegration

    @Before
    fun setup() {
        MockKAnnotations.init(this)
        mockkStatic(Base64::class)
        delegate = slot()

        every { engine.registerWebPushDelegate(capture(delegate)) } returns handler
        every { pushFeature.register(any()) } just Runs
        every { pushFeature.unregister(any()) } just Runs
        every { Base64.decode(any<ByteArray>(), any()) } answers { firstArg() }

        integration = WebPushEngineIntegration(engine, pushFeature, scope)
    }

    @After
    fun teardown() {
        unmockkStatic(Base64::class)
60
        scope.cleanupTestCoroutines()
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
    }

    @Test
    fun `methods are no-op before calling start`() = scope.runBlockingTest {
        integration.onMessageReceived("push", null)
        integration.onSubscriptionChanged("push")
        verify { handler wasNot Called }

        integration.start()

        integration.onMessageReceived("push", null)
        verify { handler.onPushMessage("push", null) }

        integration.onSubscriptionChanged("push")
        verify { handler.onSubscriptionChanged("push") }
    }

    @Test
    fun `start and stop register and unregister pushFeature`() {
        integration.start()
        verify { pushFeature.register(integration) }

        integration.stop()
        verify { pushFeature.unregister(integration) }
    }

    @Test
    fun `delegate calls getSubscription`() {
        integration.start()
        val slot = slot<(AutoPushSubscription?) -> Unit>()
        every { pushFeature.getSubscription("scope", block = capture(slot)) } just Runs

        val onSubscription = mockk<(WebPushSubscription?) -> Unit>(relaxed = true)
        delegate.captured.onGetSubscription("scope", onSubscription)

        verify { onSubscription wasNot Called }
        slot.captured(AutoPushSubscription(
            scope = "scope",
            publicKey = "abc",
            endpoint = "def",
            authKey = "xyz",
            appServerKey = null
        ))

        verify {
            onSubscription(
                WebPushSubscription(
                    scope = "scope",
                    publicKey = "abc".toByteArray(),
                    endpoint = "def",
                    authSecret = "xyz".toByteArray(),
                    appServerKey = null
                )
            )
        }
    }

    @Test
    fun `delegate calls subscribe`() {
        integration.start()
121
        val onSubscribeError = slot<(Exception) -> Unit>()
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
        val onSubscribe = slot<(AutoPushSubscription?) -> Unit>()
        every {
            pushFeature.subscribe(
                scope = "scope",
                appServerKey = null,
                onSubscribeError = capture(onSubscribeError),
                onSubscribe = capture(onSubscribe)
            )
        } just Runs

        val onSubscription = mockk<(WebPushSubscription?) -> Unit>(relaxed = true)
        delegate.captured.onSubscribe("scope", null, onSubscription)

        verify { onSubscription wasNot Called }

137
        onSubscribeError.captured(mockk())
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
        verify { onSubscription(null) }

        onSubscribe.captured(AutoPushSubscription(
            scope = "scope",
            publicKey = "abc",
            endpoint = "def",
            authKey = "xyz",
            appServerKey = null
        ))
        verify {
            onSubscription(
                WebPushSubscription(
                    scope = "scope",
                    publicKey = "abc".toByteArray(),
                    endpoint = "def",
                    authSecret = "xyz".toByteArray(),
                    appServerKey = null
                )
            )
        }
    }

    @Test
    fun `delegate calls unsubscribe`() {
        integration.start()
163
        val onUnsubscribeError = slot<(Exception) -> Unit>()
164
165
166
167
168
169
170
171
172
173
174
175
176
177
        val onUnsubscribe = slot<(Boolean) -> Unit>()
        every {
            pushFeature.unsubscribe(
                scope = "scope",
                onUnsubscribeError = capture(onUnsubscribeError),
                onUnsubscribe = capture(onUnsubscribe)
            )
        } just Runs

        val onUnsubscription = mockk<(Boolean) -> Unit>(relaxed = true)
        delegate.captured.onUnsubscribe("scope", onUnsubscription)

        verify { onUnsubscription wasNot Called }

178
        onUnsubscribeError.captured(mockk())
179
180
181
182
183
184
        verify { onUnsubscription(false) }

        onUnsubscribe.captured(true)
        verify { onUnsubscription(true) }
    }
}