-
-
Save valokafor/a8f8e0a769bc96fc9793c3fa531b6a18 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.theozgurr.apparchitecture.ui.register | |
import androidx.compose.animation.ExperimentalAnimationApi | |
import androidx.compose.ui.ExperimentalComposeUiApi | |
import androidx.compose.ui.test.assertIsDisplayed | |
import androidx.compose.ui.test.junit4.createAndroidComposeRule | |
import androidx.compose.ui.test.onNodeWithTag | |
import androidx.compose.ui.test.onNodeWithText | |
import androidx.compose.ui.test.onRoot | |
import androidx.navigation.NavHostController | |
import androidx.navigation.compose.NavHost | |
import androidx.navigation.compose.composable | |
import androidx.navigation.compose.rememberNavController | |
import com.google.common.truth.Truth.assertThat | |
import com.theozgurr.apparchitecture.R | |
import com.theozgurr.apparchitecture.common.clickToTagOwner | |
import com.theozgurr.apparchitecture.common.saveScreenshot | |
import com.theozgurr.apparchitecture.common.typeInputToTextFieldWithTag | |
import com.theozgurr.apparchitecture.data.data_source.user.local.FakeUserLocalDataSourceImplAndroid | |
import com.theozgurr.apparchitecture.data.data_source.user.remote.FakeUserRemoteDataSourceGenericErrorAndroid | |
import com.theozgurr.apparchitecture.data.data_source.user.remote.FakeUserRemoteDataSourceLoadingAndroid | |
import com.theozgurr.apparchitecture.data.data_source.user.remote.FakeUserRemoteDataSourceNetworkErrorAndroid | |
import com.theozgurr.apparchitecture.data.data_source.user.remote.FakeUserRemoteDataSourceSuccessAndroid | |
import com.theozgurr.apparchitecture.domain.model.user.UserMapper | |
import com.theozgurr.apparchitecture.domain.use_case.user.local.InsertUserUseCase | |
import com.theozgurr.apparchitecture.domain.use_case.user.local.IsLocalUserExistUseCase | |
import com.theozgurr.apparchitecture.domain.use_case.user.local.UserLocalUseCases | |
import com.theozgurr.apparchitecture.domain.use_case.user.remote.RegisterUserUseCase | |
import com.theozgurr.apparchitecture.domain.use_case.user.remote.UserRemoteUseCases | |
import com.theozgurr.apparchitecture.domain.validation.registration.RegistrationValidator | |
import com.theozgurr.apparchitecture.ui.MainActivity | |
import com.theozgurr.apparchitecture.ui.Route | |
import com.theozgurr.apparchitecture.ui.components.TAG_LOADING_INDICATOR | |
import com.theozgurr.apparchitecture.ui.home.HomeScreen | |
import com.theozgurr.apparchitecture.ui.login.LoginScreen | |
import com.theozgurr.apparchitecture.ui.theme.AppArchitectureJetpackComposeUnitAndUITestingTheme | |
import dagger.hilt.android.testing.HiltAndroidRule | |
import dagger.hilt.android.testing.HiltAndroidTest | |
import kotlinx.coroutines.ExperimentalCoroutinesApi | |
import org.junit.Before | |
import org.junit.FixMethodOrder | |
import org.junit.Rule | |
import org.junit.Test | |
import org.junit.runners.MethodSorters | |
@ExperimentalComposeUiApi | |
@ExperimentalCoroutinesApi | |
@ExperimentalAnimationApi | |
@HiltAndroidTest | |
@FixMethodOrder(MethodSorters.NAME_ASCENDING) | |
class RegisterScreenTest { | |
@get:Rule(order = 0) | |
val hiltRule = HiltAndroidRule(this) | |
@get:Rule(order = 1) | |
val composeRule = createAndroidComposeRule<MainActivity>() | |
private lateinit var navController: NavHostController | |
private lateinit var registerViewModel: RegisterViewModel | |
private lateinit var fakeUserLocalDataSource: FakeUserLocalDataSourceImplAndroid | |
private lateinit var fakeUserRemoteDataSourceGenericErrorAndroid: FakeUserRemoteDataSourceGenericErrorAndroid | |
private lateinit var fakeUserRemoteDataSourceLoadingAndroid: FakeUserRemoteDataSourceLoadingAndroid | |
private lateinit var fakeUserRemoteDataSourceNetworkErrorAndroid: FakeUserRemoteDataSourceNetworkErrorAndroid | |
private lateinit var fakeUserRemoteDataSourceSuccessAndroid: FakeUserRemoteDataSourceSuccessAndroid | |
private lateinit var userLocalUseCases: UserLocalUseCases | |
private lateinit var userRemoteUseCases: UserRemoteUseCases | |
private lateinit var registerUserUseCase: RegisterUserUseCase | |
private lateinit var userMapper: UserMapper | |
private lateinit var registrationValidator: RegistrationValidator | |
@Before | |
fun setUp() { | |
hiltRule.inject() | |
fakeUserLocalDataSource = FakeUserLocalDataSourceImplAndroid() | |
fakeUserRemoteDataSourceGenericErrorAndroid = FakeUserRemoteDataSourceGenericErrorAndroid() | |
fakeUserRemoteDataSourceLoadingAndroid = FakeUserRemoteDataSourceLoadingAndroid() | |
fakeUserRemoteDataSourceNetworkErrorAndroid = FakeUserRemoteDataSourceNetworkErrorAndroid() | |
fakeUserRemoteDataSourceSuccessAndroid = FakeUserRemoteDataSourceSuccessAndroid() | |
userMapper = UserMapper() | |
registrationValidator = RegistrationValidator() | |
userLocalUseCases = UserLocalUseCases( | |
insertUserUseCase = InsertUserUseCase( | |
dataSource = fakeUserLocalDataSource, | |
mapper = userMapper | |
), | |
isLocalUserExistUseCase = IsLocalUserExistUseCase( | |
dataSource = fakeUserLocalDataSource | |
) | |
) | |
} | |
private fun initRegisterViewModelForGenericErrorCase() { | |
registerUserUseCase = RegisterUserUseCase( | |
dataSource = fakeUserRemoteDataSourceGenericErrorAndroid | |
) | |
initUserRemoteUseCases() | |
initRegisterViewModel() | |
} | |
private fun initRegisterViewModelForLoadingCase() { | |
registerUserUseCase = RegisterUserUseCase( | |
dataSource = fakeUserRemoteDataSourceLoadingAndroid | |
) | |
initUserRemoteUseCases() | |
initRegisterViewModel() | |
} | |
private fun initRegisterViewModelForNetworkErrorCase() { | |
registerUserUseCase = RegisterUserUseCase( | |
dataSource = fakeUserRemoteDataSourceNetworkErrorAndroid | |
) | |
initUserRemoteUseCases() | |
initRegisterViewModel() | |
} | |
private fun initRegisterViewModelForSuccessCase() { | |
registerUserUseCase = RegisterUserUseCase( | |
dataSource = fakeUserRemoteDataSourceSuccessAndroid | |
) | |
initUserRemoteUseCases() | |
initRegisterViewModel() | |
} | |
private fun initUserRemoteUseCases() { | |
userRemoteUseCases = UserRemoteUseCases( | |
registerUserUseCase = registerUserUseCase | |
) | |
} | |
private fun initRegisterViewModel() { | |
registerViewModel = RegisterViewModel( | |
userLocalUseCases = userLocalUseCases, | |
userRemoteUseCases = userRemoteUseCases, | |
registrationValidator = registrationValidator | |
) | |
} | |
private fun launchRegisterScreen() { | |
composeRule.setContent { | |
AppArchitectureJetpackComposeUnitAndUITestingTheme { | |
RegisterScreen( | |
registerViewModel = registerViewModel, | |
onNavigateToLoginScreen = {}, | |
onNavigateToHomeScreen = {} | |
) | |
} | |
} | |
} | |
private fun launchRegisterScreenWithNavGraph() { | |
composeRule.setContent { | |
AppArchitectureJetpackComposeUnitAndUITestingTheme { | |
navController = rememberNavController() | |
NavHost( | |
navController = navController, | |
startDestination = Route.Register.screen | |
) { | |
composable(route = Route.Register.screen) { | |
RegisterScreen( | |
registerViewModel = registerViewModel, | |
onNavigateToLoginScreen = { | |
navController.navigate( | |
route = Route.Login.screen | |
) | |
}, | |
onNavigateToHomeScreen = { | |
navController.navigate( | |
route = Route.Home.screen | |
) { | |
popUpTo(Route.Register.screen) { | |
inclusive = true | |
} | |
} | |
} | |
) | |
} | |
composable(route = Route.Login.screen) { | |
LoginScreen() | |
} | |
composable(route = Route.Home.screen) { | |
HomeScreen() | |
} | |
} | |
} | |
} | |
} | |
@Test | |
fun test_registration_registrationForm_isVisible() { | |
initRegisterViewModelForSuccessCase() | |
launchRegisterScreen() | |
with(composeRule) { | |
onNodeWithTag(TAG_REGISTRATION_FORM) | |
.assertIsDisplayed() | |
saveScreenshot( | |
fileNamePrefix = "registrationForm", | |
node = onRoot() | |
) | |
} | |
} | |
@Test | |
fun test_registration_returns_invalidEmail() { | |
initRegisterViewModelForSuccessCase() | |
launchRegisterScreen() | |
with(composeRule) { | |
val email = "invalid_email" | |
typeInputToTextFieldWithTag( | |
input = email, | |
tag = TAG_TEXT_FIELD_EMAIL | |
) | |
clickToTagOwner(TAG_BUTTON_REGISTER) | |
val invalidEmail = activity.getString(R.string.invalid_email) | |
onNodeWithText(invalidEmail) | |
.assertIsDisplayed() | |
} | |
} | |
@Test | |
fun test_registration_returns_invalidPassword() { | |
initRegisterViewModelForSuccessCase() | |
launchRegisterScreen() | |
with(composeRule) { | |
val email = "[email protected]" | |
val password = "123456" | |
typeInputToTextFieldWithTag( | |
input = email, | |
tag = TAG_TEXT_FIELD_EMAIL | |
) | |
typeInputToTextFieldWithTag( | |
input = password, | |
tag = TAG_TEXT_FIELD_PASSWORD | |
) | |
clickToTagOwner( | |
tag = TAG_BUTTON_REGISTER | |
) | |
val invalidPassword = activity.getString(R.string.invalid_password) | |
onNodeWithText(invalidPassword) | |
.assertIsDisplayed() | |
val passwordRequirements = activity.getString(R.string.password_requirements) | |
onNodeWithText(passwordRequirements) | |
.assertIsDisplayed() | |
saveScreenshot( | |
fileNamePrefix = "invalidPassword", | |
node = onRoot() | |
) | |
} | |
} | |
@Test | |
fun test_registration_returns_unselectedGender() { | |
initRegisterViewModelForSuccessCase() | |
launchRegisterScreen() | |
with(composeRule) { | |
val email = "[email protected]" | |
val password = "123456ab" | |
typeInputToTextFieldWithTag( | |
input = email, | |
tag = TAG_TEXT_FIELD_EMAIL | |
) | |
typeInputToTextFieldWithTag( | |
input = password, | |
tag = TAG_TEXT_FIELD_PASSWORD | |
) | |
clickToTagOwner( | |
tag = TAG_BUTTON_REGISTER | |
) | |
val selectYourGender = activity.getString(R.string.please_select_your_gender) | |
onNodeWithText(selectYourGender) | |
.assertIsDisplayed() | |
saveScreenshot( | |
fileNamePrefix = "unselectedGender", | |
node = onRoot() | |
) | |
} | |
} | |
@Test | |
fun test_registration_returns_loading() { | |
initRegisterViewModelForLoadingCase() | |
launchRegisterScreen() | |
with(composeRule) { | |
val email = "[email protected]" | |
val password = "123456ab" | |
val age = "24" | |
typeInputToTextFieldWithTag( | |
input = email, | |
tag = TAG_TEXT_FIELD_EMAIL | |
) | |
typeInputToTextFieldWithTag( | |
input = password, | |
tag = TAG_TEXT_FIELD_PASSWORD | |
) | |
typeInputToTextFieldWithTag( | |
input = age, | |
tag = TAG_TEXT_FIELD_AGE | |
) | |
clickToTagOwner( | |
tag = TAG_RADIO_BUTTON_FEMALE | |
) | |
clickToTagOwner( | |
tag = TAG_BUTTON_REGISTER | |
) | |
onNodeWithTag(TAG_REGISTRATION_FORM) | |
.assertDoesNotExist() | |
onNodeWithTag(TAG_LOADING_INDICATOR) | |
.assertIsDisplayed() | |
} | |
} | |
@Test | |
fun test_registration_returns_networkError() { | |
initRegisterViewModelForNetworkErrorCase() | |
launchRegisterScreen() | |
with(composeRule) { | |
val email = "[email protected]" | |
val password = "123456ab" | |
val age = "25" | |
typeInputToTextFieldWithTag( | |
input = email, | |
tag = TAG_TEXT_FIELD_EMAIL | |
) | |
typeInputToTextFieldWithTag( | |
input = password, | |
tag = TAG_TEXT_FIELD_PASSWORD | |
) | |
typeInputToTextFieldWithTag( | |
input = age, | |
tag = TAG_TEXT_FIELD_AGE | |
) | |
clickToTagOwner( | |
tag = TAG_RADIO_BUTTON_FEMALE | |
) | |
clickToTagOwner( | |
tag = TAG_BUTTON_REGISTER | |
) | |
onNodeWithTag(TAG_REGISTRATION_FORM) | |
.assertIsDisplayed() | |
onNodeWithTag(TAG_LOADING_INDICATOR) | |
.assertDoesNotExist() | |
val noInternetConnection = activity.getString(R.string.no_internet_connection) | |
onNodeWithText(noInternetConnection) | |
.assertIsDisplayed() | |
saveScreenshot( | |
fileNamePrefix = "networkError", | |
node = onRoot() | |
) | |
} | |
} | |
@Test | |
fun test_registration_returns_genericError() { | |
initRegisterViewModelForGenericErrorCase() | |
launchRegisterScreen() | |
with(composeRule) { | |
val email = "[email protected]" | |
val password = "123456ab" | |
val age = "25" | |
typeInputToTextFieldWithTag( | |
input = email, | |
tag = TAG_TEXT_FIELD_EMAIL | |
) | |
typeInputToTextFieldWithTag( | |
input = password, | |
tag = TAG_TEXT_FIELD_PASSWORD | |
) | |
typeInputToTextFieldWithTag( | |
input = age, | |
tag = TAG_TEXT_FIELD_AGE | |
) | |
clickToTagOwner( | |
tag = TAG_RADIO_BUTTON_FEMALE | |
) | |
clickToTagOwner( | |
tag = TAG_BUTTON_REGISTER | |
) | |
val requestFailed = activity.getString(R.string.request_failed) | |
onNodeWithText(requestFailed) | |
.assertIsDisplayed() | |
saveScreenshot( | |
fileNamePrefix = "genericError", | |
node = onRoot() | |
) | |
} | |
} | |
@Test | |
fun test_registration_returns_success_navigateToHomeScreen() { | |
initRegisterViewModelForSuccessCase() | |
launchRegisterScreenWithNavGraph() | |
with(composeRule) { | |
val email = "[email protected]" | |
val password = "123456ab" | |
val age = "25" | |
typeInputToTextFieldWithTag( | |
input = email, | |
tag = TAG_TEXT_FIELD_EMAIL | |
) | |
typeInputToTextFieldWithTag( | |
input = password, | |
tag = TAG_TEXT_FIELD_PASSWORD | |
) | |
typeInputToTextFieldWithTag( | |
input = age, | |
tag = TAG_TEXT_FIELD_AGE | |
) | |
clickToTagOwner( | |
tag = TAG_RADIO_BUTTON_FEMALE | |
) | |
clickToTagOwner( | |
tag = TAG_BUTTON_REGISTER | |
) | |
waitForIdle() | |
val route = navController.currentBackStackEntry?.destination?.route | |
assertThat(route).isEqualTo(Route.Home.screen) | |
} | |
} | |
@Test | |
fun test_registration_clickOrLoginText_navigateToLoginScreen() { | |
initRegisterViewModelForSuccessCase() | |
launchRegisterScreenWithNavGraph() | |
composeRule.clickToTagOwner( | |
tag = TAG_OR_LOGIN_TEXT | |
) | |
val route = navController.currentBackStackEntry?.destination?.route | |
assertThat(route).isEqualTo(Route.Login.screen) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment