From b87abdabfade457527071d54bd107daa243c962b Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Mon, 29 Jun 2026 12:49:35 -0400 Subject: [PATCH] Improve PIN loading spinners in regV5. --- .../pincreation/PinCreationViewModel.kt | 6 +++--- .../PinEntryForRegistrationLockViewModel.kt | 21 +++++++++---------- .../pinentry/PinEntryForSmsBypassViewModel.kt | 17 +++++++-------- .../PinEntryForSvrRestoreViewModel.kt | 17 +++++++-------- .../pincreation/PinCreationViewModelTest.kt | 2 ++ ...inEntryForRegistrationLockViewModelTest.kt | 10 +++++++++ .../PinEntryForSmsBypassViewModelTest.kt | 11 ++++++++++ .../PinEntryForSvrRestoreViewModelTest.kt | 9 ++++++++ 8 files changed, 61 insertions(+), 32 deletions(-) diff --git a/feature/registration/src/main/java/org/signal/registration/screens/pincreation/PinCreationViewModel.kt b/feature/registration/src/main/java/org/signal/registration/screens/pincreation/PinCreationViewModel.kt index 8b9b0c65b9..e6a44b3218 100644 --- a/feature/registration/src/main/java/org/signal/registration/screens/pincreation/PinCreationViewModel.kt +++ b/feature/registration/src/main/java/org/signal/registration/screens/pincreation/PinCreationViewModel.kt @@ -67,9 +67,9 @@ class PinCreationViewModel( else -> { Log.d(TAG, "[PinSubmitted] Confirmation PIN matched.") - _state.value = state.copy(pinMismatch = false, loading = true) - val result = applyPinSubmitted(state, event.pin) - _state.value = result.copy(loading = false) + val loadingState = state.copy(pinMismatch = false, loading = true) + _state.value = loadingState + _state.value = applyPinSubmitted(loadingState, event.pin) } } } diff --git a/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForRegistrationLockViewModel.kt b/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForRegistrationLockViewModel.kt index 997d142c51..0be254815a 100644 --- a/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForRegistrationLockViewModel.kt +++ b/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForRegistrationLockViewModel.kt @@ -61,10 +61,9 @@ class PinEntryForRegistrationLockViewModel( suspend fun applyEvent(state: PinEntryState, event: PinEntryScreenEvents, parentEventEmitter: (RegistrationFlowEvent) -> Unit, stateEmitter: (PinEntryState) -> Unit) { when (event) { is PinEntryScreenEvents.PinEntered -> { - var localState = state.copy(loading = true) + val localState = state.copy(loading = true) stateEmitter(localState) - localState = applyPinEntered(localState, event, parentEventEmitter) - stateEmitter(localState.copy(loading = false)) + stateEmitter(applyPinEntered(localState, event, parentEventEmitter)) } is PinEntryScreenEvents.Skip -> { handleSkip() @@ -92,7 +91,7 @@ class PinEntryForRegistrationLockViewModel( return when (val error = restoreResult.error) { is NetworkController.RestoreMasterKeyError.WrongPin -> { Log.w(TAG, "[PinEntered] Wrong PIN. Tries remaining: ${error.triesRemaining}") - state.copy(triesRemaining = error.triesRemaining) + state.copy(loading = false, triesRemaining = error.triesRemaining) } is NetworkController.RestoreMasterKeyError.NoDataFound -> { Log.w(TAG, "[PinEntered] No SVR data found. Account is locked.") @@ -103,11 +102,11 @@ class PinEntryForRegistrationLockViewModel( } is RequestResult.RetryableNetworkError -> { Log.w(TAG, "[PinEntered] Network error when restoring master key.", restoreResult.networkError) - return state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) + return state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) } is RequestResult.ApplicationError -> { Log.w(TAG, "[PinEntered] Application error when restoring master key.", restoreResult.cause) - return state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) + return state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) } } @@ -157,15 +156,15 @@ class PinEntryForRegistrationLockViewModel( } is NetworkController.RegisterAccountError.RateLimited -> { Log.w(TAG, "[PinEntered] Rate limited when registering. Retry After: ${error.retryAfter}") - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.RateLimited(error.retryAfter)) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.RateLimited(error.retryAfter)) } is NetworkController.RegisterAccountError.InvalidRequest -> { Log.w(TAG, "[PinEntered] Invalid request when registering: ${error.message}") - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) } is NetworkController.RegisterAccountError.DeviceTransferPossible -> { Log.w(TAG, "[PinEntered] Device transfer possible. This shouldn't happen when skipDeviceTransfer is true.") - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) } is NetworkController.RegisterAccountError.RegistrationRecoveryPasswordIncorrect -> { Log.w(TAG, "[PinEntered] Registration recovery password incorrect: ${error.message}") @@ -176,11 +175,11 @@ class PinEntryForRegistrationLockViewModel( } is RequestResult.RetryableNetworkError -> { Log.w(TAG, "[PinEntered] Network error when registering.", registerResult.networkError) - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) } is RequestResult.ApplicationError -> { Log.w(TAG, "[PinEntered] Application error when registering.", registerResult.cause) - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) } } } diff --git a/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForSmsBypassViewModel.kt b/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForSmsBypassViewModel.kt index 0ff7c89607..2f7e5bdce7 100644 --- a/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForSmsBypassViewModel.kt +++ b/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForSmsBypassViewModel.kt @@ -68,10 +68,9 @@ class PinEntryForSmsBypassViewModel( ) { when (event) { is PinEntryScreenEvents.PinEntered -> { - var localState = state.copy(loading = true) + val localState = state.copy(loading = true) stateEmitter(localState) - localState = applyPinEntered(localState, event, parentEventEmitter) - stateEmitter(localState.copy(loading = false)) + stateEmitter(applyPinEntered(localState, event, parentEventEmitter)) } is PinEntryScreenEvents.Skip -> { handleSkip() @@ -112,7 +111,7 @@ class PinEntryForSmsBypassViewModel( when (val error = result.error) { is NetworkController.RestoreMasterKeyError.WrongPin -> { Log.w(TAG, "[PinEntered] Wrong PIN. Tries remaining: ${error.triesRemaining}") - state.copy(triesRemaining = error.triesRemaining) + state.copy(loading = false, triesRemaining = error.triesRemaining) } is NetworkController.RestoreMasterKeyError.NoDataFound -> { Log.w(TAG, "[PinEntered] No SVR data found for sms-bypass credential. Marking RRP as invalid and navigating back.") @@ -124,11 +123,11 @@ class PinEntryForSmsBypassViewModel( } is RequestResult.RetryableNetworkError -> { Log.w(TAG, "[PinEntered] Network error when restoring master key (sms-bypass).", result.networkError) - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) } is RequestResult.ApplicationError -> { Log.w(TAG, "[PinEntered] Application error when restoring master key (sms-bypass).", result.cause) - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) } } } @@ -157,10 +156,10 @@ class PinEntryForSmsBypassViewModel( state } is RequestResult.RetryableNetworkError -> { - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) } is RequestResult.ApplicationError -> { - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) } is RequestResult.NonSuccess -> { when (val error = result.error) { @@ -177,7 +176,7 @@ class PinEntryForSmsBypassViewModel( } is NetworkController.RegisterAccountError.RateLimited -> { Log.w(TAG, "[Register] Rate limited (retryAfter: ${error.retryAfter}).") - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.RateLimited(error.retryAfter)) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.RateLimited(error.retryAfter)) } is NetworkController.RegisterAccountError.RegistrationLock -> { if (provideRegistrationLock) { diff --git a/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForSvrRestoreViewModel.kt b/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForSvrRestoreViewModel.kt index e78f3cefdf..94f13f1d55 100644 --- a/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForSvrRestoreViewModel.kt +++ b/feature/registration/src/main/java/org/signal/registration/screens/pinentry/PinEntryForSvrRestoreViewModel.kt @@ -64,10 +64,9 @@ class PinEntryForSvrRestoreViewModel( ) { when (event) { is PinEntryScreenEvents.PinEntered -> { - var localState = state.copy(loading = true) + val localState = state.copy(loading = true) stateEmitter(localState) - localState = applyPinEntered(localState, event, parentEventEmitter) - stateEmitter(localState.copy(loading = false)) + stateEmitter(applyPinEntered(localState, event, parentEventEmitter)) } is PinEntryScreenEvents.Skip -> { handleSkip() @@ -114,10 +113,10 @@ class PinEntryForSvrRestoreViewModel( } } is RequestResult.RetryableNetworkError -> { - return state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) + return state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) } is RequestResult.ApplicationError -> { - return state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) + return state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) } } @@ -134,21 +133,21 @@ class PinEntryForSvrRestoreViewModel( when (val error = result.error) { is NetworkController.RestoreMasterKeyError.WrongPin -> { Log.w(TAG, "[PinEntered] Wrong PIN. Tries remaining: ${error.triesRemaining}") - state.copy(triesRemaining = error.triesRemaining) + state.copy(loading = false, triesRemaining = error.triesRemaining) } is NetworkController.RestoreMasterKeyError.NoDataFound -> { Log.w(TAG, "[PinEntered] No SVR data found. Prompting user to create a new PIN.") - state.copy(showNoDataToRestoreDialog = true) + state.copy(loading = false, showNoDataToRestoreDialog = true) } } } is RequestResult.RetryableNetworkError -> { Log.w(TAG, "[PinEntered] Network error when restoring master key.", result.networkError) - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.NetworkError) } is RequestResult.ApplicationError -> { Log.w(TAG, "[PinEntered] Application error when restoring master key.", result.cause) - state.copy(oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) + state.copy(loading = false, oneTimeEvent = PinEntryState.OneTimeEvent.UnknownError) } } } diff --git a/feature/registration/src/test/java/org/signal/registration/screens/pincreation/PinCreationViewModelTest.kt b/feature/registration/src/test/java/org/signal/registration/screens/pincreation/PinCreationViewModelTest.kt index f10ff08c7a..14e9aa28fa 100644 --- a/feature/registration/src/test/java/org/signal/registration/screens/pincreation/PinCreationViewModelTest.kt +++ b/feature/registration/src/test/java/org/signal/registration/screens/pincreation/PinCreationViewModelTest.kt @@ -125,6 +125,7 @@ class PinCreationViewModelTest { @Test fun `matching confirmation PIN with valid AEP and successful SVR backup hands off to finishRegistrationOrCreateProfile`() = runTest(testDispatcher) { + val states = collectStates() val aep = AccountEntropyPool.generate() val confirmState = PinCreationState(accountEntropyPool = aep, isConfirmEnabled = true, firstPin = "123456") @@ -135,6 +136,7 @@ class PinCreationViewModelTest { coVerify { mockRepository.setRestoreDecision(RestoreDecision.NEW_ACCOUNT) } coVerify { mockRepository.finishRegistrationOrCreateProfile(parentEventEmitter, any()) } + assertThat(states.last().loading).isTrue() } // ==================== PinSubmitted Missing AEP Test ==================== diff --git a/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForRegistrationLockViewModelTest.kt b/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForRegistrationLockViewModelTest.kt index 2584cf2c57..57a842fc0d 100644 --- a/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForRegistrationLockViewModelTest.kt +++ b/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForRegistrationLockViewModelTest.kt @@ -86,6 +86,7 @@ class PinEntryForRegistrationLockViewModelTest { assertThat(emittedParentEvents[0]).isInstanceOf() assertThat(emittedParentEvents[1]).isInstanceOf() coVerify { mockRepository.finishRegistrationOrCreateProfile(parentEventEmitter, any()) } + assertThat(emittedStates.last().loading).isEqualTo(true) } @Test @@ -102,6 +103,7 @@ class PinEntryForRegistrationLockViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().triesRemaining).isEqualTo(triesRemaining) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -122,6 +124,7 @@ class PinEntryForRegistrationLockViewModelTest { .isInstanceOf() .prop(RegistrationRoute.AccountLocked::timeRemainingMs) .isEqualTo(testTimeRemaining) + assertThat(emittedStates.last().loading).isEqualTo(true) } @Test @@ -135,6 +138,7 @@ class PinEntryForRegistrationLockViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.NetworkError) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -148,6 +152,7 @@ class PinEntryForRegistrationLockViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.UnknownError) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -233,6 +238,7 @@ class PinEntryForRegistrationLockViewModelTest { .isInstanceOf() .prop(PinEntryState.OneTimeEvent.RateLimited::retryAfter) .isEqualTo(retryAfter) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -252,6 +258,7 @@ class PinEntryForRegistrationLockViewModelTest { assertThat(emittedParentEvents).hasSize(1) assertThat(emittedParentEvents[0]).isInstanceOf() assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.UnknownError) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -271,6 +278,7 @@ class PinEntryForRegistrationLockViewModelTest { assertThat(emittedParentEvents).hasSize(1) assertThat(emittedParentEvents[0]).isInstanceOf() assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.UnknownError) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -288,6 +296,7 @@ class PinEntryForRegistrationLockViewModelTest { assertThat(emittedParentEvents).hasSize(1) assertThat(emittedParentEvents[0]).isInstanceOf() assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.NetworkError) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -305,6 +314,7 @@ class PinEntryForRegistrationLockViewModelTest { assertThat(emittedParentEvents).hasSize(1) assertThat(emittedParentEvents[0]).isInstanceOf() assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.UnknownError) + assertThat(emittedStates.last().loading).isEqualTo(false) } // ==================== Skip Tests ==================== diff --git a/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForSmsBypassViewModelTest.kt b/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForSmsBypassViewModelTest.kt index a61e71bc08..4f2e192c5b 100644 --- a/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForSmsBypassViewModelTest.kt +++ b/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForSmsBypassViewModelTest.kt @@ -79,6 +79,7 @@ class PinEntryForSmsBypassViewModelTest { assertThat(emittedParentEvents).hasSize(1) assertThat(emittedParentEvents[0]).isInstanceOf() coVerify { mockRepository.finishRegistrationOrCreateProfile(parentEventEmitter, any()) } + assertThat(emittedStates.last().loading).isEqualTo(true) } @Test @@ -110,6 +111,7 @@ class PinEntryForSmsBypassViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().triesRemaining).isEqualTo(triesRemaining) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -126,6 +128,7 @@ class PinEntryForSmsBypassViewModelTest { assertThat(emittedParentEvents).hasSize(2) assertThat(emittedParentEvents[0]).isEqualTo(RegistrationFlowEvent.RecoveryPasswordInvalid) assertThat(emittedParentEvents[1]).isEqualTo(RegistrationFlowEvent.NavigateBack) + assertThat(emittedStates.last().loading).isEqualTo(true) } @Test @@ -139,6 +142,7 @@ class PinEntryForSmsBypassViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.NetworkError) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -152,6 +156,7 @@ class PinEntryForSmsBypassViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.UnknownError) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -162,6 +167,7 @@ class PinEntryForSmsBypassViewModelTest { assertThat(emittedParentEvents).hasSize(1) assertThat(emittedParentEvents[0]).isEqualTo(RegistrationFlowEvent.ResetState) + assertThat(emittedStates.last().loading).isEqualTo(true) } // ==================== Registration Error Tests ==================== @@ -181,6 +187,7 @@ class PinEntryForSmsBypassViewModelTest { assertThat(emittedParentEvents).hasSize(1) assertThat(emittedParentEvents[0]).isInstanceOf() assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.NetworkError) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -198,6 +205,7 @@ class PinEntryForSmsBypassViewModelTest { assertThat(emittedParentEvents).hasSize(1) assertThat(emittedParentEvents[0]).isInstanceOf() assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.UnknownError) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -217,6 +225,7 @@ class PinEntryForSmsBypassViewModelTest { assertThat(emittedParentEvents).hasSize(2) assertThat(emittedParentEvents[0]).isInstanceOf() assertThat(emittedParentEvents[1]).isEqualTo(RegistrationFlowEvent.ResetState) + assertThat(emittedStates.last().loading).isEqualTo(true) } @Test @@ -260,6 +269,7 @@ class PinEntryForSmsBypassViewModelTest { .isInstanceOf() .prop(PinEntryState.OneTimeEvent.RateLimited::retryAfter) .isEqualTo(retryAfter) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -283,6 +293,7 @@ class PinEntryForSmsBypassViewModelTest { assertThat(emittedParentEvents).hasSize(1) assertThat(emittedParentEvents[0]).isInstanceOf() coVerify { mockRepository.finishRegistrationOrCreateProfile(parentEventEmitter, any()) } + assertThat(emittedStates.last().loading).isEqualTo(true) } @Test diff --git a/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForSvrRestoreViewModelTest.kt b/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForSvrRestoreViewModelTest.kt index d491468747..3e488b639a 100644 --- a/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForSvrRestoreViewModelTest.kt +++ b/feature/registration/src/test/java/org/signal/registration/screens/pinentry/PinEntryForSvrRestoreViewModelTest.kt @@ -78,6 +78,7 @@ class PinEntryForSvrRestoreViewModelTest { assertThat(emittedParentEvents[0]).isInstanceOf() coVerify { mockRepository.setRestoreDecision(RestoreDecision.COMPLETED) } coVerify { mockRepository.finishRegistrationOrCreateProfile(parentEventEmitter, any()) } + assertThat(emittedStates.last().loading).isEqualTo(true) } // ==================== GetSvrCredentials Error Tests ==================== @@ -95,6 +96,7 @@ class PinEntryForSvrRestoreViewModelTest { assertThat(emittedParentEvents).hasSize(1) assertThat(emittedParentEvents.first()).isEqualTo(RegistrationFlowEvent.ResetState) + assertThat(emittedStates.last().loading).isEqualTo(true) } @Test @@ -110,6 +112,7 @@ class PinEntryForSvrRestoreViewModelTest { assertThat(emittedParentEvents).hasSize(1) assertThat(emittedParentEvents.first()).isEqualTo(RegistrationFlowEvent.ResetState) + assertThat(emittedStates.last().loading).isEqualTo(true) } @Test @@ -123,6 +126,7 @@ class PinEntryForSvrRestoreViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.NetworkError) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -136,6 +140,7 @@ class PinEntryForSvrRestoreViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.UnknownError) + assertThat(emittedStates.last().loading).isEqualTo(false) } // ==================== RestoreMasterKey Error Tests ==================== @@ -160,6 +165,7 @@ class PinEntryForSvrRestoreViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().triesRemaining).isEqualTo(triesRemaining) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -181,6 +187,7 @@ class PinEntryForSvrRestoreViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().showNoDataToRestoreDialog).isEqualTo(true) + assertThat(emittedStates.last().loading).isEqualTo(false) } // ==================== No Data To Restore Dialog Tests ==================== @@ -226,6 +233,7 @@ class PinEntryForSvrRestoreViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.NetworkError) + assertThat(emittedStates.last().loading).isEqualTo(false) } @Test @@ -245,6 +253,7 @@ class PinEntryForSvrRestoreViewModelTest { assertThat(emittedParentEvents).hasSize(0) assertThat(emittedStates.last().oneTimeEvent).isEqualTo(PinEntryState.OneTimeEvent.UnknownError) + assertThat(emittedStates.last().loading).isEqualTo(false) } // ==================== Skip Tests ====================