diff --git a/app/src/test/java/app/closer/ui/auth/ForgotPasswordViewModelTest.kt b/app/src/test/java/app/closer/ui/auth/ForgotPasswordViewModelTest.kt new file mode 100644 index 00000000..d95b93c8 --- /dev/null +++ b/app/src/test/java/app/closer/ui/auth/ForgotPasswordViewModelTest.kt @@ -0,0 +1,89 @@ +package app.closer.ui.auth + +import app.closer.domain.repository.AuthRepository +import app.closer.domain.repository.PasswordResetException +import io.mockk.coEvery +import io.mockk.mockk +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.test.setMain +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test + +/** + * Verifies the "forgot password" outcomes are mapped from typed [PasswordResetException]s (not fragile + * message-string matching) to the right user-facing copy — including the Google-only case. + */ +@OptIn(ExperimentalCoroutinesApi::class) +class ForgotPasswordViewModelTest { + + private val dispatcher = StandardTestDispatcher() + private val authRepository: AuthRepository = mockk() + + @Before fun setUp() = Dispatchers.setMain(dispatcher) + @After fun tearDown() = Dispatchers.resetMain() + + private fun errorFor(result: Result, email: String = "sam@example.com"): String? { + coEvery { authRepository.sendPasswordResetEmail(email) } returns result + val vm = ForgotPasswordViewModel(authRepository) + vm.updateEmail(email) + vm.sendReset() + dispatcher.scheduler.advanceUntilIdle() + return vm.uiState.value.error + } + + @Test + fun `success flips to sent with no error`() = runTest(dispatcher) { + coEvery { authRepository.sendPasswordResetEmail("sam@example.com") } returns Result.success(Unit) + val vm = ForgotPasswordViewModel(authRepository) + vm.updateEmail("sam@example.com") + vm.sendReset() + advanceUntilIdle() + assertTrue(vm.uiState.value.sent) + assertNull(vm.uiState.value.error) + assertFalse(vm.uiState.value.isLoading) + } + + @Test + fun `no account maps to a friendly message`() = runTest(dispatcher) { + assertEquals( + "No account found with that email.", + errorFor(Result.failure(PasswordResetException.NoAccount())) + ) + } + + @Test + fun `invalid email maps to a friendly message`() = runTest(dispatcher) { + assertEquals( + "Please enter a valid email address.", + errorFor(Result.failure(PasswordResetException.InvalidEmail())) + ) + } + + @Test + fun `unknown failure falls back to its own message`() = runTest(dispatcher) { + assertEquals( + "Network down", + errorFor(Result.failure(RuntimeException("Network down"))) + ) + } + + @Test + fun `blank email is rejected without calling the repository`() = runTest(dispatcher) { + val vm = ForgotPasswordViewModel(authRepository) + vm.updateEmail(" ") + vm.sendReset() + advanceUntilIdle() + assertEquals("Please enter your email address.", vm.uiState.value.error) + assertFalse(vm.uiState.value.sent) + } +}