Flow migration: add back some test

This commit is contained in:
ganfra 2021-10-26 18:09:07 +02:00
parent 8cf5b727e1
commit a9d192fa39
5 changed files with 138 additions and 52 deletions

View file

@ -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",

View file

@ -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"

View file

@ -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 {

View file

@ -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()
}
}

View file

@ -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()
}
}