Flow migration: add back some test
This commit is contained in:
parent
8cf5b727e1
commit
a9d192fa39
|
@ -41,7 +41,8 @@ ext.libs = [
|
|||
jetbrains : [
|
||||
'coroutinesCore' : "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutines",
|
||||
'coroutinesAndroid' : "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutines",
|
||||
'coroutinesRx2' : "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlinCoroutines"
|
||||
'coroutinesRx2' : "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlinCoroutines",
|
||||
'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines"
|
||||
],
|
||||
androidx : [
|
||||
'appCompat' : "androidx.appcompat:appcompat:1.3.1",
|
||||
|
|
|
@ -508,6 +508,7 @@ dependencies {
|
|||
// Plant Timber tree for test
|
||||
testImplementation libs.tests.timberJunitRule
|
||||
testImplementation libs.airbnb.mavericksTesting
|
||||
testImplementation libs.jetbrains.coroutinesTest
|
||||
|
||||
// Activate when you want to check for leaks, from time to time.
|
||||
//debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'
|
||||
|
@ -521,6 +522,7 @@ dependencies {
|
|||
androidTestImplementation libs.androidx.espressoIntents
|
||||
androidTestImplementation libs.tests.kluent
|
||||
androidTestImplementation libs.androidx.coreTesting
|
||||
androidTestImplementation libs.jetbrains.coroutinesTest
|
||||
// Plant Timber tree for test
|
||||
androidTestImplementation libs.tests.timberJunitRule
|
||||
// "The one who serves a great Espresso"
|
||||
|
|
|
@ -22,6 +22,7 @@ import im.vector.app.test.InstantRxRule
|
|||
import im.vector.app.test.fakes.FakeSession
|
||||
import im.vector.app.test.fakes.FakeStringProvider
|
||||
import im.vector.app.test.test
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.matrix.android.sdk.api.session.securestorage.IntegrityResult
|
||||
|
@ -41,6 +42,7 @@ class SharedSecureStorageViewModelTest {
|
|||
|
||||
@get:Rule
|
||||
val instantRx = InstantRxRule()
|
||||
|
||||
@get:Rule
|
||||
val mvrxTestRule = MvRxTestRule()
|
||||
|
||||
|
@ -50,78 +52,100 @@ class SharedSecureStorageViewModelTest {
|
|||
|
||||
@Test
|
||||
fun `given a key info with passphrase when initialising then step is EnterPassphrase`() {
|
||||
givenKey(KEY_INFO_WITH_PASSPHRASE)
|
||||
|
||||
val viewModel = createViewModel()
|
||||
|
||||
viewModel.test().assertState(aViewState(
|
||||
hasPassphrase = true,
|
||||
step = SharedSecureStorageViewState.Step.EnterPassphrase
|
||||
))
|
||||
runBlockingTest {
|
||||
givenKey(KEY_INFO_WITH_PASSPHRASE)
|
||||
val viewModel = createViewModel()
|
||||
viewModel
|
||||
.test(this)
|
||||
.assertState(aViewState(
|
||||
hasPassphrase = true,
|
||||
step = SharedSecureStorageViewState.Step.EnterPassphrase
|
||||
))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a key info without passphrase when initialising then step is EnterKey`() {
|
||||
givenKey(KEY_INFO_WITHOUT_PASSPHRASE)
|
||||
runBlockingTest {
|
||||
givenKey(KEY_INFO_WITHOUT_PASSPHRASE)
|
||||
|
||||
val viewModel = createViewModel()
|
||||
val viewModel = createViewModel()
|
||||
|
||||
viewModel.test().assertState(aViewState(
|
||||
hasPassphrase = false,
|
||||
step = SharedSecureStorageViewState.Step.EnterKey
|
||||
))
|
||||
viewModel
|
||||
.test(this)
|
||||
.assertState(aViewState(
|
||||
hasPassphrase = false,
|
||||
step = SharedSecureStorageViewState.Step.EnterKey
|
||||
))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given on EnterKey step when going back then dismisses`() {
|
||||
givenKey(KEY_INFO_WITHOUT_PASSPHRASE)
|
||||
runBlockingTest {
|
||||
givenKey(KEY_INFO_WITHOUT_PASSPHRASE)
|
||||
|
||||
val viewModel = createViewModel()
|
||||
val test = viewModel.test()
|
||||
|
||||
viewModel.handle(SharedSecureStorageAction.Back)
|
||||
|
||||
test.assertEvents(SharedSecureStorageViewEvent.Dismiss)
|
||||
val viewModel = createViewModel()
|
||||
val test = viewModel.test(this)
|
||||
viewModel.handle(SharedSecureStorageAction.Back)
|
||||
test
|
||||
.assertEvents(SharedSecureStorageViewEvent.Dismiss)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given on passphrase step when using key then step is EnterKey`() {
|
||||
givenKey(KEY_INFO_WITH_PASSPHRASE)
|
||||
val viewModel = createViewModel()
|
||||
val test = viewModel.test()
|
||||
runBlockingTest {
|
||||
givenKey(KEY_INFO_WITH_PASSPHRASE)
|
||||
val viewModel = createViewModel()
|
||||
val test = viewModel.test(this)
|
||||
|
||||
viewModel.handle(SharedSecureStorageAction.UseKey)
|
||||
viewModel.handle(SharedSecureStorageAction.UseKey)
|
||||
|
||||
test.assertState(aViewState(
|
||||
hasPassphrase = true,
|
||||
step = SharedSecureStorageViewState.Step.EnterKey
|
||||
))
|
||||
test
|
||||
.assertState(aViewState(
|
||||
hasPassphrase = true,
|
||||
step = SharedSecureStorageViewState.Step.EnterKey
|
||||
))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given a key info with passphrase and on EnterKey step when going back then step is EnterPassphrase`() {
|
||||
givenKey(KEY_INFO_WITH_PASSPHRASE)
|
||||
val viewModel = createViewModel()
|
||||
val test = viewModel.test()
|
||||
runBlockingTest {
|
||||
givenKey(KEY_INFO_WITH_PASSPHRASE)
|
||||
val viewModel = createViewModel()
|
||||
val test = viewModel.test(this)
|
||||
|
||||
viewModel.handle(SharedSecureStorageAction.UseKey)
|
||||
viewModel.handle(SharedSecureStorageAction.Back)
|
||||
viewModel.handle(SharedSecureStorageAction.UseKey)
|
||||
viewModel.handle(SharedSecureStorageAction.Back)
|
||||
|
||||
test.assertState(aViewState(
|
||||
hasPassphrase = true,
|
||||
step = SharedSecureStorageViewState.Step.EnterPassphrase
|
||||
))
|
||||
test
|
||||
.assertState(aViewState(
|
||||
hasPassphrase = true,
|
||||
step = SharedSecureStorageViewState.Step.EnterPassphrase
|
||||
))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given on passphrase step when going back then dismisses`() {
|
||||
givenKey(KEY_INFO_WITH_PASSPHRASE)
|
||||
val viewModel = createViewModel()
|
||||
val test = viewModel.test()
|
||||
runBlockingTest {
|
||||
givenKey(KEY_INFO_WITH_PASSPHRASE)
|
||||
val viewModel = createViewModel()
|
||||
val test = viewModel.test(this)
|
||||
|
||||
viewModel.handle(SharedSecureStorageAction.Back)
|
||||
viewModel.handle(SharedSecureStorageAction.Back)
|
||||
|
||||
test.assertEvents(SharedSecureStorageViewEvent.Dismiss)
|
||||
test
|
||||
.assertEvents(SharedSecureStorageViewEvent.Dismiss)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createViewModel(): SharedSecureStorageViewModel {
|
||||
|
|
|
@ -20,27 +20,33 @@ import com.airbnb.mvrx.MavericksState
|
|||
import im.vector.app.core.platform.VectorViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
import io.reactivex.observers.TestObserver
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.amshove.kluent.shouldBeEqualTo
|
||||
|
||||
fun String.trimIndentOneLine() = trimIndent().replace("\n", "")
|
||||
|
||||
fun <S : MavericksState, VA : VectorViewModelAction, VE : VectorViewEvents> VectorViewModel<S, VA, VE>.test(): ViewModelTest<S, VE> {
|
||||
fun <S : MavericksState, VA : VectorViewModelAction, VE : VectorViewEvents> VectorViewModel<S, VA, VE>.test(coroutineScope: CoroutineScope): ViewModelTest<S, VE> {
|
||||
val state = { com.airbnb.mvrx.withState(this) { it } }
|
||||
//val viewEvents = viewEvents.stream().test()
|
||||
return ViewModelTest(state)
|
||||
val viewEvents = viewEvents.stream().test(coroutineScope)
|
||||
return ViewModelTest(state, viewEvents)
|
||||
}
|
||||
|
||||
class ViewModelTest<S, VE>(
|
||||
val state: () -> S,
|
||||
//val viewEvents: TestObserver<VE>
|
||||
val viewEvents: FlowTestObserver<VE>
|
||||
) {
|
||||
|
||||
fun assertEvents(vararg expected: VE) {
|
||||
//viewEvents.assertValues(*expected)
|
||||
fun assertEvents(vararg expected: VE): ViewModelTest<S,VE> {
|
||||
viewEvents.assertValues(*expected)
|
||||
return this
|
||||
}
|
||||
|
||||
fun assertState(expected: S) {
|
||||
fun assertState(expected: S): ViewModelTest<S,VE> {
|
||||
state() shouldBeEqualTo expected
|
||||
return this
|
||||
}
|
||||
|
||||
fun finish(){
|
||||
viewEvents.finish()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.test
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import org.junit.Assert.assertEquals
|
||||
|
||||
fun <T> Flow<T>.test(scope: CoroutineScope): FlowTestObserver<T> {
|
||||
return FlowTestObserver(scope, this)
|
||||
}
|
||||
|
||||
class FlowTestObserver<T>(
|
||||
scope: CoroutineScope,
|
||||
flow: Flow<T>
|
||||
) {
|
||||
private val values = mutableListOf<T>()
|
||||
private val job: Job = flow
|
||||
.onEach {
|
||||
values.add(it)
|
||||
}.launchIn(scope)
|
||||
|
||||
fun assertNoValues(): FlowTestObserver<T> {
|
||||
assertEquals(emptyList<T>(), this.values)
|
||||
return this
|
||||
}
|
||||
|
||||
fun assertValues(vararg values: T): FlowTestObserver<T> {
|
||||
assertEquals(values.toList(), this.values)
|
||||
return this
|
||||
}
|
||||
|
||||
fun finish() {
|
||||
job.cancel()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue