diff --git a/app/src/main/java/org/openedx/app/di/ScreenModule.kt b/app/src/main/java/org/openedx/app/di/ScreenModule.kt index 4c3aa59cd..6ebcacf64 100644 --- a/app/src/main/java/org/openedx/app/di/ScreenModule.kt +++ b/app/src/main/java/org/openedx/app/di/ScreenModule.kt @@ -256,7 +256,7 @@ val screenModule = module { ) } - viewModel { (courseId: String) -> WhatsNewViewModel(courseId, get()) } + viewModel { (courseId: String?) -> WhatsNewViewModel(courseId, get()) } viewModel { HtmlUnitViewModel( get(), diff --git a/auth/src/main/java/org/openedx/auth/presentation/logistration/LogistrationFragment.kt b/auth/src/main/java/org/openedx/auth/presentation/logistration/LogistrationFragment.kt index 5c77688c3..529058cc6 100644 --- a/auth/src/main/java/org/openedx/auth/presentation/logistration/LogistrationFragment.kt +++ b/auth/src/main/java/org/openedx/auth/presentation/logistration/LogistrationFragment.kt @@ -25,13 +25,17 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview @@ -90,6 +94,7 @@ class LogistrationFragment : Fragment() { } } +@OptIn(ExperimentalComposeUiApi::class) @Composable private fun LogistrationScreen( onSearchClick: (String) -> Unit, @@ -105,6 +110,9 @@ private fun LogistrationScreen( Scaffold( scaffoldState = scaffoldState, modifier = Modifier + .semantics { + testTagsAsResourceId = true + } .fillMaxSize() .navigationBarsPadding(), backgroundColor = MaterialTheme.appColors.background @@ -135,17 +143,22 @@ private fun LogistrationScreen( text = stringResource(id = R.string.pre_auth_title), color = MaterialTheme.appColors.textPrimary, style = MaterialTheme.appTypography.headlineSmall, - modifier = Modifier.padding(bottom = 40.dp) + modifier = Modifier + .testTag("txt_screen_title") + .padding(bottom = 40.dp) ) val focusManager = LocalFocusManager.current Column(Modifier.padding(bottom = 8.dp)) { Text( - modifier = Modifier.padding(bottom = 10.dp), + modifier = Modifier + .testTag("txt_search_label") + .padding(bottom = 10.dp), style = MaterialTheme.appTypography.titleMedium, text = stringResource(id = R.string.pre_auth_search_title), ) SearchBar( modifier = Modifier + .testTag("tf_discovery_search") .fillMaxWidth() .height(48.dp), label = stringResource(id = R.string.pre_auth_search_hint), @@ -166,6 +179,7 @@ private fun LogistrationScreen( Text( modifier = Modifier + .testTag("txt_explore_all_courses") .padding(bottom = 32.dp) .noRippleClickable { onSearchClick("") diff --git a/auth/src/main/java/org/openedx/auth/presentation/restore/RestorePasswordFragment.kt b/auth/src/main/java/org/openedx/auth/presentation/restore/RestorePasswordFragment.kt index bd10b1092..dd530bfa0 100644 --- a/auth/src/main/java/org/openedx/auth/presentation/restore/RestorePasswordFragment.kt +++ b/auth/src/main/java/org/openedx/auth/presentation/restore/RestorePasswordFragment.kt @@ -35,13 +35,17 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Devices @@ -112,6 +116,7 @@ class RestorePasswordFragment : Fragment() { } } +@OptIn(ExperimentalComposeUiApi::class) @Composable private fun RestorePasswordScreen( windowSize: WindowSize, @@ -129,6 +134,9 @@ private fun RestorePasswordScreen( Scaffold( scaffoldState = scaffoldState, modifier = Modifier + .semantics { + testTagsAsResourceId = true + } .fillMaxSize() .navigationBarsPadding(), backgroundColor = MaterialTheme.appColors.background @@ -200,6 +208,7 @@ private fun RestorePasswordScreen( ) { Text( modifier = Modifier + .testTag("txt_screen_title") .fillMaxWidth(), text = stringResource(id = authR.string.auth_forgot_your_password), color = Color.White, @@ -216,8 +225,7 @@ private fun RestorePasswordScreen( } Surface( - modifier = Modifier - .fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), color = MaterialTheme.appColors.background, shape = MaterialTheme.appShapes.screenBackgroundShape ) { @@ -239,6 +247,7 @@ private fun RestorePasswordScreen( ) { Text( modifier = Modifier + .testTag("txt_forgot_password_title") .fillMaxWidth(), text = stringResource(id = authR.string.auth_forgot_your_password), style = MaterialTheme.appTypography.displaySmall, @@ -247,6 +256,7 @@ private fun RestorePasswordScreen( Spacer(Modifier.height(2.dp)) Text( modifier = Modifier + .testTag("txt_forgot_password_description") .fillMaxWidth(), text = stringResource(id = authR.string.auth_please_enter_your_log_in), style = MaterialTheme.appTypography.titleSmall, @@ -279,7 +289,7 @@ private fun RestorePasswordScreen( } } else { OpenEdXButton( - width = buttonWidth, + width = buttonWidth.testTag("btn_reset_password"), text = stringResource(id = authR.string.auth_reset_password), onClick = { onRestoreButtonClick(email) diff --git a/auth/src/main/java/org/openedx/auth/presentation/signin/compose/SignInView.kt b/auth/src/main/java/org/openedx/auth/presentation/signin/compose/SignInView.kt index efe82ca90..a0a1f3f82 100644 --- a/auth/src/main/java/org/openedx/auth/presentation/signin/compose/SignInView.kt +++ b/auth/src/main/java/org/openedx/auth/presentation/signin/compose/SignInView.kt @@ -37,12 +37,16 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation @@ -71,6 +75,7 @@ import org.openedx.core.ui.theme.appTypography import org.openedx.core.ui.windowSizeValue import org.openedx.core.R as coreR +@OptIn(ExperimentalComposeUiApi::class) @Composable internal fun LoginScreen( windowSize: WindowSize, @@ -84,6 +89,9 @@ internal fun LoginScreen( Scaffold( scaffoldState = scaffoldState, modifier = Modifier + .semantics { + testTagsAsResourceId = true + } .fillMaxSize() .navigationBarsPadding(), backgroundColor = MaterialTheme.appColors.background @@ -173,12 +181,15 @@ internal fun LoginScreen( .then(contentPaddings), ) { Text( + modifier = Modifier.testTag("txt_sign_in_title"), text = stringResource(id = coreR.string.core_sign_in), color = MaterialTheme.appColors.textPrimary, style = MaterialTheme.appTypography.displaySmall ) Text( - modifier = Modifier.padding(top = 4.dp), + modifier = Modifier + .testTag("txt_sign_in_description") + .padding(top = 4.dp), text = stringResource(id = R.string.auth_welcome_back), color = MaterialTheme.appColors.textPrimary, style = MaterialTheme.appTypography.titleSmall @@ -234,9 +245,11 @@ private fun AuthForm( ) { if (state.isLogistrationEnabled.not()) { Text( - modifier = Modifier.noRippleClickable { - onEvent(AuthEvent.RegisterClick) - }, + modifier = Modifier + .testTag("txt_register") + .noRippleClickable { + onEvent(AuthEvent.RegisterClick) + }, text = stringResource(id = coreR.string.core_register), color = MaterialTheme.appColors.primary, style = MaterialTheme.appTypography.labelLarge @@ -244,9 +257,11 @@ private fun AuthForm( } Spacer(modifier = Modifier.weight(1f)) Text( - modifier = Modifier.noRippleClickable { - onEvent(AuthEvent.ForgotPasswordClick) - }, + modifier = Modifier + .testTag("txt_forgot_password") + .noRippleClickable { + onEvent(AuthEvent.ForgotPasswordClick) + }, text = stringResource(id = R.string.auth_forgot_password), color = MaterialTheme.appColors.primary, style = MaterialTheme.appTypography.labelLarge @@ -257,7 +272,7 @@ private fun AuthForm( CircularProgressIndicator(color = MaterialTheme.appColors.primary) } else { OpenEdXButton( - width = buttonWidth, + width = buttonWidth.testTag("btn_sign_in"), text = stringResource(id = coreR.string.core_sign_in), onClick = { onEvent(AuthEvent.SignIn(login = login, password = password)) @@ -278,7 +293,9 @@ private fun SocialLoginView( ) { if (state.isGoogleAuthEnabled) { OpenEdXOutlinedButton( - modifier = buttonWidth.padding(top = 24.dp), + modifier = buttonWidth + .testTag("btn_google_auth") + .padding(top = 24.dp), backgroundColor = MaterialTheme.appColors.background, borderColor = MaterialTheme.appColors.primary, textColor = Color.Unspecified, @@ -293,7 +310,9 @@ private fun SocialLoginView( tint = Color.Unspecified, ) Text( - modifier = Modifier.padding(start = 10.dp), + modifier = Modifier + .testTag("txt_google_auth") + .padding(start = 10.dp), text = stringResource(id = R.string.auth_google) ) } @@ -301,7 +320,9 @@ private fun SocialLoginView( } if (state.isFacebookAuthEnabled) { OpenEdXButton( - width = buttonWidth.padding(top = 12.dp), + width = buttonWidth + .testTag("btn_facebook_auth") + .padding(top = 12.dp), text = stringResource(id = R.string.auth_facebook), backgroundColor = MaterialTheme.appColors.authFacebookButtonBackground, onClick = { @@ -315,7 +336,9 @@ private fun SocialLoginView( tint = MaterialTheme.appColors.buttonText, ) Text( - modifier = Modifier.padding(start = 10.dp), + modifier = Modifier + .testTag("txt_facebook_auth") + .padding(start = 10.dp), color = MaterialTheme.appColors.buttonText, text = stringResource(id = R.string.auth_facebook) ) @@ -324,7 +347,9 @@ private fun SocialLoginView( } if (state.isMicrosoftAuthEnabled) { OpenEdXButton( - width = buttonWidth.padding(top = 12.dp), + width = buttonWidth + .testTag("btn_microsoft_auth") + .padding(top = 12.dp), text = stringResource(id = R.string.auth_microsoft), backgroundColor = MaterialTheme.appColors.authMicrosoftButtonBackground, onClick = { @@ -338,7 +363,9 @@ private fun SocialLoginView( tint = Color.Unspecified, ) Text( - modifier = Modifier.padding(start = 10.dp), + modifier = Modifier + .testTag("txt_microsoft_auth") + .padding(start = 10.dp), color = MaterialTheme.appColors.buttonText, text = stringResource(id = R.string.auth_microsoft) ) @@ -360,14 +387,16 @@ private fun PasswordTextField( } val focusManager = LocalFocusManager.current Text( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .testTag("txt_password_label") + .fillMaxWidth(), text = stringResource(id = coreR.string.core_password), color = MaterialTheme.appColors.textPrimary, style = MaterialTheme.appTypography.labelLarge ) Spacer(modifier = Modifier.height(8.dp)) OutlinedTextField( - modifier = modifier, + modifier = modifier.testTag("tf_password"), value = passwordTextFieldValue, onValueChange = { passwordTextFieldValue = it @@ -380,6 +409,7 @@ private fun PasswordTextField( shape = MaterialTheme.appShapes.textFieldShape, placeholder = { Text( + modifier = Modifier.testTag("txt_password_placeholder"), text = stringResource(id = R.string.auth_enter_password), color = MaterialTheme.appColors.textFieldHint, style = MaterialTheme.appTypography.bodyMedium diff --git a/auth/src/main/java/org/openedx/auth/presentation/signup/SignUpFragment.kt b/auth/src/main/java/org/openedx/auth/presentation/signup/SignUpFragment.kt index 7b112473a..a30e25451 100644 --- a/auth/src/main/java/org/openedx/auth/presentation/signup/SignUpFragment.kt +++ b/auth/src/main/java/org/openedx/auth/presentation/signup/SignUpFragment.kt @@ -56,8 +56,11 @@ import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Devices @@ -243,6 +246,9 @@ internal fun RegistrationScreen( Scaffold( scaffoldState = scaffoldState, modifier = Modifier + .semantics { + testTagsAsResourceId = true + } .fillMaxSize() .navigationBarsPadding(), backgroundColor = MaterialTheme.appColors.background @@ -343,6 +349,7 @@ internal fun RegistrationScreen( ) { Text( modifier = Modifier + .testTag("txt_screen_title") .fillMaxWidth(), text = stringResource(id = R.string.core_register), color = Color.White, @@ -396,13 +403,16 @@ internal fun RegistrationScreen( ) { Column() { Text( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .testTag("txt_sign_up_title") + .fillMaxWidth(), text = stringResource(id = org.openedx.auth.R.string.auth_sign_up), color = MaterialTheme.appColors.textPrimary, style = MaterialTheme.appTypography.displaySmall ) Text( modifier = Modifier + .testTag("txt_sign_up_description") .fillMaxWidth() .padding(top = 4.dp), text = stringResource(id = org.openedx.auth.R.string.auth_create_new_account), @@ -431,9 +441,10 @@ internal fun RegistrationScreen( } ) if (uiState.optionalFields.isNotEmpty()) { - ExpandableText(isExpanded = showOptionalFields, onClick = { - showOptionalFields = !showOptionalFields - }) + ExpandableText(modifier = Modifier.testTag("txt_optional_field"), + isExpanded = showOptionalFields, onClick = { + showOptionalFields = !showOptionalFields + }) Surface(color = MaterialTheme.appColors.background) { AnimatedVisibility(visible = showOptionalFields) { OptionalFields( @@ -472,7 +483,7 @@ internal fun RegistrationScreen( } } else { OpenEdXButton( - width = buttonWidth, + width = buttonWidth.testTag("btn_create_account"), text = stringResource(id = org.openedx.auth.R.string.auth_create_account), onClick = { showErrorMap.clear() diff --git a/auth/src/main/java/org/openedx/auth/presentation/ui/AuthUI.kt b/auth/src/main/java/org/openedx/auth/presentation/ui/AuthUI.kt index d01519f8d..2ee5f1a55 100644 --- a/auth/src/main/java/org/openedx/auth/presentation/ui/AuthUI.kt +++ b/auth/src/main/java/org/openedx/auth/presentation/ui/AuthUI.kt @@ -37,6 +37,7 @@ import androidx.compose.ui.focus.FocusManager import androidx.compose.ui.focus.focusTarget import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType @@ -85,6 +86,7 @@ fun RequiredFields( val linkedText = TextConverter.htmlTextToLinkedText(field.label) HyperlinkText( + modifier = Modifier.testTag("txt_${field.name}"), fullText = linkedText.text, hyperLinks = linkedText.links, linkTextColor = MaterialTheme.appColors.primary @@ -227,7 +229,9 @@ fun LoginTextField( } val focusManager = LocalFocusManager.current Text( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .testTag("txt_email_label") + .fillMaxWidth(), text = title, color = MaterialTheme.appColors.textPrimary, style = MaterialTheme.appTypography.labelLarge @@ -246,6 +250,7 @@ fun LoginTextField( shape = MaterialTheme.appShapes.textFieldShape, placeholder = { Text( + modifier = Modifier.testTag("txt_email_placeholder"), text = description, color = MaterialTheme.appColors.textFieldHint, style = MaterialTheme.appTypography.bodyMedium @@ -260,7 +265,7 @@ fun LoginTextField( }, textStyle = MaterialTheme.appTypography.bodyMedium, singleLine = true, - modifier = modifier + modifier = modifier.testTag("tf_email") ) } @@ -302,7 +307,9 @@ fun InputRegistrationField( } Column { Text( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .testTag("txt_${registrationField.name}_label") + .fillMaxWidth(), text = registrationField.label, style = MaterialTheme.appTypography.labelLarge, color = MaterialTheme.appColors.textPrimary @@ -325,6 +332,7 @@ fun InputRegistrationField( shape = MaterialTheme.appShapes.textFieldShape, placeholder = { Text( + modifier = modifier.testTag("txt_${registrationField.name}_placeholder"), text = registrationField.label, color = MaterialTheme.appColors.textFieldHint, style = MaterialTheme.appTypography.bodyMedium @@ -340,10 +348,11 @@ fun InputRegistrationField( }, textStyle = MaterialTheme.appTypography.bodyMedium, singleLine = isSingleLine, - modifier = modifier + modifier = modifier.testTag("tf_${registrationField.name}") ) Spacer(modifier = Modifier.height(6.dp)) Text( + modifier = Modifier.testTag("txt_${registrationField.name}_description"), text = helperText, style = MaterialTheme.appTypography.bodySmall, color = helperTextColor @@ -385,7 +394,9 @@ fun SelectableRegisterField( } ) { Text( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .testTag("txt_${registrationField.name}_label") + .fillMaxWidth(), text = registrationField.label, style = MaterialTheme.appTypography.labelLarge, color = MaterialTheme.appColors.textPrimary @@ -406,12 +417,14 @@ fun SelectableRegisterField( textStyle = MaterialTheme.appTypography.bodyMedium, onValueChange = { }, modifier = Modifier + .testTag("tf_${registrationField.name}") .fillMaxWidth() .noRippleClickable { onClick(registrationField.name, registrationField.options) }, placeholder = { Text( + modifier = Modifier.testTag("txt_${registrationField.name}_placeholder"), text = registrationField.label, color = MaterialTheme.appColors.textFieldHint, style = MaterialTheme.appTypography.bodyMedium @@ -427,6 +440,7 @@ fun SelectableRegisterField( ) Spacer(modifier = Modifier.height(6.dp)) Text( + modifier = Modifier.testTag("txt_${registrationField.name}_description"), text = helperText, style = MaterialTheme.appTypography.bodySmall, color = helperTextColor @@ -436,6 +450,7 @@ fun SelectableRegisterField( @Composable fun ExpandableText( + modifier: Modifier = Modifier, isExpanded: Boolean, onClick: (Boolean) -> Unit ) { @@ -459,7 +474,7 @@ fun ExpandableText( val icon = Icons.Filled.ChevronRight Row( - modifier = Modifier + modifier = modifier .fillMaxWidth() .noRippleClickable { onClick(isExpanded) diff --git a/core/src/main/java/org/openedx/core/ui/ComposeCommon.kt b/core/src/main/java/org/openedx/core/ui/ComposeCommon.kt index 94d3455d2..6ffb2274a 100644 --- a/core/src/main/java/org/openedx/core/ui/ComposeCommon.kt +++ b/core/src/main/java/org/openedx/core/ui/ComposeCommon.kt @@ -68,6 +68,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.SpanStyle @@ -241,7 +242,9 @@ fun SearchBar( ), placeholder = { Text( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .testTag("txt_search_placeholder") + .fillMaxWidth(), text = label, color = MaterialTheme.appColors.textSecondary, style = MaterialTheme.appTypography.bodyMedium @@ -601,6 +604,7 @@ fun SheetContent( ) { Text( modifier = Modifier + .testTag("txt_selection_title") .fillMaxWidth() .padding(10.dp), textAlign = TextAlign.Center, @@ -609,6 +613,7 @@ fun SheetContent( ) SearchBarStateless( modifier = Modifier + .testTag("sb_search") .fillMaxWidth() .height(48.dp) .padding(horizontal = 16.dp), @@ -629,6 +634,7 @@ fun SheetContent( }) { item -> Text( modifier = Modifier + .testTag("txt_${item.value}_title") .fillMaxWidth() .padding(horizontal = 16.dp) .clickable { @@ -1116,7 +1122,7 @@ fun BackBtn( tint: Color = MaterialTheme.appColors.primary, onBackClick: () -> Unit ) { - IconButton(modifier = modifier, + IconButton(modifier = modifier.testTag("ib_back"), onClick = { onBackClick() }) { Icon( painter = painterResource(id = R.drawable.core_ic_back), @@ -1168,6 +1174,7 @@ fun AuthButtonsPanel( Row { OpenEdXButton( width = Modifier + .testTag("btn_register") .width(0.dp) .weight(1f), text = stringResource(id = R.string.core_register), @@ -1176,6 +1183,7 @@ fun AuthButtonsPanel( OpenEdXOutlinedButton( modifier = Modifier + .testTag("btn_sign_in") .width(100.dp) .padding(start = 16.dp), text = stringResource(id = R.string.core_sign_in), diff --git a/whatsnew/src/main/java/org/openedx/whatsnew/presentation/ui/WhatsNewUI.kt b/whatsnew/src/main/java/org/openedx/whatsnew/presentation/ui/WhatsNewUI.kt index 136625bd2..a76ff9a10 100644 --- a/whatsnew/src/main/java/org/openedx/whatsnew/presentation/ui/WhatsNewUI.kt +++ b/whatsnew/src/main/java/org/openedx/whatsnew/presentation/ui/WhatsNewUI.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.geometry.CornerRadius import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -63,7 +64,8 @@ fun PageIndicator( ) { for (i in 0 until numberOfPages) { val isSelected = i == selectedPage - val unselectedColor = if (i < selectedPage) previousUnselectedColor else nextUnselectedColor + val unselectedColor = + if (i < selectedPage) previousUnselectedColor else nextUnselectedColor PageIndicatorView( isSelected = isSelected, selectedColor = selectedColor, @@ -168,6 +170,7 @@ fun PrevButton( OutlinedButton( modifier = Modifier + .testTag("btn_previous") .height(42.dp) .alpha(prevButtonAnimationFactor), colors = ButtonDefaults.outlinedButtonColors( @@ -204,6 +207,7 @@ fun NextFinishButton( ) { Button( modifier = Modifier + .testTag("btn_next") .height(42.dp), colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.appColors.buttonBackground @@ -225,6 +229,7 @@ fun NextFinishButton( horizontalArrangement = Arrangement.Center ) { Text( + modifier = Modifier.testTag("txt_next"), text = stringResource(id = R.string.whats_new_navigation_next), color = MaterialTheme.appColors.buttonText, style = MaterialTheme.appTypography.labelLarge @@ -242,6 +247,7 @@ fun NextFinishButton( horizontalArrangement = Arrangement.Center ) { Text( + modifier = Modifier.testTag("txt_done"), text = stringResource(id = R.string.whats_new_navigation_done), color = MaterialTheme.appColors.buttonText, style = MaterialTheme.appTypography.labelLarge diff --git a/whatsnew/src/main/java/org/openedx/whatsnew/presentation/whatsnew/WhatsNewFragment.kt b/whatsnew/src/main/java/org/openedx/whatsnew/presentation/whatsnew/WhatsNewFragment.kt index d07b3a9bb..d1d69b861 100644 --- a/whatsnew/src/main/java/org/openedx/whatsnew/presentation/whatsnew/WhatsNewFragment.kt +++ b/whatsnew/src/main/java/org/openedx/whatsnew/presentation/whatsnew/WhatsNewFragment.kt @@ -35,13 +35,17 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTagsAsResourceId import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview @@ -113,7 +117,7 @@ class WhatsNewFragment : Fragment() { } } -@OptIn(ExperimentalFoundationApi::class) +@OptIn(ExperimentalFoundationApi::class, ExperimentalComposeUiApi::class) @Composable fun WhatsNewScreen( windowSize: WindowSize, @@ -128,7 +132,11 @@ fun WhatsNewScreen( } Scaffold( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .semantics { + testTagsAsResourceId = true + } + .fillMaxSize(), scaffoldState = scaffoldState, topBar = { WhatsNewTopBar( @@ -189,14 +197,18 @@ private fun WhatsNewTopBar( contentAlignment = Alignment.CenterEnd ) { Text( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .testTag("txt_screen_title") + .fillMaxWidth(), text = stringResource(id = org.openedx.whatsnew.R.string.whats_new_title), textAlign = TextAlign.Center, color = MaterialTheme.appColors.textPrimary, style = MaterialTheme.appTypography.titleMedium ) IconButton( - modifier = Modifier.padding(end = 16.dp), + modifier = Modifier + .testTag("ib_close") + .padding(end = 16.dp), onClick = onCloseClick ) { Icon( @@ -271,6 +283,7 @@ private fun WhatsNewScreenPortrait( ) { Text( modifier = Modifier + .testTag("txt_whats_new_title") .fillMaxWidth(), text = targetText.title, color = MaterialTheme.appColors.textPrimary, @@ -279,6 +292,7 @@ private fun WhatsNewScreenPortrait( ) Text( modifier = Modifier + .testTag("txt_whats_new_description") .fillMaxWidth() .height(80.dp), text = targetText.message, diff --git a/whatsnew/src/main/java/org/openedx/whatsnew/presentation/whatsnew/WhatsNewViewModel.kt b/whatsnew/src/main/java/org/openedx/whatsnew/presentation/whatsnew/WhatsNewViewModel.kt index 97b0b9f5c..c27ead37c 100644 --- a/whatsnew/src/main/java/org/openedx/whatsnew/presentation/whatsnew/WhatsNewViewModel.kt +++ b/whatsnew/src/main/java/org/openedx/whatsnew/presentation/whatsnew/WhatsNewViewModel.kt @@ -7,7 +7,7 @@ import org.openedx.whatsnew.WhatsNewManager import org.openedx.whatsnew.domain.model.WhatsNewItem class WhatsNewViewModel( - val courseId: String, + val courseId: String?, private val whatsNewManager: WhatsNewManager ) : BaseViewModel() {