adding unified push delegate tests
This commit is contained in:
parent
093e5b64bb
commit
1e8d868348
|
@ -6,7 +6,11 @@ import kotlinx.coroutines.test.runTest
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
fun runExpectTest(testBody: suspend ExpectTestScope.() -> Unit) {
|
fun runExpectTest(testBody: suspend ExpectTestScope.() -> Unit) {
|
||||||
runTest { testBody(ExpectTest(coroutineContext)) }
|
runTest {
|
||||||
|
val expectTest = ExpectTest(coroutineContext)
|
||||||
|
testBody(expectTest)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExpectTest(override val coroutineContext: CoroutineContext) : ExpectTestScope {
|
class ExpectTest(override val coroutineContext: CoroutineContext) : ExpectTestScope {
|
||||||
|
@ -24,6 +28,11 @@ class ExpectTest(override val coroutineContext: CoroutineContext) : ExpectTestSc
|
||||||
expects.add(times to { block(this@expectUnit) })
|
expects.add(times to { block(this@expectUnit) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun <T> T.expect(times: Int, block: suspend MockKMatcherScope.(T) -> Unit) {
|
||||||
|
coJustRun { block(this@expect) }.ignore()
|
||||||
|
expects.add(times to { block(this@expect) })
|
||||||
|
}
|
||||||
|
|
||||||
override fun <T> T.captureExpects(block: suspend MockKMatcherScope.(T) -> Unit) {
|
override fun <T> T.captureExpects(block: suspend MockKMatcherScope.(T) -> Unit) {
|
||||||
groups.add { block(this@captureExpects) }
|
groups.add { block(this@captureExpects) }
|
||||||
}
|
}
|
||||||
|
@ -34,5 +43,6 @@ private fun Any.ignore() = Unit
|
||||||
interface ExpectTestScope : CoroutineScope {
|
interface ExpectTestScope : CoroutineScope {
|
||||||
fun verifyExpects()
|
fun verifyExpects()
|
||||||
fun <T> T.expectUnit(times: Int = 1, block: suspend MockKMatcherScope.(T) -> Unit)
|
fun <T> T.expectUnit(times: Int = 1, block: suspend MockKMatcherScope.(T) -> Unit)
|
||||||
|
fun <T> T.expect(times: Int = 1, block: suspend MockKMatcherScope.(T) -> Unit)
|
||||||
fun <T> T.captureExpects(block: suspend MockKMatcherScope.(T) -> Unit)
|
fun <T> T.captureExpects(block: suspend MockKMatcherScope.(T) -> Unit)
|
||||||
}
|
}
|
|
@ -10,4 +10,8 @@ dependencies {
|
||||||
|
|
||||||
implementation Dependencies.mavenCentral.kotlinSerializationJson
|
implementation Dependencies.mavenCentral.kotlinSerializationJson
|
||||||
implementation Dependencies.jitPack.unifiedPush
|
implementation Dependencies.jitPack.unifiedPush
|
||||||
|
|
||||||
|
kotlinTest(it)
|
||||||
|
androidImportFixturesWorkaround(project, project(":core"))
|
||||||
|
androidImportFixturesWorkaround(project, project(":domains:android:stub"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,10 @@ private val json = Json { ignoreUnknownKeys = true }
|
||||||
|
|
||||||
class UnifiedPushMessageDelegate(
|
class UnifiedPushMessageDelegate(
|
||||||
private val scope: CoroutineScope = CoroutineScope(SupervisorJob()),
|
private val scope: CoroutineScope = CoroutineScope(SupervisorJob()),
|
||||||
private val pushModuleProvider: (Context) -> PushModule = { it.module() }
|
private val pushModuleProvider: (Context) -> PushModule = { it.module() },
|
||||||
|
private val endpointReader: suspend (URL) -> String = {
|
||||||
|
runCatching { it.openStream().use { String(it.readBytes()) } }.getOrNull() ?: ""
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun onMessage(context: Context, message: ByteArray) {
|
fun onMessage(context: Context, message: ByteArray) {
|
||||||
|
@ -44,7 +47,7 @@ class UnifiedPushMessageDelegate(
|
||||||
scope.launch {
|
scope.launch {
|
||||||
withContext(module.dispatcher().io) {
|
withContext(module.dispatcher().io) {
|
||||||
val matrixEndpoint = URL(endpoint).let { URL("${it.protocol}://${it.host}/_matrix/push/v1/notify") }
|
val matrixEndpoint = URL(endpoint).let { URL("${it.protocol}://${it.host}/_matrix/push/v1/notify") }
|
||||||
val content = runCatching { matrixEndpoint.openStream().use { String(it.readBytes()) } }.getOrNull() ?: ""
|
val content = endpointReader(matrixEndpoint)
|
||||||
val gatewayUrl = when {
|
val gatewayUrl = when {
|
||||||
content.contains("\"gateway\":\"matrix\"") -> matrixEndpoint.toString()
|
content.contains("\"gateway\":\"matrix\"") -> matrixEndpoint.toString()
|
||||||
else -> FALLBACK_UNIFIED_PUSH_GATEWAY
|
else -> FALLBACK_UNIFIED_PUSH_GATEWAY
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
package app.dapk.st.push.unifiedpush
|
||||||
|
|
||||||
|
import app.dapk.st.matrix.common.EventId
|
||||||
|
import app.dapk.st.matrix.common.RoomId
|
||||||
|
import app.dapk.st.push.PushHandler
|
||||||
|
import app.dapk.st.push.PushModule
|
||||||
|
import app.dapk.st.push.PushTokenPayload
|
||||||
|
import fake.FakeContext
|
||||||
|
import fixture.CoroutineDispatchersFixture.aCoroutineDispatchers
|
||||||
|
import io.mockk.coEvery
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||||
|
import org.junit.Test
|
||||||
|
import test.delegateReturn
|
||||||
|
import test.runExpectTest
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
private val A_CONTEXT = FakeContext()
|
||||||
|
private const val A_ROOM_ID = "a room id"
|
||||||
|
private const val AN_EVENT_ID = "an event id"
|
||||||
|
private const val AN_ENDPOINT_HOST = "https://aendpointurl.com"
|
||||||
|
private const val AN_ENDPOINT = "$AN_ENDPOINT_HOST/with/path"
|
||||||
|
private const val A_GATEWAY_URL = "$AN_ENDPOINT_HOST/_matrix/push/v1/notify"
|
||||||
|
private const val FALLBACK_GATEWAY_URL = "https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify"
|
||||||
|
|
||||||
|
class UnifiedPushMessageDelegateTest {
|
||||||
|
|
||||||
|
private val fakePushHandler = FakePushHandler()
|
||||||
|
private val fakeEndpointReader = FakeEndpointReader()
|
||||||
|
private val fakePushModule = FakePushModule().also {
|
||||||
|
it.givenPushHandler().returns(fakePushHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val unifiedPushReceiver = UnifiedPushMessageDelegate(
|
||||||
|
CoroutineScope(UnconfinedTestDispatcher()),
|
||||||
|
pushModuleProvider = { _ -> fakePushModule.instance },
|
||||||
|
endpointReader = fakeEndpointReader,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `parses incoming message payloads`() = runExpectTest {
|
||||||
|
fakePushHandler.expect { it.onMessageReceived(EventId(AN_EVENT_ID), RoomId(A_ROOM_ID)) }
|
||||||
|
val messageBytes = createMessage(A_ROOM_ID, AN_EVENT_ID)
|
||||||
|
|
||||||
|
unifiedPushReceiver.onMessage(A_CONTEXT.instance, messageBytes)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given endpoint is a gateway, then uses original endpoint url`() = runExpectTest {
|
||||||
|
fakeEndpointReader.given(A_GATEWAY_URL).returns("""{"unifiedpush":{"gateway":"matrix"}}""")
|
||||||
|
fakePushHandler.expect { it.onNewToken(PushTokenPayload(token = AN_ENDPOINT, gatewayUrl = A_GATEWAY_URL)) }
|
||||||
|
|
||||||
|
unifiedPushReceiver.onNewEndpoint(A_CONTEXT.instance, AN_ENDPOINT)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given endpoint is not a gateway, then uses fallback endpoint url`() = runExpectTest {
|
||||||
|
fakeEndpointReader.given(A_GATEWAY_URL).returns("")
|
||||||
|
fakePushHandler.expect { it.onNewToken(PushTokenPayload(token = AN_ENDPOINT, gatewayUrl = FALLBACK_GATEWAY_URL)) }
|
||||||
|
|
||||||
|
unifiedPushReceiver.onNewEndpoint(A_CONTEXT.instance, AN_ENDPOINT)
|
||||||
|
|
||||||
|
verifyExpects()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createMessage(roomId: String, eventId: String) = """
|
||||||
|
{
|
||||||
|
"notification": {
|
||||||
|
"room_id": "$roomId",
|
||||||
|
"event_id": "$eventId"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent().toByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakePushModule {
|
||||||
|
val instance = mockk<PushModule>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
every { instance.dispatcher() }.returns(aCoroutineDispatchers())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun givenPushHandler() = every { instance.pushHandler() }.delegateReturn()
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakePushHandler : PushHandler by mockk()
|
||||||
|
|
||||||
|
class FakeEndpointReader : suspend (URL) -> String by mockk() {
|
||||||
|
|
||||||
|
fun given(url: String) = coEvery { this@FakeEndpointReader.invoke(URL(url)) }.delegateReturn()
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue