Fix Part of #4938: Create Admin PIN (4/12) - #5880
Conversation
# Conflicts: # app/src/main/res/values/styles.xml
|
@adhiamboperes this PR is being marked as draft because the PR description must contain 'Fixes #' or 'Fixes part of #' for each issue the PR is changing, and each one on its own line with no other text. |
|
Also the issue assignment workflow is still failing despite this branch being up to date with develop. |
@adhiamboperes it seems the regex check is case sensitive. Perhaps it will pass now? |
BenHenning
left a comment
There was a problem hiding this comment.
Thanks @adhiamboperes! Took a full pass, PTAL. I'll also respond to my earlier long comment (but can't as part of this review due to a GitHub bug).
|
|
||
| @Test | ||
| fun testFragment_onLaunch_allTextViewsHaveCorrectContent() { | ||
| launch(CreateAdminPinActivity::class.java).use { |
There was a problem hiding this comment.
Nit: it's ideal to test fragments in the context of a different activity. If it's easy I suggest using TestActivity for this purpose.
That might potentially help with figuring out the timeout, too, since it looks like (per CI) both the fragment and activity classes are hanging.
| delay(100) | ||
| keyboardController?.show() |
There was a problem hiding this comment.
Is the delay and explicit show actually necessary? Gemini seems to suggest that the delay is likely what's causing the deadlock with our coroutine dispatcher testing barrier which would cause the hanging. It seems to assume that these lines may be unnecessary because focusing the text view ought to be sufficient to open the keyboard automatically.
However, if this is called too soon it may need to be wrapped in a onGloballyPositioned so that focus happens after layout.
There was a problem hiding this comment.
No, They keyboard shows correctly without the delay, so I have removed it, and there was no need to use onGloballyPositioned
There was a problem hiding this comment.
Removing the delay does not fix the hanging test issue. I had previously spent a lot of time investigating this issue, and the closest I got was pinpointing a platform parameter load issue:
at org.oppia.android.testing.platformparameter.TestPlatformParameterModule$providePlatformParameterController$1.loadParametersAsync
at org.oppia.android.app.activity.InjectableAppCompatActivity$ensurePlatformParametersAreLoaded$1.invokeSuspend| { | ||
| focusManager.clearFocus() | ||
| onDone?.invoke() | ||
| } |
There was a problem hiding this comment.
Unnecessary extra curly braces?
There was a problem hiding this comment.
These are needed. The function expectes a unit:
Error: type mismatch: inferred type is Unit? but (KeyboardActionScope.() -> Unit)? was expected
onDone = if (imeAction == ImeAction.Done) {
^| else -> PinValidationResult( | ||
| isValid = false, | ||
| errorMessage = resourceHandler.getStringInLocaleWithWrapping( | ||
| R.string.create_admin_pin_activity_mismatch_error |
There was a problem hiding this comment.
There are some repeat references to these strings. Is it possible to cleanly refactor to avoid repeating these such that each string is only referenced once?
There was a problem hiding this comment.
Added these to the companion object and refactored the references.
| private data class PinValidationResult( | ||
| val isValid: Boolean, | ||
| val errorMessage: String = "" | ||
| ) |
There was a problem hiding this comment.
Optional, but you could refine this a bit by leveraging a sealed class and also using a StringRes so that the string lookup only needs to happen in one place for the error:
private sealed class PinValidationResult {
object Valid: PinValidationResult()
data class Invalid(@StringRes val errorMessageId: Int): PinValidationResult()
}There was a problem hiding this comment.
Done, the code readability has improved a bit.
| private val resourceHandler: AppLanguageResourceHandler, | ||
| private val profileManagementController: ProfileManagementController | ||
| ) { | ||
| private lateinit var binding: CreateAdminPinFragmentBinding |
There was a problem hiding this comment.
Does this actually need to use databinding? It seems unnecessary looking at the layout file (and probably better to avoid it since I'm not exactly sure how well Compose and databinding will interoperate...).
There was a problem hiding this comment.
I have made the ComposeView the root element in the layout, and refactored its reference directly:
val composeView = inflater.inflate(
R.layout.create_admin_pin_fragment, container, /* attachToRoot= */ false
) as ComposeView| } | ||
| } | ||
|
|
||
| fun testFragment_supervisorOnboardingFlow_stepCountThreeText_isDisplayed() { |
| testCoroutineDispatchers.runCurrent() | ||
|
|
||
| composeRule | ||
| .onNodeWithText(context.getString(R.string.create_admin_pin_activity_blank_error)) |
There was a problem hiding this comment.
Hmm looking at these tests, I acknowledge they are quite clean however one issue I see is that there's a bit of a risk here. I think it's theoretically possible to show every related string to the new screen at one time and all of the tests will pass (or most will, there are a few assert not visible).
This is actually why I think it's important to validate specific views but I know Compose makes that tricky. I think we do need a solution for this but I'm not precisely sure what it is.
There was a problem hiding this comment.
I realized that I didn't quite understand your intent here.
If you mean that we should assert something about the structure or context of those strings, then we could try to ensure we assert for a few conditions at a time, e.g. all other errors hidden + button disabled + only expected error shown. The downside is that the tests can be overly verbose.
But this doesn't look unique to Compose, since the problem could still occur with Android Views.
There was a problem hiding this comment.
Or did you mean:
composeTestRule
.onNode(matcher).assert(hasText("Button") or hasText("Button2"))| // The submit-time error message to display when show_error is true. | ||
| string error_message = 4; |
There was a problem hiding this comment.
Will this cause any problems with the user changing their system language while the activity is open?
There was a problem hiding this comment.
No, it won't. I tested this and the string language updates correctly for all errors on activity recreation.
Screen_recording_20260421_160640.webm
| exempted_file_path: "app/src/main/java/org/oppia/android/app/profile/CreateAdminPinActivityPresenter.kt" | ||
| test_file_not_required: true |
There was a problem hiding this comment.
This file does not use spacing between each item.
|
Unassigning @BenHenning since the review is done. |
|
Hi @adhiamboperes, it looks like some changes were requested on this pull request by @BenHenning. PTAL. Thanks! |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
1 similar comment
This comment was marked as outdated.
This comment was marked as outdated.
# Conflicts: # app/src/main/java/org/oppia/android/app/onboarding/AdminIntroFragmentPresenter.kt # app/src/main/java/org/oppia/android/app/profile/ProfileChooserFragmentPresenter.kt # model/src/main/proto/screens.proto # utility/src/main/java/org/oppia/android/util/logging/EventBundleCreator.kt
|
Hi @adhiamboperes, I'm going to mark this PR as stale because it hasn't had any updates for 7 days. If no further activity occurs within 7 days, it will be automatically closed so that others can take up the issue. |
Explanation
Fixes part of #4938
Introduces a new screen for creating an admin PIN during admin onboarding. This is the last step of admin onboarding.
The PR ensures there are validations to enforce correct PINs that are 5 digits long and that the user inputs and appropriate error messages are retained even on configuration changes.
There are additional changes that clean up the onboarding flow placeholders, and tests have been added where necessary.
Essential Checklist
For UI-specific PRs only
If your PR includes UI-related changes, then: