fixing view model tests not collecting flow results

- the switch from runBlockingTest to runTest means we need to provide a separate scope from the test in order to asynchronously collect the flow results
This commit is contained in:
Adam Brown 2022-03-22 17:01:34 +00:00
parent 012cdf4b4d
commit fdf3cc36ce
3 changed files with 28 additions and 26 deletions

View file

@ -51,7 +51,7 @@ class SharedSecureStorageViewModelTest {
givenKey(KEY_INFO_WITH_PASSPHRASE)
val viewModel = createViewModel()
viewModel
.test(this)
.test()
.assertState(aViewState(
hasPassphrase = true,
step = SharedSecureStorageViewState.Step.EnterPassphrase
@ -66,7 +66,7 @@ class SharedSecureStorageViewModelTest {
val viewModel = createViewModel()
viewModel
.test(this)
.test()
.assertState(aViewState(
hasPassphrase = false,
step = SharedSecureStorageViewState.Step.EnterKey
@ -79,7 +79,7 @@ class SharedSecureStorageViewModelTest {
givenKey(KEY_INFO_WITHOUT_PASSPHRASE)
val viewModel = createViewModel()
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(SharedSecureStorageAction.Back)
test
.assertEvents(SharedSecureStorageViewEvent.Dismiss)
@ -90,7 +90,7 @@ class SharedSecureStorageViewModelTest {
fun `given on passphrase step when using key then step is EnterKey`() = runTest {
givenKey(KEY_INFO_WITH_PASSPHRASE)
val viewModel = createViewModel()
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(SharedSecureStorageAction.UseKey)
@ -112,7 +112,7 @@ class SharedSecureStorageViewModelTest {
fun `given a key info with passphrase and on EnterKey step when going back then step is EnterPassphrase`() = runTest {
givenKey(KEY_INFO_WITH_PASSPHRASE)
val viewModel = createViewModel()
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(SharedSecureStorageAction.UseKey)
viewModel.handle(SharedSecureStorageAction.Back)
@ -139,7 +139,7 @@ class SharedSecureStorageViewModelTest {
fun `given on passphrase step when going back then dismisses`() = runTest {
givenKey(KEY_INFO_WITH_PASSPHRASE)
val viewModel = createViewModel()
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(SharedSecureStorageAction.Back)

View file

@ -83,7 +83,7 @@ class OnboardingViewModelTest {
@Test
fun `when handling PostViewEvent, then emits contents as view event`() = runTest {
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnTakeMeHome))
@ -96,7 +96,7 @@ class OnboardingViewModelTest {
fun `given supports changing display name, when handling PersonalizeProfile, then emits contents choose display name`() = runTest {
val initialState = initialState.copy(personalizationState = PersonalizationState(supportsChangingDisplayName = true, supportsChangingProfilePicture = false))
viewModel = createViewModel(initialState)
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.PersonalizeProfile)
@ -109,7 +109,7 @@ class OnboardingViewModelTest {
fun `given only supports changing profile picture, when handling PersonalizeProfile, then emits contents choose profile picture`() = runTest {
val initialState = initialState.copy(personalizationState = PersonalizationState(supportsChangingDisplayName = false, supportsChangingProfilePicture = true))
viewModel = createViewModel(initialState)
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.PersonalizeProfile)
@ -121,7 +121,7 @@ class OnboardingViewModelTest {
@Test
fun `when handling SignUp then sets sign mode to sign up and starts registration`() = runTest {
givenRegistrationResultFor(RegisterAction.StartRegistration, ANY_CONTINUING_REGISTRATION_RESULT)
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.UpdateSignMode(SignMode.SignUp))
@ -138,7 +138,7 @@ class OnboardingViewModelTest {
@Test
fun `given register action requires more steps, when handling action, then posts next steps`() = runTest {
val test = viewModel.test(this)
val test = viewModel.test()
givenRegistrationResultFor(A_LOADABLE_REGISTER_ACTION, ANY_CONTINUING_REGISTRATION_RESULT)
viewModel.handle(OnboardingAction.PostRegisterAction(A_LOADABLE_REGISTER_ACTION))
@ -155,7 +155,7 @@ class OnboardingViewModelTest {
@Test
fun `given register action is non loadable, when handling action, then posts next steps without loading`() = runTest {
val test = viewModel.test(this)
val test = viewModel.test()
givenRegistrationResultFor(A_NON_LOADABLE_REGISTER_ACTION, ANY_CONTINUING_REGISTRATION_RESULT)
viewModel.handle(OnboardingAction.PostRegisterAction(A_NON_LOADABLE_REGISTER_ACTION))
@ -168,7 +168,7 @@ class OnboardingViewModelTest {
@Test
fun `given register action ignores result, when handling action, then does nothing on success`() = runTest {
val test = viewModel.test(this)
val test = viewModel.test()
givenRegistrationResultFor(A_RESULT_IGNORED_REGISTER_ACTION, RegistrationResult.FlowResponse(AN_IGNORED_FLOW_RESULT))
viewModel.handle(OnboardingAction.PostRegisterAction(A_RESULT_IGNORED_REGISTER_ACTION))
@ -187,7 +187,7 @@ class OnboardingViewModelTest {
fun `when registering account, then updates state and emits account created event`() = runTest {
givenRegistrationResultFor(A_LOADABLE_REGISTER_ACTION, RegistrationResult.Success(fakeSession))
givenSuccessfullyCreatesAccount(A_HOMESERVER_CAPABILITIES)
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.PostRegisterAction(A_LOADABLE_REGISTER_ACTION))
@ -205,7 +205,7 @@ class OnboardingViewModelTest {
@Test
fun `given registration has started and has dummy step to do, when handling action, then ignores other steps and executes dummy`() = runTest {
givenSuccessfulRegistrationForStartAndDummySteps(missingStages = listOf(Stage.Dummy(mandatory = true)))
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.PostRegisterAction(A_LOADABLE_REGISTER_ACTION))
@ -224,7 +224,7 @@ class OnboardingViewModelTest {
fun `given changing profile picture is supported, when updating display name, then updates upstream user display name and moves to choose profile picture`() = runTest {
val personalisedInitialState = initialState.copy(personalizationState = PersonalizationState(supportsChangingProfilePicture = true))
viewModel = createViewModel(personalisedInitialState)
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
@ -239,7 +239,7 @@ class OnboardingViewModelTest {
fun `given changing profile picture is not supported, when updating display name, then updates upstream user display name and completes personalization`() = runTest {
val personalisedInitialState = initialState.copy(personalizationState = PersonalizationState(supportsChangingProfilePicture = false))
viewModel = createViewModel(personalisedInitialState)
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
@ -252,7 +252,7 @@ class OnboardingViewModelTest {
@Test
fun `given upstream failure, when handling display name update, then emits failure event`() = runTest {
val test = viewModel.test(this)
val test = viewModel.test()
fakeSession.fakeProfileService.givenSetDisplayNameErrors(AN_ERROR)
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
@ -269,7 +269,7 @@ class OnboardingViewModelTest {
@Test
fun `when handling profile picture selected, then updates selected picture state`() = runTest {
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.ProfilePictureSelected(fakeUri.instance))
@ -286,7 +286,7 @@ class OnboardingViewModelTest {
fun `given a selected picture, when handling save selected profile picture, then updates upstream avatar and completes personalization`() = runTest {
val initialStateWithPicture = givenPictureSelected(fakeUri.instance, A_PICTURE_FILENAME)
viewModel = createViewModel(initialStateWithPicture)
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.SaveSelectedProfilePicture)
@ -302,7 +302,7 @@ class OnboardingViewModelTest {
fakeSession.fakeProfileService.givenUpdateAvatarErrors(AN_ERROR)
val initialStateWithPicture = givenPictureSelected(fakeUri.instance, A_PICTURE_FILENAME)
viewModel = createViewModel(initialStateWithPicture)
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.SaveSelectedProfilePicture)
@ -314,7 +314,7 @@ class OnboardingViewModelTest {
@Test
fun `given no selected picture, when saving selected profile picture, then emits failure event`() = runTest {
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.SaveSelectedProfilePicture)
@ -326,7 +326,7 @@ class OnboardingViewModelTest {
@Test
fun `when handling profile skipped, then completes personalization`() = runTest {
val test = viewModel.test(this)
val test = viewModel.test()
viewModel.handle(OnboardingAction.UpdateProfilePictureSkipped)

View file

@ -21,12 +21,14 @@ import im.vector.app.core.platform.VectorViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.VectorViewModelAction
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
fun String.trimIndentOneLine() = trimIndent().replace("\n", "")
fun <S : MavericksState, VA : VectorViewModelAction, VE : VectorViewEvents> VectorViewModel<S, VA, VE>.test(coroutineScope: CoroutineScope): ViewModelTest<S, VE> {
val state = stateFlow.test(coroutineScope)
val viewEvents = viewEvents.stream().test(coroutineScope)
fun <S : MavericksState, VA : VectorViewModelAction, VE : VectorViewEvents> VectorViewModel<S, VA, VE>.test(): ViewModelTest<S, VE> {
val testResultCollectingScope = CoroutineScope(Dispatchers.Unconfined)
val state = stateFlow.test(testResultCollectingScope)
val viewEvents = viewEvents.stream().test(testResultCollectingScope)
return ViewModelTest(state, viewEvents)
}