Add unit test on RustLinkDesktopHandler
Add unit test on RustLinkMobileHandler Add unit test on DefaultLinkNewDeviceEntryPoint
This commit is contained in:
parent
5bb9f579a4
commit
b5fdc179c7
10 changed files with 348 additions and 2 deletions
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Element Creations Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.linknewdevice.impl
|
||||||
|
|
||||||
|
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||||
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
|
import com.bumble.appyx.testing.junit4.util.MainDispatcherRule
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import io.element.android.features.linknewdevice.api.LinkNewDeviceEntryPoint
|
||||||
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
|
import io.element.android.tests.testutils.lambda.lambdaError
|
||||||
|
import io.element.android.tests.testutils.node.TestParentNode
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class DefaultLinkNewDeviceEntryPointTest {
|
||||||
|
@get:Rule
|
||||||
|
val instantTaskExecutorRule = InstantTaskExecutorRule()
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val mainDispatcherRule = MainDispatcherRule()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test node creation`() = runTest {
|
||||||
|
val entryPoint = DefaultLinkNewDeviceEntryPoint()
|
||||||
|
val client = FakeMatrixClient()
|
||||||
|
val parentNode = TestParentNode.create { buildContext, plugins ->
|
||||||
|
LinkNewDeviceFlowNode(
|
||||||
|
buildContext = buildContext,
|
||||||
|
plugins = plugins,
|
||||||
|
sessionCoroutineScope = backgroundScope,
|
||||||
|
linkNewMobileHandler = LinkNewMobileHandler(client),
|
||||||
|
linkNewDesktopHandler = LinkNewDesktopHandler(client),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val callback: LinkNewDeviceEntryPoint.Callback = object : LinkNewDeviceEntryPoint.Callback {
|
||||||
|
override fun onDone() = lambdaError()
|
||||||
|
}
|
||||||
|
val result = entryPoint.createNode(parentNode, BuildContext.root(null), callback)
|
||||||
|
assertThat(result).isInstanceOf(LinkNewDeviceFlowNode::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -49,6 +49,7 @@ import io.element.android.libraries.matrix.impl.encryption.RustEncryptionService
|
||||||
import io.element.android.libraries.matrix.impl.exception.mapClientException
|
import io.element.android.libraries.matrix.impl.exception.mapClientException
|
||||||
import io.element.android.libraries.matrix.impl.linknewdevice.RustLinkDesktopHandler
|
import io.element.android.libraries.matrix.impl.linknewdevice.RustLinkDesktopHandler
|
||||||
import io.element.android.libraries.matrix.impl.linknewdevice.RustLinkMobileHandler
|
import io.element.android.libraries.matrix.impl.linknewdevice.RustLinkMobileHandler
|
||||||
|
import io.element.android.libraries.matrix.impl.linknewdevice.RustQrCodeDataParser
|
||||||
import io.element.android.libraries.matrix.impl.mapper.map
|
import io.element.android.libraries.matrix.impl.mapper.map
|
||||||
import io.element.android.libraries.matrix.impl.media.RustMediaLoader
|
import io.element.android.libraries.matrix.impl.media.RustMediaLoader
|
||||||
import io.element.android.libraries.matrix.impl.media.RustMediaPreviewService
|
import io.element.android.libraries.matrix.impl.media.RustMediaPreviewService
|
||||||
|
|
@ -754,6 +755,7 @@ class RustMatrixClient(
|
||||||
inner = handler,
|
inner = handler,
|
||||||
sessionCoroutineScope = sessionCoroutineScope,
|
sessionCoroutineScope = sessionCoroutineScope,
|
||||||
sessionDispatcher = sessionDispatcher,
|
sessionDispatcher = sessionDispatcher,
|
||||||
|
qrCodeDataParser = RustQrCodeDataParser(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Element Creations Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.matrix.impl.linknewdevice
|
||||||
|
|
||||||
|
import org.matrix.rustcomponents.sdk.QrCodeData
|
||||||
|
|
||||||
|
interface QrCodeDataParser {
|
||||||
|
fun parse(data: ByteArray): QrCodeData
|
||||||
|
}
|
||||||
|
|
||||||
|
class RustQrCodeDataParser : QrCodeDataParser {
|
||||||
|
override fun parse(data: ByteArray): QrCodeData {
|
||||||
|
return QrCodeData.fromBytes(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,7 +23,6 @@ import org.matrix.rustcomponents.sdk.GrantLoginWithQrCodeHandler
|
||||||
import org.matrix.rustcomponents.sdk.GrantQrLoginProgress
|
import org.matrix.rustcomponents.sdk.GrantQrLoginProgress
|
||||||
import org.matrix.rustcomponents.sdk.GrantQrLoginProgressListener
|
import org.matrix.rustcomponents.sdk.GrantQrLoginProgressListener
|
||||||
import org.matrix.rustcomponents.sdk.HumanQrGrantLoginException
|
import org.matrix.rustcomponents.sdk.HumanQrGrantLoginException
|
||||||
import org.matrix.rustcomponents.sdk.QrCodeData
|
|
||||||
import org.matrix.rustcomponents.sdk.QrCodeDecodeException
|
import org.matrix.rustcomponents.sdk.QrCodeDecodeException
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
|
|
@ -33,6 +32,7 @@ class RustLinkDesktopHandler(
|
||||||
private val inner: GrantLoginWithQrCodeHandler,
|
private val inner: GrantLoginWithQrCodeHandler,
|
||||||
private val sessionCoroutineScope: CoroutineScope,
|
private val sessionCoroutineScope: CoroutineScope,
|
||||||
private val sessionDispatcher: CoroutineDispatcher,
|
private val sessionDispatcher: CoroutineDispatcher,
|
||||||
|
private val qrCodeDataParser: QrCodeDataParser,
|
||||||
) : LinkDesktopHandler {
|
) : LinkDesktopHandler {
|
||||||
private val _linkDesktopStep = MutableStateFlow<LinkDesktopStep>(LinkDesktopStep.Uninitialized)
|
private val _linkDesktopStep = MutableStateFlow<LinkDesktopStep>(LinkDesktopStep.Uninitialized)
|
||||||
override val linkDesktopStep: StateFlow<LinkDesktopStep> = _linkDesktopStep.asStateFlow()
|
override val linkDesktopStep: StateFlow<LinkDesktopStep> = _linkDesktopStep.asStateFlow()
|
||||||
|
|
@ -41,7 +41,7 @@ class RustLinkDesktopHandler(
|
||||||
Timber.tag(tag.value).d("Emit Uninitialized")
|
Timber.tag(tag.value).d("Emit Uninitialized")
|
||||||
_linkDesktopStep.emit(LinkDesktopStep.Uninitialized)
|
_linkDesktopStep.emit(LinkDesktopStep.Uninitialized)
|
||||||
try {
|
try {
|
||||||
val qrCodeData = QrCodeData.fromBytes(data)
|
val qrCodeData = qrCodeDataParser.parse(data)
|
||||||
inner.scan(
|
inner.scan(
|
||||||
qrCodeData = qrCodeData,
|
qrCodeData = qrCodeData,
|
||||||
progressListener = object : GrantQrLoginProgressListener {
|
progressListener = object : GrantQrLoginProgressListener {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Element Creations Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.matrix.impl.fixtures.fakes
|
||||||
|
|
||||||
|
import org.matrix.rustcomponents.sdk.CheckCodeSender
|
||||||
|
import org.matrix.rustcomponents.sdk.NoHandle
|
||||||
|
|
||||||
|
class FakeFfiCheckCodeSender : CheckCodeSender(NoHandle)
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Element Creations Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.matrix.impl.fixtures.fakes
|
||||||
|
|
||||||
|
import org.matrix.rustcomponents.sdk.GrantGeneratedQrLoginProgress
|
||||||
|
import org.matrix.rustcomponents.sdk.GrantGeneratedQrLoginProgressListener
|
||||||
|
import org.matrix.rustcomponents.sdk.GrantLoginWithQrCodeHandler
|
||||||
|
import org.matrix.rustcomponents.sdk.GrantQrLoginProgress
|
||||||
|
import org.matrix.rustcomponents.sdk.GrantQrLoginProgressListener
|
||||||
|
import org.matrix.rustcomponents.sdk.NoHandle
|
||||||
|
import org.matrix.rustcomponents.sdk.QrCodeData
|
||||||
|
|
||||||
|
class FakeFfiGrantLoginWithQrCodeHandler(
|
||||||
|
private val generateResult: () -> Unit = {},
|
||||||
|
private val scanResult: (QrCodeData) -> Unit = {},
|
||||||
|
) : GrantLoginWithQrCodeHandler(NoHandle) {
|
||||||
|
private var generateProgressListener: GrantGeneratedQrLoginProgressListener? = null
|
||||||
|
private var scanProgressListener: GrantQrLoginProgressListener? = null
|
||||||
|
override suspend fun generate(progressListener: GrantGeneratedQrLoginProgressListener) {
|
||||||
|
generateProgressListener = progressListener
|
||||||
|
generateResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun emitGenerateProgress(progress: GrantGeneratedQrLoginProgress) {
|
||||||
|
generateProgressListener?.onUpdate(progress)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun scan(qrCodeData: QrCodeData, progressListener: GrantQrLoginProgressListener) {
|
||||||
|
scanProgressListener = progressListener
|
||||||
|
scanResult(qrCodeData)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun emitScanProgress(progress: GrantQrLoginProgress) {
|
||||||
|
scanProgressListener?.onUpdate(progress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,8 +14,13 @@ import org.matrix.rustcomponents.sdk.QrCodeData
|
||||||
|
|
||||||
class FakeFfiQrCodeData(
|
class FakeFfiQrCodeData(
|
||||||
private val serverNameResult: () -> String? = { lambdaError() },
|
private val serverNameResult: () -> String? = { lambdaError() },
|
||||||
|
private val toBytesResult: () -> ByteArray = { lambdaError() },
|
||||||
) : QrCodeData(NoHandle) {
|
) : QrCodeData(NoHandle) {
|
||||||
override fun serverName(): String? {
|
override fun serverName(): String? {
|
||||||
return serverNameResult()
|
return serverNameResult()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toBytes(): ByteArray {
|
||||||
|
return toBytesResult()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Element Creations Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.matrix.impl.linknewdevice
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiQrCodeData
|
||||||
|
import org.matrix.rustcomponents.sdk.QrCodeData
|
||||||
|
|
||||||
|
class FakeQrCodeDataParser : QrCodeDataParser {
|
||||||
|
override fun parse(data: ByteArray): QrCodeData {
|
||||||
|
return FakeFfiQrCodeData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Element Creations Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
|
||||||
|
package io.element.android.libraries.matrix.impl.linknewdevice
|
||||||
|
|
||||||
|
import app.cash.turbine.test
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import io.element.android.libraries.matrix.api.linknewdevice.ErrorType
|
||||||
|
import io.element.android.libraries.matrix.api.linknewdevice.LinkDesktopStep
|
||||||
|
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiGrantLoginWithQrCodeHandler
|
||||||
|
import io.element.android.libraries.matrix.test.QR_CODE_DATA
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
import kotlinx.coroutines.test.runCurrent
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.rustcomponents.sdk.GrantQrLoginProgress
|
||||||
|
import org.matrix.rustcomponents.sdk.HumanQrGrantLoginException
|
||||||
|
import org.matrix.rustcomponents.sdk.QrCodeDecodeException
|
||||||
|
|
||||||
|
class RustLinkDesktopHandlerTest {
|
||||||
|
@Test
|
||||||
|
fun `handleScannedQrCode function works as expected`() = runTest {
|
||||||
|
val handler = FakeFfiGrantLoginWithQrCodeHandler()
|
||||||
|
val sut = createRustLinkDesktopHandler(
|
||||||
|
handler,
|
||||||
|
)
|
||||||
|
sut.linkDesktopStep.test {
|
||||||
|
val initialItem = awaitItem()
|
||||||
|
assertThat(initialItem).isEqualTo(LinkDesktopStep.Uninitialized)
|
||||||
|
backgroundScope.launch {
|
||||||
|
sut.handleScannedQrCode(QR_CODE_DATA)
|
||||||
|
}
|
||||||
|
runCurrent()
|
||||||
|
// progress from the handler is mapped and emitted
|
||||||
|
listOf(
|
||||||
|
GrantQrLoginProgress.Starting to LinkDesktopStep.Starting,
|
||||||
|
GrantQrLoginProgress.SyncingSecrets to LinkDesktopStep.SyncingSecrets,
|
||||||
|
GrantQrLoginProgress.WaitingForAuth("aVerificationUri")
|
||||||
|
to LinkDesktopStep.WaitingForAuth("aVerificationUri"),
|
||||||
|
GrantQrLoginProgress.EstablishingSecureChannel(1.toUByte(), "1")
|
||||||
|
to LinkDesktopStep.EstablishingSecureChannel(1.toUByte(), "1"),
|
||||||
|
GrantQrLoginProgress.Done to LinkDesktopStep.Done,
|
||||||
|
).forEach { (progress, expectedStep) ->
|
||||||
|
handler.emitScanProgress(progress)
|
||||||
|
assertThat(awaitItem()).isEqualTo(expectedStep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when handleScannedQrCode throws QrCodeDecodeException, the handler emits error step`() = runTest {
|
||||||
|
val handler = FakeFfiGrantLoginWithQrCodeHandler(
|
||||||
|
scanResult = { throw QrCodeDecodeException.Crypto("Scan failed") }
|
||||||
|
)
|
||||||
|
val sut = createRustLinkDesktopHandler(
|
||||||
|
handler,
|
||||||
|
)
|
||||||
|
sut.linkDesktopStep.test {
|
||||||
|
val initialItem = awaitItem()
|
||||||
|
assertThat(initialItem).isEqualTo(LinkDesktopStep.Uninitialized)
|
||||||
|
backgroundScope.launch {
|
||||||
|
sut.handleScannedQrCode(QR_CODE_DATA)
|
||||||
|
}
|
||||||
|
runCurrent()
|
||||||
|
val errorState = awaitItem()
|
||||||
|
assertThat(errorState).isInstanceOf(LinkDesktopStep.InvalidQrCode::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when handleScannedQrCode throws HumanQrGrantLoginException, the handler emits error step`() = runTest {
|
||||||
|
val handler = FakeFfiGrantLoginWithQrCodeHandler(
|
||||||
|
scanResult = { throw HumanQrGrantLoginException.InvalidCheckCode("Invalid check code") }
|
||||||
|
)
|
||||||
|
val sut = createRustLinkDesktopHandler(
|
||||||
|
handler,
|
||||||
|
)
|
||||||
|
sut.linkDesktopStep.test {
|
||||||
|
val initialItem = awaitItem()
|
||||||
|
assertThat(initialItem).isEqualTo(LinkDesktopStep.Uninitialized)
|
||||||
|
backgroundScope.launch {
|
||||||
|
sut.handleScannedQrCode(QR_CODE_DATA)
|
||||||
|
}
|
||||||
|
runCurrent()
|
||||||
|
val errorState = awaitItem()
|
||||||
|
assertThat(errorState).isInstanceOf(LinkDesktopStep.Error::class.java)
|
||||||
|
val errorType = (errorState as LinkDesktopStep.Error).errorType
|
||||||
|
assertThat(errorType).isInstanceOf(ErrorType.InvalidCheckCode::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TestScope.createRustLinkDesktopHandler(
|
||||||
|
handler: FakeFfiGrantLoginWithQrCodeHandler = FakeFfiGrantLoginWithQrCodeHandler(),
|
||||||
|
) = RustLinkDesktopHandler(
|
||||||
|
inner = handler,
|
||||||
|
sessionCoroutineScope = backgroundScope,
|
||||||
|
sessionDispatcher = StandardTestDispatcher(testScheduler),
|
||||||
|
qrCodeDataParser = FakeQrCodeDataParser(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Element Creations Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
|
||||||
|
package io.element.android.libraries.matrix.impl.linknewdevice
|
||||||
|
|
||||||
|
import app.cash.turbine.test
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import io.element.android.libraries.matrix.api.linknewdevice.ErrorType
|
||||||
|
import io.element.android.libraries.matrix.api.linknewdevice.LinkMobileStep
|
||||||
|
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiCheckCodeSender
|
||||||
|
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiGrantLoginWithQrCodeHandler
|
||||||
|
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiQrCodeData
|
||||||
|
import io.element.android.libraries.matrix.test.QR_CODE_DATA_RECIPROCATE
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
import kotlinx.coroutines.test.runCurrent
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.rustcomponents.sdk.GrantGeneratedQrLoginProgress
|
||||||
|
import org.matrix.rustcomponents.sdk.HumanQrGrantLoginException
|
||||||
|
|
||||||
|
class RustLinkMobileHandlerTest {
|
||||||
|
@Test
|
||||||
|
fun `start function works as expected`() = runTest {
|
||||||
|
val handler = FakeFfiGrantLoginWithQrCodeHandler()
|
||||||
|
val sut = createRustLinkMobileHandler(
|
||||||
|
handler,
|
||||||
|
)
|
||||||
|
sut.linkMobileStep.test {
|
||||||
|
val initialItem = awaitItem()
|
||||||
|
assertThat(initialItem).isEqualTo(LinkMobileStep.Uninitialized)
|
||||||
|
backgroundScope.launch {
|
||||||
|
sut.start()
|
||||||
|
}
|
||||||
|
runCurrent()
|
||||||
|
// progress from the handler is mapped and emitted
|
||||||
|
listOf(
|
||||||
|
GrantGeneratedQrLoginProgress.Starting to LinkMobileStep.Starting::class.java,
|
||||||
|
GrantGeneratedQrLoginProgress.SyncingSecrets to LinkMobileStep.SyncingSecrets::class.java,
|
||||||
|
GrantGeneratedQrLoginProgress.WaitingForAuth("aVerificationUri")
|
||||||
|
to LinkMobileStep.WaitingForAuth::class.java,
|
||||||
|
GrantGeneratedQrLoginProgress.QrScanned(FakeFfiCheckCodeSender())
|
||||||
|
to LinkMobileStep.QrScanned::class.java,
|
||||||
|
GrantGeneratedQrLoginProgress.QrReady(FakeFfiQrCodeData(toBytesResult = { QR_CODE_DATA_RECIPROCATE }))
|
||||||
|
to LinkMobileStep.QrReady::class.java,
|
||||||
|
GrantGeneratedQrLoginProgress.Done to LinkMobileStep.Done::class.java,
|
||||||
|
).forEach { (progress, expectedStepClass) ->
|
||||||
|
handler.emitGenerateProgress(progress)
|
||||||
|
assertThat(awaitItem()).isInstanceOf(expectedStepClass)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when start throws HumanQrGrantLoginException, the handler emits error step`() = runTest {
|
||||||
|
val handler = FakeFfiGrantLoginWithQrCodeHandler(
|
||||||
|
generateResult = { throw HumanQrGrantLoginException.NotFound("Timeout") }
|
||||||
|
)
|
||||||
|
val sut = createRustLinkMobileHandler(
|
||||||
|
handler,
|
||||||
|
)
|
||||||
|
sut.linkMobileStep.test {
|
||||||
|
val initialItem = awaitItem()
|
||||||
|
assertThat(initialItem).isEqualTo(LinkMobileStep.Uninitialized)
|
||||||
|
backgroundScope.launch {
|
||||||
|
sut.start()
|
||||||
|
}
|
||||||
|
runCurrent()
|
||||||
|
val errorState = awaitItem()
|
||||||
|
assertThat(errorState).isInstanceOf(LinkMobileStep.Error::class.java)
|
||||||
|
val errorType = (errorState as LinkMobileStep.Error).errorType
|
||||||
|
assertThat(errorType).isInstanceOf(ErrorType.NotFound::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TestScope.createRustLinkMobileHandler(
|
||||||
|
handler: FakeFfiGrantLoginWithQrCodeHandler = FakeFfiGrantLoginWithQrCodeHandler(),
|
||||||
|
) = RustLinkMobileHandler(
|
||||||
|
inner = handler,
|
||||||
|
sessionCoroutineScope = backgroundScope,
|
||||||
|
sessionDispatcher = StandardTestDispatcher(testScheduler),
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue