diff --git a/app/src/test/java/com/github/swent/echo/fakes/FakeAuthenticationService.kt b/app/src/test/java/com/github/swent/echo/fakes/FakeAuthenticationService.kt new file mode 100644 index 000000000..071f57962 --- /dev/null +++ b/app/src/test/java/com/github/swent/echo/fakes/FakeAuthenticationService.kt @@ -0,0 +1,43 @@ +package com.github.swent.echo.fakes + +import com.github.swent.echo.authentication.AuthenticationResult +import com.github.swent.echo.authentication.AuthenticationService +import java.util.concurrent.CompletableFuture +import kotlinx.coroutines.future.await + +/** A fake implementation of the authentication service. */ +class FakeAuthenticationService : AuthenticationService { + private lateinit var signedInResult: CompletableFuture + + /** The user ID to return when [getCurrentUserID] is called. */ + var userID: String? = null + + /** + * Completes the current signing operation with the given result. Make sure to call this method + * after calling [signIn], [signUp], or [signOut]. + * + * @param result The result of the signing operation. + */ + fun completeSigningOperation(result: AuthenticationResult) { + signedInResult.complete(result) + } + + override suspend fun signIn(email: String, password: String): AuthenticationResult { + signedInResult = CompletableFuture() + return signedInResult.await() + } + + override suspend fun signUp(email: String, password: String): AuthenticationResult { + signedInResult = CompletableFuture() + return signedInResult.await() + } + + override suspend fun signOut(): AuthenticationResult { + signedInResult = CompletableFuture() + return signedInResult.await() + } + + override suspend fun getCurrentUserID(): String? { + return userID + } +} diff --git a/app/src/test/java/com/github/swent/echo/viewmodels/authentication/LoginViewModelTest.kt b/app/src/test/java/com/github/swent/echo/viewmodels/authentication/LoginViewModelTest.kt new file mode 100644 index 000000000..05bc8d925 --- /dev/null +++ b/app/src/test/java/com/github/swent/echo/viewmodels/authentication/LoginViewModelTest.kt @@ -0,0 +1,58 @@ +package com.github.swent.echo.viewmodels.authentication + +import com.github.swent.echo.authentication.AuthenticationResult +import com.github.swent.echo.fakes.FakeAuthenticationService +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.test.setMain +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test + +@OptIn(ExperimentalCoroutinesApi::class) +class LoginViewModelTest { + private lateinit var fakeAuthenticationService: FakeAuthenticationService + private lateinit var viewModel: LoginViewModel + + companion object { + private const val EMAIL = "test@email.com" + private const val PASSWORD = "password" + } + + @Before + fun setUp() { + fakeAuthenticationService = FakeAuthenticationService() + viewModel = LoginViewModel(fakeAuthenticationService) + } + + @Test + fun `state should be signed out when created`() { + assertEquals(AuthenticationState.SignedOut, viewModel.state.value) + } + + @Test + fun `login should return success when successful`() = runTest { + val testDispatcher = UnconfinedTestDispatcher(testScheduler) + Dispatchers.setMain(testDispatcher) + + viewModel.login(EMAIL, PASSWORD) + assertEquals(AuthenticationState.SigningIn, viewModel.state.value) + fakeAuthenticationService.completeSigningOperation(AuthenticationResult.Success) + assertEquals(AuthenticationState.SignedIn, viewModel.state.value) + } + + @Test + fun `login should return error when failed`() = runTest { + val testDispatcher = UnconfinedTestDispatcher(testScheduler) + Dispatchers.setMain(testDispatcher) + + viewModel.login(EMAIL, PASSWORD) + assertEquals(AuthenticationState.SigningIn, viewModel.state.value) + fakeAuthenticationService.completeSigningOperation( + AuthenticationResult.Error("Error message") + ) + assertEquals(AuthenticationState.Error("Error message"), viewModel.state.value) + } +}