test(auth): ForgotPasswordViewModelTest — typed exception + blank-email coverage

This commit is contained in:
null 2026-07-01 01:50:46 -05:00
parent 1a6cdaa078
commit f47fa3cdbd
1 changed files with 89 additions and 0 deletions

View File

@ -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<Unit>, 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)
}
}