Skip to content

RCF-1349: Automation Task for Phone Screen#1087

Merged
Prafulrakhade merged 17 commits into
mosip:developfrom
damodarguru:develop
Jun 4, 2026
Merged

RCF-1349: Automation Task for Phone Screen#1087
Prafulrakhade merged 17 commits into
mosip:developfrom
damodarguru:develop

Conversation

@damodarguru

@damodarguru damodarguru commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

RCF-1349: Automation Task for Phone Screen

Summary by CodeRabbit

Release Notes

  • Tests
    • Added test coverage for registration workflows under network-unavailable conditions
    • Enhanced settings functionality validation including Master Data Sync and Global Configuration features
    • Improved UI navigation robustness and element visibility detection across authentication and document flows
    • Strengthened user authentication testing with additional error handling scenarios

damodarguru and others added 16 commits March 26, 2026 09:31
Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
…tomation.

Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
…tomation.

Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
…tomation.

Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
Signed-off-by: damodarguru <damodar.g@cyberpwn.com>
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 24b0026f-9b04-4142-a4e7-95fff46c38a3

📥 Commits

Reviewing files that changed from the base of the PR and between b006565 and 3a9be58.

📒 Files selected for processing (29)
  • ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java
  • ui-test/src/main/java/regclient/androidTestCases/LoginTest.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdultException.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdultUploadMultipleDoccuments.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationInfant.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinor.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinorException.java
  • ui-test/src/main/java/regclient/androidTestCases/Settings.java
  • ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateDocuments.java
  • ui-test/src/main/java/regclient/api/AdminTestUtil.java
  • ui-test/src/main/java/regclient/api/ArcConfigManager.java
  • ui-test/src/main/java/regclient/api/KeycloakUserManager.java
  • ui-test/src/main/java/regclient/page/BasePage.java
  • ui-test/src/main/java/regclient/page/KeycloakPage.java
  • ui-test/src/main/java/regclient/page/MockSBIPage.java
  • ui-test/src/main/java/regclient/page/SettingsPage.java
  • ui-test/src/main/java/regclient/pages/arabic/SettingsPageArabic.java
  • ui-test/src/main/java/regclient/pages/english/ApplicantBiometricsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/DemographicDetailsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/DocumentUploadPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/IntroducerBiometricPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/ManageApplicationsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/PreviewPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/SelectLanguagePageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/SettingsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/SupervisorBiometricVerificationpageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/UpdateOperatorBiometricspageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/UpdateUINPageEnglish.java
  • ui-test/src/main/java/regclient/pages/french/SettingsPageFrench.java

Walkthrough

This PR adds a comprehensive no-network registration test, expands test infrastructure for "different center" user scenarios, refactors page object navigation/gesture logic for better UI reliability, and extends Settings UI validation to cover Master Data Sync and global configuration features in English and Arabic locales.

Changes

End-to-End No-Network Registration Test

Layer / File(s) Summary
Test Class Imports and Initialization
ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java (1-122)
Introduces new test class with TestNG/Test harness, localized page-object classes, and utility/config API imports.
Login and Registration Flow Start
CreatePacketWithoutNetwork.java (123-273)
Reads test language, instantiates localized login/registration page objects, disables network, logs in, and enters language/notification selection before screen-by-screen registration.
Core Registration Screen-Order Loop
CreatePacketWithoutNetwork.java (224-401)
Iterates through localized page objects (consent, demographic, document, biometric) per FetchUiSpec configuration, handling conditional scans (eyes, thumbs, face) based on test data.
Preview, Authentication Retry, and Acknowledgement
CreatePacketWithoutNetwork.java (402-479)
Validates preview content, authenticates with retries (up to 3x), enters credentials, and proceeds via acknowledgement page to operational tasks.
Pending Approval, Supervisor Authentication, and Network Recovery
CreatePacketWithoutNetwork.java (481-560)
Navigates to pending approval, approves packet, triggers auth with network disabled (asserting "no network found"), re-enables connectivity, and retries until supervisor auth UI appears and credentials are submitted.
Manage Applications, Upload, and Logout
CreatePacketWithoutNetwork.java (563-633)
Searches/filters approved packets by AID, uploads repeatedly until "zero application" condition, logs out, and asserts login page is displayed.

Test Infrastructure & User Management for Different-Center Scenario

Layer / File(s) Summary
Login Test Updates for Different-Center User
ui-test/src/main/java/regclient/androidTestCases/LoginTest.java
Adds negative login step with differentCenterUser, asserts "user not found" error, continues with standard login, and adds client version assertion on registration tasks page.
Configuration Getter and User Initialization
ui-test/src/main/java/regclient/api/ArcConfigManager.java, AdminTestUtil.java
Adds getIAMUsersToCreateDifferentCenterUser() configuration getter and extends AdminTestUtil.initialize() to provision "different center" user with zone/center mapping.
Keycloak User Manager for Different-Center User Creation
ui-test/src/main/java/regclient/api/KeycloakUserManager.java
Adds public field for storing derived "different center" username and implements createUserForDifferentCenter() method that provisions Keycloak users, assigns roles, and handles existing user conflicts.

Page Object Refactoring: Scrolling, Gestures, and Navigation

Layer / File(s) Summary
BasePage Gesture and Scrolling Updates
ui-test/src/main/java/regclient/page/BasePage.java
Updates cropCaptureImage touch coordinates, adds cropCaptureImageEnglishFrench gesture helper, reduces scroll iteration limits, and refactors scrollHorizontallyUntilVisible to accept By locator and re-find element on each attempt.
Keycloak Page Password Entry and Locator Updates
ui-test/src/main/java/regclient/page/KeycloakPage.java
Broadens native "Password" element XPath, adds horizontal scroll-to-visible step, introduces local By locators for input fields, and updates clickOnPasswordOption to scroll before clicking.
MockSBIPage Device Navigation and Seek Bar Simplification
ui-test/src/main/java/regclient/page/MockSBIPage.java
Replaces swipe-based device transitions with scrollUntilElementVisible calls and simplifies setSeekBarPercent to compute tap coordinates from rectangle geometry instead of complex touch-drag calibration.

Settings Page Contract Expansion and Multi-Locale Implementation

Layer / File(s) Summary
Abstract SettingsPage Contract Extension
ui-test/src/main/java/regclient/page/SettingsPage.java
Adds six new abstract boolean methods for verifying key/server/local label presence, config list and local value box visibility, and global config search box display.
Settings Test Case Updates
ui-test/src/main/java/regclient/androidTestCases/Settings.java
Simplifies test imports, adds device settings language assertion, uncomments "no devices found" check, and extends Master Data Sync validation to include toast assertion and global config UI checks (header, labels, config list, local value box, search box).
SettingsPageEnglish Locator and Method Implementation
ui-test/src/main/java/regclient/pages/english/SettingsPageEnglish.java
Updates imports, changes globalConfigSettingsTab to accessibility selector, adds new @AndroidFindBy fields for Master Data Sync toast and global config elements, and implements visibility-check methods with explicit waits and direct element checks.
SettingsPageArabic Locator and Method Implementation
ui-test/src/main/java/regclient/pages/arabic/SettingsPageArabic.java
Updates locators for Arabic text, adds new UI element fields for Master Data Sync and global config, rewrites validateJobCardFields to check content-desc presence, and implements new visibility-check methods for labels, config list, and device settings in Arabic.
SettingsPageFrench Locator and Method Implementation
ui-test/src/main/java/regclient/pages/french/SettingsPageFrench.java
Updates locators for French text ("Paramètres de configuration globale", "Aucun appareil trouvé"), adds new UI element fields, and implements visibility-check methods with timed waits and language-specific label matching for "Réglages de l'appareil".

Biometric Page Scan Title Visibility Updates

Layer / File(s) Summary
Applicant, Introducer, Supervisor, and Operator Biometric Pages
ui-test/src/main/java/regclient/pages/english/ApplicantBiometricsPageEnglish.java, IntroducerBiometricPageEnglish.java, SupervisorBiometricVerificationpageEnglish.java, UpdateOperatorBiometricspageEnglish.java, PreviewPageEnglish.java
Adds scrollToTop() calls before visibility checks for right-hand, left-hand, thumbs, face, exception scan titles, and "NEW" registration title to ensure consistent page position before assertions.

Document Upload and Demographic Details UI Workflow Updates

Layer / File(s) Summary
DocumentUploadPageEnglish Locator and Navigation
ui-test/src/main/java/regclient/pages/english/DocumentUploadPageEnglish.java
Changes PopUpCloseButton XPath selector, delegates crop to cropCaptureImageEnglishFrench, adds isPacketSizeDisplayed() helper, and adds swipeUp() calls around popup-close handling across branches to improve UI state before scan/capture steps.
DemographicDetailsPageEnglish Dropdown Selection
ui-test/src/main/java/regclient/pages/english/DemographicDetailsPageEnglish.java
Introduces dropdownLocator, adds special case for residenceStatus that selects nonForeignerOption, and updates general flow to use scrollUntilElementVisible with re-obtained dropdown element references.
SelectLanguagePageEnglish and UpdateUINPageEnglish Navigation
ui-test/src/main/java/regclient/pages/english/SelectLanguagePageEnglish.java, UpdateUINPageEnglish.java
SelectLanguagePageEnglish adds scrollInsidePopup() before language selection; UpdateUINPageEnglish adds scrollUntilElementVisible() before group label visibility assertion.

Manage Applications and UpdateMyUin Test Refactoring

Layer / File(s) Summary
ManageApplicationsPageEnglish UiScrollable Navigation
ui-test/src/main/java/regclient/pages/english/ManageApplicationsPageEnglish.java
Refactors dropdown navigation using MobileBy.AndroidUIAutomator (UiScrollable), adds clearFilterButton element, and introduces helpers clickOnClearFilterButton(), isClientStatusDropdownDisplayed(), and scrollTillDisplayingApplicationCountVisible().
UpdateMyUinUpdateDocuments Test Flow
ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateDocuments.java
Renames documentuploadPage variable, adds document upload page display assertion, and reworks second navigation pass to perform simplified interactions (document continues without re-upload, biometric continues without detail steps), then re-validates preview and retrieves application ID.

Test Class Formatting and Whitespace Cleanup

Layer / File(s) Summary
NewRegistration Test Classes Formatting
ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdultException.java, NewRegistrationAdultUploadMultipleDoccuments.java, NewRegistrationInfant.java, NewRegistrationMinor.java, NewRegistrationMinorException.java
Minor whitespace, blank-line, and class declaration formatting adjustments across multiple test classes without logic changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • mosip/android-registration-client#679: Refactors SettingsPage/SettingsPageArabic for job-based sync actions ("Master Data Sync" flow) that overlap with this PR's settings contract and implementation updates.
  • mosip/android-registration-client#1085: Extends Settings UI test and page-object contract/implementations for "Global Config Settings" (Master Data Sync, job-card, toast, key/server/local assertions) that directly overlap with this PR's settings updates.
  • mosip/android-registration-client#1082: Modifies shared Settings UI page contract and English settings page implementation around Master Data Sync toast and related helpers, overlapping with this PR's code-level changes.

Suggested reviewers

  • mohanachandran-s
  • anushasunkada
  • Prafulrakhade

🐰 A registration test hops through the network's dark,
Scrolling screens and gestures leave a careful mark,
Settings sync and configs dance in every tongue,
From English words to Arabic songs half-sung!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'RCF-1349: Automation Task for Phone Screen' relates to the pull request, but is overly vague and does not clearly convey the primary changes made in the changeset. Consider using a more specific title that clearly describes the main automation work, such as 'Add CreatePacketWithoutNetwork test and enhance page object methods for UI automation' or similar to better communicate the scope of changes.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch develop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Signed-off-by: damodarguru <damodar.g@cyberpwn.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
ui-test/src/main/java/regclient/pages/english/SupervisorBiometricVerificationpageEnglish.java (1)

200-202: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

isExceptionScanTitleDisplayed() omits the scrollToTop() that its siblings now use.

The right/left/thumbs/face checks were updated to scroll to top first, but the exception variant was left as-is. If this method is exercised in tests, it may behave inconsistently (stale viewport) compared to the others. If exception scan is intentionally untested here, ignore.

Proposed alignment
 public boolean isExceptionScanTitleDisplayed() {
+	scrollToTop();
 	return isElementDisplayed(exceptionScanTitle);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ui-test/src/main/java/regclient/pages/english/SupervisorBiometricVerificationpageEnglish.java`
around lines 200 - 202, The isExceptionScanTitleDisplayed() method currently
returns isElementDisplayed(exceptionScanTitle) but omits the scrollToTop() call
used by the sibling checks; update isExceptionScanTitleDisplayed() in
SupervisorBiometricVerificationpageEnglish to call scrollToTop() before checking
isElementDisplayed(exceptionScanTitle) so its viewport behavior matches the
other thumb/face methods.
ui-test/src/main/java/regclient/pages/english/UpdateOperatorBiometricspageEnglish.java (1)

207-209: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Same scrollToTop() omission as SupervisorBiometricVerificationpageEnglish.

isExceptionScanTitleDisplayed() was not aligned with the other four scan-title checks. Add scrollToTop() here too if exception scan is verified in tests; otherwise this is fine to leave.

Proposed alignment
 public boolean isExceptionScanTitleDisplayed() {
+	scrollToTop();
 	return isElementDisplayed(exceptionScanTitle);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ui-test/src/main/java/regclient/pages/english/UpdateOperatorBiometricspageEnglish.java`
around lines 207 - 209, The isExceptionScanTitleDisplayed() method omits the
scrollToTop() call used by the other scan-title checks; update the method
(isExceptionScanTitleDisplayed) to call scrollToTop() before returning
isElementDisplayed(exceptionScanTitle) so the exception scan title is always
scrolled into view prior to verification, matching the pattern used in
SupervisorBiometricVerificationpageEnglish and the other four scan-title checks.
ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateDocuments.java (1)

379-379: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep the second preview assertion on the Update UIN title.

The first preview check correctly uses updateUINTitleDisplayed(), but after navigating back through the edit flow this switches to isNewRegistrationTitleDisplayed(). That turns the revisit path into a false failure even though the test is still in the Update My UIN journey.

Proposed fix
-		assertTrue(previewPage.isNewRegistrationTitleDisplayed(), "Verify if new Registration title is displayed");
+		assertTrue(previewPage.updateUINTitleDisplayed(), "Verify if update UIN title is displayed");

Also applies to: 482-483

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateDocuments.java`
at line 379, The second preview assertion incorrectly calls
previewPage.isNewRegistrationTitleDisplayed() after navigating back through the
edit flow; replace that call with previewPage.updateUINTitleDisplayed() so both
preview checks validate the Update UIN title (apply the same replacement where
similar assertions occur around the other affected spots such as the assertions
near lines referenced in the review).
ui-test/src/main/java/regclient/page/KeycloakPage.java (1)

83-88: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Switch to NATIVE_APP before trying to scroll the native password tab.

openKeycloakWebView() leaves the driver in WEBVIEW, but this method now tries to horizontally scroll a native XPath before changing context. In that state the scroll loop just searches/swipes in the wrong context, so the later native wait still times out when the tab is off-screen.

Minimal fix
 public boolean openKeycloakPassword() {
     scrollToTopSafe();

     By nativePwd = By.xpath("//*[`@text`='Password']");
-    scrollHorizontallyUntilVisible(nativePwd);
     try {
         ((SupportsContextSwitching) driver).context("NATIVE_APP");
+        scrollHorizontallyUntilVisible(nativePwd);
         new WebDriverWait(driver, Duration.ofSeconds(8))
                 .until(ExpectedConditions.visibilityOfElementLocated(nativePwd));
         return true;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/page/KeycloakPage.java` around lines 83 - 88,
The scroll is running in WEBVIEW because openKeycloakWebView() leaves the driver
in WEBVIEW; switch the driver to the native context before attempting the native
horizontal scroll. Change the order in KeycloakPage so that you call
((SupportsContextSwitching) driver).context("NATIVE_APP") (or a helper that
switches context) immediately before calling
scrollHorizontallyUntilVisible(nativePwd), then proceed with the WebDriverWait
for nativePwd; keep the subsequent flow (waiting and any later context switches)
intact.
ui-test/src/main/java/regclient/page/BasePage.java (1)

657-669: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Five swipes is not enough to guarantee top/bottom on these flows.

This PR also adds page checks that call scrollToTop() immediately before asserting scan/title visibility. Hard-capping both helpers at 5 swipes can leave long biometric/document screens mid-page, so those assertions still run against the wrong viewport.

Safer options
 protected void scrollToTop() {
-    int maxScrolls = 5;
+    int maxScrolls = 8;
     for (int i = 0; i < maxScrolls; i++) {
         swipeDown();
     }
 }

 protected void scrollToBottom() {
-    int maxScrolls = 5;
+    int maxScrolls = 15;
     for (int i = 0; i < maxScrolls; i++) {
         swipeUp();
     }
 }

Or stop on a stable boundary instead of using a smaller fixed count.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/page/BasePage.java` around lines 657 - 669,
The hard cap of 5 swipes in scrollToTop() and scrollToBottom() can leave long
pages mid-scroll; update these helpers to stop on a stable boundary rather than
a fixed small count: repeatedly call swipeDown()/swipeUp() until either the
page/viewport stops changing (detect via stable page source, stable element
position, or an isAtTop()/isAtBottom() check) or a much larger safety cap (e.g.,
20) is reached; modify scrollToTop(), scrollToBottom() to implement this loop
and use swipeDown()/swipeUp() as before, so callers that assert visibility after
scrolling reliably see the intended viewport.
🧹 Nitpick comments (3)
ui-test/src/main/java/regclient/androidTestCases/Settings.java (1)

172-173: ⚡ Quick win

Avoid fixed sleep before sync action.

Line 172 uses a hard wait that adds test latency and can still be flaky under slower/faster devices; use condition-based wait on the target job card/button instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/androidTestCases/Settings.java` around lines
172 - 173, Remove the fixed sleep BasePage.waitTime(10) and replace it with an
explicit, condition-based wait for the specific sync UI element before calling
settingsPage.clickOnSyncButton("Master Data Sync"); specifically, wait until the
"Master Data Sync" job card or its sync button is visible and/or clickable (use
your project's WebDriverWait/ExpectedConditions helper or add a
settingsPage.waitForSyncJob("Master Data Sync") that waits for
visibility/clickability) and then invoke settingsPage.clickOnSyncButton; ensure
the hard wait is deleted so the test uses the condition-based wait for
reliability and lower latency.
ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java (1)

226-401: ⚡ Quick win

Fail fast on unsupported screenOrder entries.

This loop silently ignores any UI-spec screen id outside the four hard-coded branches, so spec drift turns into a later page-mismatch instead of a clear contract failure. Add an else that fails on unknown ids, and ideally assert the mandatory screens expected for newProcess before starting the loop.

Suggested fix
-		for (String screen : screenOrder) {
+		for (String screen : screenOrder) {
 			if (screen.equals("consentdet") || screen.equals("consent")) {
 				...
 			} else if (screen.equals("DemographicDetails")) {
 				...
 			} else if (screen.equals("Documents")) {
 				...
 			} else if (screen.equals("BiometricDetails")) {
 				...
+			} else {
+				throw new AssertionError("Unsupported screen in UI spec: " + screen);
 			}
 		}

Based on learnings: In ExportPacket.java and similar Android UI test flows, the screenOrder is sourced from the UI spec, so tests should validate that mandatory screens defined in the UI spec are always included and not skipped, and that the flow respects the spec-defined order.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java`
around lines 226 - 401, The loop over screenOrder in CreatePacketWithoutNetwork
silently ignores unknown screen ids; add an else branch after the existing
if/else-if chain that throws an IllegalStateException (or fails the test) with
the unknown screen id to fail fast, and before the loop add a short verification
that screenOrder contains the mandatory screens (e.g., "consentdet"/"consent",
"DemographicDetails", "Documents", "BiometricDetails")—use
screenOrder.contains(...) and throw a clear IllegalStateException if any
mandatory screen is missing so the test fails immediately and points to spec
drift.
ui-test/src/main/java/regclient/api/KeycloakUserManager.java (1)

301-361: ⚡ Quick win

Inconsistent role assignment pattern.

The createUserForDifferentCenter() method uses ArcConfigManager.getRolesForUser() at line 350, whereas other specialized user creation methods follow a dedicated configuration pattern:

  • createUsersWithOutSupervisorRole() uses getRolesForOperatorUser()
  • createOnboardingUser() uses getRolesForOnboardUser()

Consider adding a dedicated getRolesForDifferentCenterUser() method to ArcConfigManager if the "different center" user requires a distinct set of roles. This would maintain consistency with the established pattern and allow independent configuration of roles for each user type.

♻️ Proposed refactor to align with established pattern

First, add the dedicated role getter to ArcConfigManager:

+	public static String getRolesForDifferentCenterUser() { 
+		return getProperty("rolesForDifferentCenterUser", "");
+	}

Then update the role assignment in KeycloakUserManager:

-			List<String> toBeAssignedRoles = List.of(ArcConfigManager.getRolesForUser().split(","));
+			List<String> toBeAssignedRoles = List.of(ArcConfigManager.getRolesForDifferentCenterUser().split(","));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/api/KeycloakUserManager.java` around lines
301 - 361, The role assignment in createUserForDifferentCenter() is using
ArcConfigManager.getRolesForUser(), which is inconsistent with other creators;
add a dedicated getter like ArcConfigManager.getRolesForDifferentCenterUser()
and update createUserForDifferentCenter() to call that method instead of
getRolesForUser() so the different-center user's roles can be configured
independently (update the List<String> to use the new getter and adjust any
config parsing there).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java`:
- Around line 597-604: The loop blindly re-clicks the mutating operation
manageApplicationsPage.clickOnUploadButton(), which can double-submit if the UI
is slow; change the logic to perform a single click then wait for a clear state
transition (for example implement/wait for a method like
manageApplicationsPage.waitForUploadToSettle(), waitForRowDisappearance(), or
waitUntilUploadStatusChanges()) and only attempt a retry if that wait reports an
explicit failure/timeout; use
manageApplicationsPage.isZeroApplicationDisplayed() or an explicit error
indicator to decide whether to retry, and remove immediate re-clicks while the
prior upload is still pending.
- Line 163: The test currently calls BasePage.disableWifiAndData() without
guaranteeing re-enablement; wrap the test logic that runs while offline in a
try/finally so BasePage.enableWifiAndData() is always called in the finally
block; locate the call to BasePage.disableWifiAndData() in
CreatePacketWithoutNetwork and replace the surrounding test flow to ensure
BasePage.enableWifiAndData() is invoked in finally (also update the similar
occurrences around the lines referenced 539-540).

In `@ui-test/src/main/java/regclient/androidTestCases/Settings.java`:
- Line 148: The test re-enabled a known-flaky assertion: remove or guard the
assertTrue(settingsPage.isNoDevicesFoundDisplayed(), ...) in the Settings test
that follows setAllToNotReadyAndSave(); instead revert to the previous safe
state by commenting out that assertion or wrapping it in an
environment-check/feature-flag so it only runs when MockSBI visibility is
guaranteed (locate the assert in Settings.java and the related
setAllToNotReadyAndSave() call to apply the change).

In `@ui-test/src/main/java/regclient/api/AdminTestUtil.java`:
- Around line 143-150: AdminTestUtil calls
propsKernel.getProperty("diffRegCenterId") and passes the result to
mapUserToCenter which can send a null "regCenterId"; add a null/empty check
before calling mapUserToCenter in AdminTestUtil (validate
propsKernel.getProperty("diffRegCenterId") and throw or log/fail fast) and/or
ensure Kernel.properties contains a diffRegCenterId entry; specifically update
the code around KeycloakUserManager.createUserForDifferentCenter() to validate
the diffRegCenterId value and avoid invoking mapUserToCenter with a null/empty
id.

In `@ui-test/src/main/java/regclient/page/BasePage.java`:
- Around line 217-231: The drag targets in cropCaptureImage (and similarly
cropCaptureImageEnglishFrench) use hardcoded viewport coordinates (e.g., 260,320
and 623,261) which break on different device resolutions; replace those
hardcoded numbers by computing target coordinates from the element bounds (use
element.getLocation() and element.getSize() or getCenterOfElement and
add/subtract offsets based on element width/height or fractions) and pass the
computed absolute viewport coordinates into createPointerMove so the pointer
moves relative to the element center/size rather than fixed pixels.

In `@ui-test/src/main/java/regclient/page/KeycloakPage.java`:
- Around line 136-138: clickOnPasswordOption currently calls the WebElement
overloads (scrollHorizontallyUntilVisible(passwordOption) and
clickOnElement(passwordOption)) which can cause staleness; change it to use the
locator-based overloads on BasePage instead: call
scrollHorizontallyUntilVisible(<By locator for passwordOption>) and
clickOnElement(<By locator for passwordOption>) so the element is re-resolved if
it becomes stale (use the existing By field or add one named e.g.
passwordOptionLocator if missing).

In
`@ui-test/src/main/java/regclient/pages/english/DocumentUploadPageEnglish.java`:
- Around line 77-87: The isPacketSizeDisplayed method currently uses
String.matches which requires the whole contentDescription to match and can
false-negative if there is surrounding text; update isPacketSizeDisplayed in
DocumentUploadPageEnglish to compile a Pattern like "Size:
\\d+(\\.\\d+)?\\s?(KB|MB)" and use Matcher.find() on
packetSize.getAttribute("contentDescription") (or String#contains with a looser
regex) to check for the size substring, keeping the
driver.findElement(By.xpath(...)) lookup and the existing exception handling.

In
`@ui-test/src/main/java/regclient/pages/english/ManageApplicationsPageEnglish.java`:
- Around line 314-326: In scrollTillDisplayingApplicationCountVisible() the
lookup uses textContains("Displaying") but the page exposes the count via
accessibility/content-desc keys (displayZeroApplication /
displayOneApplication), so update the visibility check to look for those
accessibility locators instead of text: query for
driver.findElements(MobileBy.AccessibilityId("displayZeroApplication")) and
driver.findElements(MobileBy.AccessibilityId("displayOneApplication")) (or a
single descriptionContains selector that matches either) and return when found;
keep the existing scrollBackward() loop and only scroll if neither accessibility
element is present.

---

Outside diff comments:
In
`@ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateDocuments.java`:
- Line 379: The second preview assertion incorrectly calls
previewPage.isNewRegistrationTitleDisplayed() after navigating back through the
edit flow; replace that call with previewPage.updateUINTitleDisplayed() so both
preview checks validate the Update UIN title (apply the same replacement where
similar assertions occur around the other affected spots such as the assertions
near lines referenced in the review).

In `@ui-test/src/main/java/regclient/page/BasePage.java`:
- Around line 657-669: The hard cap of 5 swipes in scrollToTop() and
scrollToBottom() can leave long pages mid-scroll; update these helpers to stop
on a stable boundary rather than a fixed small count: repeatedly call
swipeDown()/swipeUp() until either the page/viewport stops changing (detect via
stable page source, stable element position, or an isAtTop()/isAtBottom() check)
or a much larger safety cap (e.g., 20) is reached; modify scrollToTop(),
scrollToBottom() to implement this loop and use swipeDown()/swipeUp() as before,
so callers that assert visibility after scrolling reliably see the intended
viewport.

In `@ui-test/src/main/java/regclient/page/KeycloakPage.java`:
- Around line 83-88: The scroll is running in WEBVIEW because
openKeycloakWebView() leaves the driver in WEBVIEW; switch the driver to the
native context before attempting the native horizontal scroll. Change the order
in KeycloakPage so that you call ((SupportsContextSwitching)
driver).context("NATIVE_APP") (or a helper that switches context) immediately
before calling scrollHorizontallyUntilVisible(nativePwd), then proceed with the
WebDriverWait for nativePwd; keep the subsequent flow (waiting and any later
context switches) intact.

In
`@ui-test/src/main/java/regclient/pages/english/SupervisorBiometricVerificationpageEnglish.java`:
- Around line 200-202: The isExceptionScanTitleDisplayed() method currently
returns isElementDisplayed(exceptionScanTitle) but omits the scrollToTop() call
used by the sibling checks; update isExceptionScanTitleDisplayed() in
SupervisorBiometricVerificationpageEnglish to call scrollToTop() before checking
isElementDisplayed(exceptionScanTitle) so its viewport behavior matches the
other thumb/face methods.

In
`@ui-test/src/main/java/regclient/pages/english/UpdateOperatorBiometricspageEnglish.java`:
- Around line 207-209: The isExceptionScanTitleDisplayed() method omits the
scrollToTop() call used by the other scan-title checks; update the method
(isExceptionScanTitleDisplayed) to call scrollToTop() before returning
isElementDisplayed(exceptionScanTitle) so the exception scan title is always
scrolled into view prior to verification, matching the pattern used in
SupervisorBiometricVerificationpageEnglish and the other four scan-title checks.

---

Nitpick comments:
In
`@ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java`:
- Around line 226-401: The loop over screenOrder in CreatePacketWithoutNetwork
silently ignores unknown screen ids; add an else branch after the existing
if/else-if chain that throws an IllegalStateException (or fails the test) with
the unknown screen id to fail fast, and before the loop add a short verification
that screenOrder contains the mandatory screens (e.g., "consentdet"/"consent",
"DemographicDetails", "Documents", "BiometricDetails")—use
screenOrder.contains(...) and throw a clear IllegalStateException if any
mandatory screen is missing so the test fails immediately and points to spec
drift.

In `@ui-test/src/main/java/regclient/androidTestCases/Settings.java`:
- Around line 172-173: Remove the fixed sleep BasePage.waitTime(10) and replace
it with an explicit, condition-based wait for the specific sync UI element
before calling settingsPage.clickOnSyncButton("Master Data Sync"); specifically,
wait until the "Master Data Sync" job card or its sync button is visible and/or
clickable (use your project's WebDriverWait/ExpectedConditions helper or add a
settingsPage.waitForSyncJob("Master Data Sync") that waits for
visibility/clickability) and then invoke settingsPage.clickOnSyncButton; ensure
the hard wait is deleted so the test uses the condition-based wait for
reliability and lower latency.

In `@ui-test/src/main/java/regclient/api/KeycloakUserManager.java`:
- Around line 301-361: The role assignment in createUserForDifferentCenter() is
using ArcConfigManager.getRolesForUser(), which is inconsistent with other
creators; add a dedicated getter like
ArcConfigManager.getRolesForDifferentCenterUser() and update
createUserForDifferentCenter() to call that method instead of getRolesForUser()
so the different-center user's roles can be configured independently (update the
List<String> to use the new getter and adjust any config parsing there).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 24b0026f-9b04-4142-a4e7-95fff46c38a3

📥 Commits

Reviewing files that changed from the base of the PR and between b006565 and 3a9be58.

📒 Files selected for processing (29)
  • ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java
  • ui-test/src/main/java/regclient/androidTestCases/LoginTest.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdultException.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdultUploadMultipleDoccuments.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationInfant.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinor.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinorException.java
  • ui-test/src/main/java/regclient/androidTestCases/Settings.java
  • ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateDocuments.java
  • ui-test/src/main/java/regclient/api/AdminTestUtil.java
  • ui-test/src/main/java/regclient/api/ArcConfigManager.java
  • ui-test/src/main/java/regclient/api/KeycloakUserManager.java
  • ui-test/src/main/java/regclient/page/BasePage.java
  • ui-test/src/main/java/regclient/page/KeycloakPage.java
  • ui-test/src/main/java/regclient/page/MockSBIPage.java
  • ui-test/src/main/java/regclient/page/SettingsPage.java
  • ui-test/src/main/java/regclient/pages/arabic/SettingsPageArabic.java
  • ui-test/src/main/java/regclient/pages/english/ApplicantBiometricsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/DemographicDetailsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/DocumentUploadPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/IntroducerBiometricPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/ManageApplicationsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/PreviewPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/SelectLanguagePageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/SettingsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/SupervisorBiometricVerificationpageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/UpdateOperatorBiometricspageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/UpdateUINPageEnglish.java
  • ui-test/src/main/java/regclient/pages/french/SettingsPageFrench.java

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
ui-test/src/main/java/regclient/pages/english/SupervisorBiometricVerificationpageEnglish.java (1)

200-202: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

isExceptionScanTitleDisplayed() omits the scrollToTop() that its siblings now use.

The right/left/thumbs/face checks were updated to scroll to top first, but the exception variant was left as-is. If this method is exercised in tests, it may behave inconsistently (stale viewport) compared to the others. If exception scan is intentionally untested here, ignore.

Proposed alignment
 public boolean isExceptionScanTitleDisplayed() {
+	scrollToTop();
 	return isElementDisplayed(exceptionScanTitle);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ui-test/src/main/java/regclient/pages/english/SupervisorBiometricVerificationpageEnglish.java`
around lines 200 - 202, The isExceptionScanTitleDisplayed() method currently
returns isElementDisplayed(exceptionScanTitle) but omits the scrollToTop() call
used by the sibling checks; update isExceptionScanTitleDisplayed() in
SupervisorBiometricVerificationpageEnglish to call scrollToTop() before checking
isElementDisplayed(exceptionScanTitle) so its viewport behavior matches the
other thumb/face methods.
ui-test/src/main/java/regclient/pages/english/UpdateOperatorBiometricspageEnglish.java (1)

207-209: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Same scrollToTop() omission as SupervisorBiometricVerificationpageEnglish.

isExceptionScanTitleDisplayed() was not aligned with the other four scan-title checks. Add scrollToTop() here too if exception scan is verified in tests; otherwise this is fine to leave.

Proposed alignment
 public boolean isExceptionScanTitleDisplayed() {
+	scrollToTop();
 	return isElementDisplayed(exceptionScanTitle);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ui-test/src/main/java/regclient/pages/english/UpdateOperatorBiometricspageEnglish.java`
around lines 207 - 209, The isExceptionScanTitleDisplayed() method omits the
scrollToTop() call used by the other scan-title checks; update the method
(isExceptionScanTitleDisplayed) to call scrollToTop() before returning
isElementDisplayed(exceptionScanTitle) so the exception scan title is always
scrolled into view prior to verification, matching the pattern used in
SupervisorBiometricVerificationpageEnglish and the other four scan-title checks.
ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateDocuments.java (1)

379-379: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep the second preview assertion on the Update UIN title.

The first preview check correctly uses updateUINTitleDisplayed(), but after navigating back through the edit flow this switches to isNewRegistrationTitleDisplayed(). That turns the revisit path into a false failure even though the test is still in the Update My UIN journey.

Proposed fix
-		assertTrue(previewPage.isNewRegistrationTitleDisplayed(), "Verify if new Registration title is displayed");
+		assertTrue(previewPage.updateUINTitleDisplayed(), "Verify if update UIN title is displayed");

Also applies to: 482-483

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateDocuments.java`
at line 379, The second preview assertion incorrectly calls
previewPage.isNewRegistrationTitleDisplayed() after navigating back through the
edit flow; replace that call with previewPage.updateUINTitleDisplayed() so both
preview checks validate the Update UIN title (apply the same replacement where
similar assertions occur around the other affected spots such as the assertions
near lines referenced in the review).
ui-test/src/main/java/regclient/page/KeycloakPage.java (1)

83-88: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Switch to NATIVE_APP before trying to scroll the native password tab.

openKeycloakWebView() leaves the driver in WEBVIEW, but this method now tries to horizontally scroll a native XPath before changing context. In that state the scroll loop just searches/swipes in the wrong context, so the later native wait still times out when the tab is off-screen.

Minimal fix
 public boolean openKeycloakPassword() {
     scrollToTopSafe();

     By nativePwd = By.xpath("//*[`@text`='Password']");
-    scrollHorizontallyUntilVisible(nativePwd);
     try {
         ((SupportsContextSwitching) driver).context("NATIVE_APP");
+        scrollHorizontallyUntilVisible(nativePwd);
         new WebDriverWait(driver, Duration.ofSeconds(8))
                 .until(ExpectedConditions.visibilityOfElementLocated(nativePwd));
         return true;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/page/KeycloakPage.java` around lines 83 - 88,
The scroll is running in WEBVIEW because openKeycloakWebView() leaves the driver
in WEBVIEW; switch the driver to the native context before attempting the native
horizontal scroll. Change the order in KeycloakPage so that you call
((SupportsContextSwitching) driver).context("NATIVE_APP") (or a helper that
switches context) immediately before calling
scrollHorizontallyUntilVisible(nativePwd), then proceed with the WebDriverWait
for nativePwd; keep the subsequent flow (waiting and any later context switches)
intact.
ui-test/src/main/java/regclient/page/BasePage.java (1)

657-669: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Five swipes is not enough to guarantee top/bottom on these flows.

This PR also adds page checks that call scrollToTop() immediately before asserting scan/title visibility. Hard-capping both helpers at 5 swipes can leave long biometric/document screens mid-page, so those assertions still run against the wrong viewport.

Safer options
 protected void scrollToTop() {
-    int maxScrolls = 5;
+    int maxScrolls = 8;
     for (int i = 0; i < maxScrolls; i++) {
         swipeDown();
     }
 }

 protected void scrollToBottom() {
-    int maxScrolls = 5;
+    int maxScrolls = 15;
     for (int i = 0; i < maxScrolls; i++) {
         swipeUp();
     }
 }

Or stop on a stable boundary instead of using a smaller fixed count.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/page/BasePage.java` around lines 657 - 669,
The hard cap of 5 swipes in scrollToTop() and scrollToBottom() can leave long
pages mid-scroll; update these helpers to stop on a stable boundary rather than
a fixed small count: repeatedly call swipeDown()/swipeUp() until either the
page/viewport stops changing (detect via stable page source, stable element
position, or an isAtTop()/isAtBottom() check) or a much larger safety cap (e.g.,
20) is reached; modify scrollToTop(), scrollToBottom() to implement this loop
and use swipeDown()/swipeUp() as before, so callers that assert visibility after
scrolling reliably see the intended viewport.
🧹 Nitpick comments (3)
ui-test/src/main/java/regclient/androidTestCases/Settings.java (1)

172-173: ⚡ Quick win

Avoid fixed sleep before sync action.

Line 172 uses a hard wait that adds test latency and can still be flaky under slower/faster devices; use condition-based wait on the target job card/button instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/androidTestCases/Settings.java` around lines
172 - 173, Remove the fixed sleep BasePage.waitTime(10) and replace it with an
explicit, condition-based wait for the specific sync UI element before calling
settingsPage.clickOnSyncButton("Master Data Sync"); specifically, wait until the
"Master Data Sync" job card or its sync button is visible and/or clickable (use
your project's WebDriverWait/ExpectedConditions helper or add a
settingsPage.waitForSyncJob("Master Data Sync") that waits for
visibility/clickability) and then invoke settingsPage.clickOnSyncButton; ensure
the hard wait is deleted so the test uses the condition-based wait for
reliability and lower latency.
ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java (1)

226-401: ⚡ Quick win

Fail fast on unsupported screenOrder entries.

This loop silently ignores any UI-spec screen id outside the four hard-coded branches, so spec drift turns into a later page-mismatch instead of a clear contract failure. Add an else that fails on unknown ids, and ideally assert the mandatory screens expected for newProcess before starting the loop.

Suggested fix
-		for (String screen : screenOrder) {
+		for (String screen : screenOrder) {
 			if (screen.equals("consentdet") || screen.equals("consent")) {
 				...
 			} else if (screen.equals("DemographicDetails")) {
 				...
 			} else if (screen.equals("Documents")) {
 				...
 			} else if (screen.equals("BiometricDetails")) {
 				...
+			} else {
+				throw new AssertionError("Unsupported screen in UI spec: " + screen);
 			}
 		}

Based on learnings: In ExportPacket.java and similar Android UI test flows, the screenOrder is sourced from the UI spec, so tests should validate that mandatory screens defined in the UI spec are always included and not skipped, and that the flow respects the spec-defined order.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java`
around lines 226 - 401, The loop over screenOrder in CreatePacketWithoutNetwork
silently ignores unknown screen ids; add an else branch after the existing
if/else-if chain that throws an IllegalStateException (or fails the test) with
the unknown screen id to fail fast, and before the loop add a short verification
that screenOrder contains the mandatory screens (e.g., "consentdet"/"consent",
"DemographicDetails", "Documents", "BiometricDetails")—use
screenOrder.contains(...) and throw a clear IllegalStateException if any
mandatory screen is missing so the test fails immediately and points to spec
drift.
ui-test/src/main/java/regclient/api/KeycloakUserManager.java (1)

301-361: ⚡ Quick win

Inconsistent role assignment pattern.

The createUserForDifferentCenter() method uses ArcConfigManager.getRolesForUser() at line 350, whereas other specialized user creation methods follow a dedicated configuration pattern:

  • createUsersWithOutSupervisorRole() uses getRolesForOperatorUser()
  • createOnboardingUser() uses getRolesForOnboardUser()

Consider adding a dedicated getRolesForDifferentCenterUser() method to ArcConfigManager if the "different center" user requires a distinct set of roles. This would maintain consistency with the established pattern and allow independent configuration of roles for each user type.

♻️ Proposed refactor to align with established pattern

First, add the dedicated role getter to ArcConfigManager:

+	public static String getRolesForDifferentCenterUser() { 
+		return getProperty("rolesForDifferentCenterUser", "");
+	}

Then update the role assignment in KeycloakUserManager:

-			List<String> toBeAssignedRoles = List.of(ArcConfigManager.getRolesForUser().split(","));
+			List<String> toBeAssignedRoles = List.of(ArcConfigManager.getRolesForDifferentCenterUser().split(","));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/api/KeycloakUserManager.java` around lines
301 - 361, The role assignment in createUserForDifferentCenter() is using
ArcConfigManager.getRolesForUser(), which is inconsistent with other creators;
add a dedicated getter like ArcConfigManager.getRolesForDifferentCenterUser()
and update createUserForDifferentCenter() to call that method instead of
getRolesForUser() so the different-center user's roles can be configured
independently (update the List<String> to use the new getter and adjust any
config parsing there).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java`:
- Around line 597-604: The loop blindly re-clicks the mutating operation
manageApplicationsPage.clickOnUploadButton(), which can double-submit if the UI
is slow; change the logic to perform a single click then wait for a clear state
transition (for example implement/wait for a method like
manageApplicationsPage.waitForUploadToSettle(), waitForRowDisappearance(), or
waitUntilUploadStatusChanges()) and only attempt a retry if that wait reports an
explicit failure/timeout; use
manageApplicationsPage.isZeroApplicationDisplayed() or an explicit error
indicator to decide whether to retry, and remove immediate re-clicks while the
prior upload is still pending.
- Line 163: The test currently calls BasePage.disableWifiAndData() without
guaranteeing re-enablement; wrap the test logic that runs while offline in a
try/finally so BasePage.enableWifiAndData() is always called in the finally
block; locate the call to BasePage.disableWifiAndData() in
CreatePacketWithoutNetwork and replace the surrounding test flow to ensure
BasePage.enableWifiAndData() is invoked in finally (also update the similar
occurrences around the lines referenced 539-540).

In `@ui-test/src/main/java/regclient/androidTestCases/Settings.java`:
- Line 148: The test re-enabled a known-flaky assertion: remove or guard the
assertTrue(settingsPage.isNoDevicesFoundDisplayed(), ...) in the Settings test
that follows setAllToNotReadyAndSave(); instead revert to the previous safe
state by commenting out that assertion or wrapping it in an
environment-check/feature-flag so it only runs when MockSBI visibility is
guaranteed (locate the assert in Settings.java and the related
setAllToNotReadyAndSave() call to apply the change).

In `@ui-test/src/main/java/regclient/api/AdminTestUtil.java`:
- Around line 143-150: AdminTestUtil calls
propsKernel.getProperty("diffRegCenterId") and passes the result to
mapUserToCenter which can send a null "regCenterId"; add a null/empty check
before calling mapUserToCenter in AdminTestUtil (validate
propsKernel.getProperty("diffRegCenterId") and throw or log/fail fast) and/or
ensure Kernel.properties contains a diffRegCenterId entry; specifically update
the code around KeycloakUserManager.createUserForDifferentCenter() to validate
the diffRegCenterId value and avoid invoking mapUserToCenter with a null/empty
id.

In `@ui-test/src/main/java/regclient/page/BasePage.java`:
- Around line 217-231: The drag targets in cropCaptureImage (and similarly
cropCaptureImageEnglishFrench) use hardcoded viewport coordinates (e.g., 260,320
and 623,261) which break on different device resolutions; replace those
hardcoded numbers by computing target coordinates from the element bounds (use
element.getLocation() and element.getSize() or getCenterOfElement and
add/subtract offsets based on element width/height or fractions) and pass the
computed absolute viewport coordinates into createPointerMove so the pointer
moves relative to the element center/size rather than fixed pixels.

In `@ui-test/src/main/java/regclient/page/KeycloakPage.java`:
- Around line 136-138: clickOnPasswordOption currently calls the WebElement
overloads (scrollHorizontallyUntilVisible(passwordOption) and
clickOnElement(passwordOption)) which can cause staleness; change it to use the
locator-based overloads on BasePage instead: call
scrollHorizontallyUntilVisible(<By locator for passwordOption>) and
clickOnElement(<By locator for passwordOption>) so the element is re-resolved if
it becomes stale (use the existing By field or add one named e.g.
passwordOptionLocator if missing).

In
`@ui-test/src/main/java/regclient/pages/english/DocumentUploadPageEnglish.java`:
- Around line 77-87: The isPacketSizeDisplayed method currently uses
String.matches which requires the whole contentDescription to match and can
false-negative if there is surrounding text; update isPacketSizeDisplayed in
DocumentUploadPageEnglish to compile a Pattern like "Size:
\\d+(\\.\\d+)?\\s?(KB|MB)" and use Matcher.find() on
packetSize.getAttribute("contentDescription") (or String#contains with a looser
regex) to check for the size substring, keeping the
driver.findElement(By.xpath(...)) lookup and the existing exception handling.

In
`@ui-test/src/main/java/regclient/pages/english/ManageApplicationsPageEnglish.java`:
- Around line 314-326: In scrollTillDisplayingApplicationCountVisible() the
lookup uses textContains("Displaying") but the page exposes the count via
accessibility/content-desc keys (displayZeroApplication /
displayOneApplication), so update the visibility check to look for those
accessibility locators instead of text: query for
driver.findElements(MobileBy.AccessibilityId("displayZeroApplication")) and
driver.findElements(MobileBy.AccessibilityId("displayOneApplication")) (or a
single descriptionContains selector that matches either) and return when found;
keep the existing scrollBackward() loop and only scroll if neither accessibility
element is present.

---

Outside diff comments:
In
`@ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateDocuments.java`:
- Line 379: The second preview assertion incorrectly calls
previewPage.isNewRegistrationTitleDisplayed() after navigating back through the
edit flow; replace that call with previewPage.updateUINTitleDisplayed() so both
preview checks validate the Update UIN title (apply the same replacement where
similar assertions occur around the other affected spots such as the assertions
near lines referenced in the review).

In `@ui-test/src/main/java/regclient/page/BasePage.java`:
- Around line 657-669: The hard cap of 5 swipes in scrollToTop() and
scrollToBottom() can leave long pages mid-scroll; update these helpers to stop
on a stable boundary rather than a fixed small count: repeatedly call
swipeDown()/swipeUp() until either the page/viewport stops changing (detect via
stable page source, stable element position, or an isAtTop()/isAtBottom() check)
or a much larger safety cap (e.g., 20) is reached; modify scrollToTop(),
scrollToBottom() to implement this loop and use swipeDown()/swipeUp() as before,
so callers that assert visibility after scrolling reliably see the intended
viewport.

In `@ui-test/src/main/java/regclient/page/KeycloakPage.java`:
- Around line 83-88: The scroll is running in WEBVIEW because
openKeycloakWebView() leaves the driver in WEBVIEW; switch the driver to the
native context before attempting the native horizontal scroll. Change the order
in KeycloakPage so that you call ((SupportsContextSwitching)
driver).context("NATIVE_APP") (or a helper that switches context) immediately
before calling scrollHorizontallyUntilVisible(nativePwd), then proceed with the
WebDriverWait for nativePwd; keep the subsequent flow (waiting and any later
context switches) intact.

In
`@ui-test/src/main/java/regclient/pages/english/SupervisorBiometricVerificationpageEnglish.java`:
- Around line 200-202: The isExceptionScanTitleDisplayed() method currently
returns isElementDisplayed(exceptionScanTitle) but omits the scrollToTop() call
used by the sibling checks; update isExceptionScanTitleDisplayed() in
SupervisorBiometricVerificationpageEnglish to call scrollToTop() before checking
isElementDisplayed(exceptionScanTitle) so its viewport behavior matches the
other thumb/face methods.

In
`@ui-test/src/main/java/regclient/pages/english/UpdateOperatorBiometricspageEnglish.java`:
- Around line 207-209: The isExceptionScanTitleDisplayed() method omits the
scrollToTop() call used by the other scan-title checks; update the method
(isExceptionScanTitleDisplayed) to call scrollToTop() before returning
isElementDisplayed(exceptionScanTitle) so the exception scan title is always
scrolled into view prior to verification, matching the pattern used in
SupervisorBiometricVerificationpageEnglish and the other four scan-title checks.

---

Nitpick comments:
In
`@ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java`:
- Around line 226-401: The loop over screenOrder in CreatePacketWithoutNetwork
silently ignores unknown screen ids; add an else branch after the existing
if/else-if chain that throws an IllegalStateException (or fails the test) with
the unknown screen id to fail fast, and before the loop add a short verification
that screenOrder contains the mandatory screens (e.g., "consentdet"/"consent",
"DemographicDetails", "Documents", "BiometricDetails")—use
screenOrder.contains(...) and throw a clear IllegalStateException if any
mandatory screen is missing so the test fails immediately and points to spec
drift.

In `@ui-test/src/main/java/regclient/androidTestCases/Settings.java`:
- Around line 172-173: Remove the fixed sleep BasePage.waitTime(10) and replace
it with an explicit, condition-based wait for the specific sync UI element
before calling settingsPage.clickOnSyncButton("Master Data Sync"); specifically,
wait until the "Master Data Sync" job card or its sync button is visible and/or
clickable (use your project's WebDriverWait/ExpectedConditions helper or add a
settingsPage.waitForSyncJob("Master Data Sync") that waits for
visibility/clickability) and then invoke settingsPage.clickOnSyncButton; ensure
the hard wait is deleted so the test uses the condition-based wait for
reliability and lower latency.

In `@ui-test/src/main/java/regclient/api/KeycloakUserManager.java`:
- Around line 301-361: The role assignment in createUserForDifferentCenter() is
using ArcConfigManager.getRolesForUser(), which is inconsistent with other
creators; add a dedicated getter like
ArcConfigManager.getRolesForDifferentCenterUser() and update
createUserForDifferentCenter() to call that method instead of getRolesForUser()
so the different-center user's roles can be configured independently (update the
List<String> to use the new getter and adjust any config parsing there).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 24b0026f-9b04-4142-a4e7-95fff46c38a3

📥 Commits

Reviewing files that changed from the base of the PR and between b006565 and 3a9be58.

📒 Files selected for processing (29)
  • ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java
  • ui-test/src/main/java/regclient/androidTestCases/LoginTest.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdultException.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationAdultUploadMultipleDoccuments.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationInfant.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinor.java
  • ui-test/src/main/java/regclient/androidTestCases/NewRegistrationMinorException.java
  • ui-test/src/main/java/regclient/androidTestCases/Settings.java
  • ui-test/src/main/java/regclient/androidTestCases/UpdateMyUinUpdateDocuments.java
  • ui-test/src/main/java/regclient/api/AdminTestUtil.java
  • ui-test/src/main/java/regclient/api/ArcConfigManager.java
  • ui-test/src/main/java/regclient/api/KeycloakUserManager.java
  • ui-test/src/main/java/regclient/page/BasePage.java
  • ui-test/src/main/java/regclient/page/KeycloakPage.java
  • ui-test/src/main/java/regclient/page/MockSBIPage.java
  • ui-test/src/main/java/regclient/page/SettingsPage.java
  • ui-test/src/main/java/regclient/pages/arabic/SettingsPageArabic.java
  • ui-test/src/main/java/regclient/pages/english/ApplicantBiometricsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/DemographicDetailsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/DocumentUploadPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/IntroducerBiometricPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/ManageApplicationsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/PreviewPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/SelectLanguagePageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/SettingsPageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/SupervisorBiometricVerificationpageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/UpdateOperatorBiometricspageEnglish.java
  • ui-test/src/main/java/regclient/pages/english/UpdateUINPageEnglish.java
  • ui-test/src/main/java/regclient/pages/french/SettingsPageFrench.java
🛑 Comments failed to post (8)
ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java (2)

163-163: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Always restore connectivity in a finally block.

If any assertion fails between disabling and re-enabling Wi‑Fi/data, the device stays offline and can poison every later test in the suite.

Suggested fix
-		BasePage.disableWifiAndData();
-
-		loginPage.selectLanguage();
-		...
-		BasePage.enableWifiAndData();
-		BasePage.waitTime(10);
+		BasePage.disableWifiAndData();
+		try {
+			loginPage.selectLanguage();
+			...
+			BasePage.enableWifiAndData();
+			BasePage.waitTime(10);
+			...
+		} finally {
+			BasePage.enableWifiAndData();
+		}

Also applies to: 539-540

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java`
at line 163, The test currently calls BasePage.disableWifiAndData() without
guaranteeing re-enablement; wrap the test logic that runs while offline in a
try/finally so BasePage.enableWifiAndData() is always called in the finally
block; locate the call to BasePage.disableWifiAndData() in
CreatePacketWithoutNetwork and replace the surrounding test flow to ensure
BasePage.enableWifiAndData() is invoked in finally (also update the similar
occurrences around the lines referenced 539-540).

597-604: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t blind-retry the upload action.

clickOnUploadButton() is a mutating operation. Re-clicking it before the first attempt settles can double-submit the same packet if the UI is just slow to refresh. Retry only after a confirmed failure, or wait for a state change such as row disappearance/upload status transition before clicking again.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ui-test/src/main/java/regclient/androidTestCases/CreatePacketWithoutNetwork.java`
around lines 597 - 604, The loop blindly re-clicks the mutating operation
manageApplicationsPage.clickOnUploadButton(), which can double-submit if the UI
is slow; change the logic to perform a single click then wait for a clear state
transition (for example implement/wait for a method like
manageApplicationsPage.waitForUploadToSettle(), waitForRowDisappearance(), or
waitUntilUploadStatusChanges()) and only attempt a retry if that wait reports an
explicit failure/timeout; use
manageApplicationsPage.isZeroApplicationDisplayed() or an explicit error
indicator to decide whether to retry, and remove immediate re-clicks while the
prior upload is still pending.
ui-test/src/main/java/regclient/androidTestCases/Settings.java (1)

148-148: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reintroduced known-failing assertion in this environment.

Line 148 re-enables isNoDevicesFoundDisplayed() in the exact path previously documented as not visible after switching back from MockSBI, which can make this test fail nondeterministically in CI.

Suggested stabilization diff
-		assertTrue(settingsPage.isNoDevicesFoundDisplayed(), "Verify if no devices found displayed");
+		// Intentionally skipped in current env: banner is not consistently visible after app switch.
+		// Keep scan button assertion as the stable post-condition.
+		// assertTrue(settingsPage.isNoDevicesFoundDisplayed(), "Verify if no devices found displayed");

Based on learnings: In ui-test/src/main/java/regclient/androidTestCases/Settings.java, settingsPage.isNoDevicesFoundDisplayed() is intentionally commented out because it is not currently visible in the test environment after setAllToNotReadyAndSave().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/androidTestCases/Settings.java` at line 148,
The test re-enabled a known-flaky assertion: remove or guard the
assertTrue(settingsPage.isNoDevicesFoundDisplayed(), ...) in the Settings test
that follows setAllToNotReadyAndSave(); instead revert to the previous safe
state by commenting out that assertion or wrapping it in an
environment-check/feature-flag so it only runs when MockSBI visibility is
guaranteed (locate the assert in Settings.java and the related
setAllToNotReadyAndSave() call to apply the change).
ui-test/src/main/java/regclient/api/AdminTestUtil.java (1)

143-150: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for diffRegCenterId property definition in config files

rg -n "diffRegCenterId" --type properties --type xml --type json

Repository: mosip/android-registration-client

Length of output: 112


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find all occurrences (code + config) of the key
rg -n "diffRegCenterId" .

# 2) Specifically look for likely definition patterns in .properties / .env / YAML / JSON / XML
rg -n "(^|[[:space:]])diffRegCenterId[[:space:]]*=" . -g'*.properties' -g'*.env' -g'*.yml' -g'*.yaml' -g'*.json' -g'*.xml' -g'*.conf' || true
rg -n "\"diffRegCenterId\"[[:space:]]*:" . -g'*.json' -g'*.yaml' -g'*.yml' || true
rg -n "diffRegCenterId" . -g'*.xml' || true

# 3) Locate propsKernel.getProperty call site(s) for context on validation/behavior when missing
rg -n "getProperty\\(\"diffRegCenterId\"\\)" .

# 4) Find where propsKernel is defined/loaded to understand missing-property behavior
rg -n "propsKernel" ui-test/src/main/java/regclient/api/AdminTestUtil.java
rg -n "class .*PropsKernel|propsKernel.*getProperty|getProperty\\(" ui-test/src/main/java/regclient/api/AdminTestUtil.java ui-test/src/main/java -S || true

Repository: mosip/android-registration-client

Length of output: 17387


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the relevant code around the snippet
sed -n '120,175p' ui-test/src/main/java/regclient/api/AdminTestUtil.java | nl -ba

# Inspect how propsKernel.getProperty is implemented/validated
sed -n '1,120p' ui-test/src/main/java/regclient/utils/PropertiesReader.java | nl -ba

# Find where propsKernel is created/loaded
rg -n "propsKernel" ui-test/src/main/java/regclient -S

Repository: mosip/android-registration-client

Length of output: 120


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== AdminTestUtil snippet (approx. 120-175) ==="
sed -n '120,175p' ui-test/src/main/java/regclient/api/AdminTestUtil.java | cat -n

echo "=== PropertiesReader implementation ==="
sed -n '1,120p' ui-test/src/main/java/regclient/utils/PropertiesReader.java | cat -n

echo "=== Where propsKernel is created/loaded ==="
rg -n "propsKernel" ui-test/src/main/java/regclient -S

Repository: mosip/android-registration-client

Length of output: 10821


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate Kernel.properties and print any matching keys
fd -a -e properties 'Kernel.properties' ui-test || true
fd -a 'Kernel.properties' . || true

# Search all config/*.properties that likely back propsKernel
rg -n "diffRegCenterId" . -g'*.properties' || true
rg -n "diffRegCenterId" ui-test -g'*.properties' || true

# Show the relevant line(s) and some surrounding context in Kernel.properties (if present)
for f in $(fd -a 'Kernel.properties' ui-test); do
  echo "=== $f ==="
  rg -n "diffRegCenterId" "$f" || true
done

# Also inspect the code that loads propsKernel (BaseTestCase / KeycloakUserManager getproperty)
rg -n "getproperty\\(TestRunner\\.getResourcePath\\(\\) \\+ \"/config/Kernel\\.properties\"\\)" ui-test/src/main/java/regclient/api -S
sed -n '1,120p' ui-test/src/main/java/regclient/api/BaseTestCase.java | cat -n
sed -n '1,120p' ui-test/src/main/java/regclient/api/KeycloakUserManager.java | cat -n

Repository: mosip/android-registration-client

Length of output: 11833


🏁 Script executed:

#!/bin/bash
set -euo pipefail

KERNEL="ui-test/src/main/resources/config/Kernel.properties"

echo "=== Does Kernel.properties contain diffRegCenterId? ==="
rg -n "diffRegCenterId" "$KERNEL" || true
echo

echo "=== Kernel.properties lines mentioning regCenterId/zoneMapping (context) ==="
rg -n "(regCenterId|zoneMappingUrl|zoneMappingActivateUrl)" "$KERNEL" || true
echo

echo "=== mapUserToCenter implementation in AdminTestUtil.java ==="
rg -n "mapUserToCenter\\(" ui-test/src/main/java/regclient/api/AdminTestUtil.java
# print surrounding method
start=$(rg -n "mapUserToCenter\\(" ui-test/src/main/java/regclient/api/AdminTestUtil.java | head -n1 | cut -d: -f1)
# show a window around the first occurrence
sed -n "$((start-10)),$((start+80))p" ui-test/src/main/java/regclient/api/AdminTestUtil.java | cat -n

Repository: mosip/android-registration-client

Length of output: 6550


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Confirm where diffRegCenterId is defined anywhere in the repo configs
rg -n "diffRegCenterId" . -g'*.properties' -g'*.env' -g'*.yml' -g'*.yaml' -g'*.json' -g'*.xml' -g'*.conf' || true

# 2) Inspect mapUserToCenter method behavior when center is null/empty
sed -n '200,320p' ui-test/src/main/java/regclient/api/AdminTestUtil.java | cat -n

Repository: mosip/android-registration-client

Length of output: 6206


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Global search for the key (all file types)
rg -n "diffRegCenterId" . || true

# Show nearby kernel keys for context
KERNEL="ui-test/src/main/resources/config/Kernel.properties"
rg -n "iam-users-to-create-differentCenterUser|diffRegCenterId|regCenterId|zone" "$KERNEL" || true

Repository: mosip/android-registration-client

Length of output: 477


Define/validate diffRegCenterId for different-center user mapping

  • AdminTestUtil uses propsKernel.getProperty("diffRegCenterId") (line 149) but diffRegCenterId is not present in ui-test/src/main/resources/config/Kernel.properties (only referenced in this code), so mapUserToCenter will send "regCenterId": null to /v1/masterdata/usercentermapping, breaking the “differentCenterUser” initialization path.
  • Add diffRegCenterId to Kernel.properties and/or fail fast with a non-null validation before calling mapUserToCenter.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/api/AdminTestUtil.java` around lines 143 -
150, AdminTestUtil calls propsKernel.getProperty("diffRegCenterId") and passes
the result to mapUserToCenter which can send a null "regCenterId"; add a
null/empty check before calling mapUserToCenter in AdminTestUtil (validate
propsKernel.getProperty("diffRegCenterId") and throw or log/fail fast) and/or
ensure Kernel.properties contains a diffRegCenterId entry; specifically update
the code around KeycloakUserManager.createUserForDifferentCenter() to validate
the diffRegCenterId value and avoid invoking mapUserToCenter with a null/empty
id.
ui-test/src/main/java/regclient/page/BasePage.java (1)

217-231: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Compute crop targets from the element bounds, not fixed viewport pixels.

Both crop helpers now drag to absolute coordinates (260,320 / 623,261). That makes the gesture depend on the exact device resolution/orientation used when this was recorded, so on a different emulator/phone the drag can miss the crop area entirely.

Suggested direction
 protected void cropCaptureImage(WebElement element) {
+    Rectangle rect = element.getRect();
+    int endX = rect.x + (int) (rect.width * 0.75);
+    int endY = rect.y + (int) (rect.height * 0.25);
     PointerInput finger1 = new PointerInput(PointerInput.Kind.TOUCH, "finger1");
     Sequence sequence = new Sequence(finger1, 1)
             .addAction(finger1.createPointerMove(Duration.ZERO, PointerInput.Origin.viewport(),
                     getCenterOfElement(element.getLocation(), element.getSize())))
             .addAction(finger1.createPointerDown(PointerInput.MouseButton.LEFT.asArg()))
             .addAction(new Pause(finger1, Duration.ofMillis(200)))
-            .addAction(finger1.createPointerMove(Duration.ofMillis(500), PointerInput.Origin.viewport(), 260, 320))
+            .addAction(finger1.createPointerMove(Duration.ofMillis(500), PointerInput.Origin.viewport(), endX, endY))
             .addAction(finger1.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
     driver.perform(Collections.singletonList(sequence));
 }

Apply the same pattern to cropCaptureImageEnglishFrench(...).

Also applies to: 234-249

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/page/BasePage.java` around lines 217 - 231,
The drag targets in cropCaptureImage (and similarly
cropCaptureImageEnglishFrench) use hardcoded viewport coordinates (e.g., 260,320
and 623,261) which break on different device resolutions; replace those
hardcoded numbers by computing target coordinates from the element bounds (use
element.getLocation() and element.getSize() or getCenterOfElement and
add/subtract offsets based on element width/height or fractions) and pass the
computed absolute viewport coordinates into createPointerMove so the pointer
moves relative to the element center/size rather than fixed pixels.
ui-test/src/main/java/regclient/page/KeycloakPage.java (1)

136-138: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the locator-based horizontal scroll here too.

This still calls the WebElement overload, so if passwordOption goes stale while the tab strip is being swiped it can never be re-found. The new By overload added in BasePage fixes exactly that failure mode.

Suggested change
 public void clickOnPasswordOption() {
-    scrollHorizontallyUntilVisible(passwordOption);
+    scrollHorizontallyUntilVisible(By.xpath("//android.widget.TextView[`@text`='Password']"));
     clickOnElement(passwordOption);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/page/KeycloakPage.java` around lines 136 -
138, clickOnPasswordOption currently calls the WebElement overloads
(scrollHorizontallyUntilVisible(passwordOption) and
clickOnElement(passwordOption)) which can cause staleness; change it to use the
locator-based overloads on BasePage instead: call
scrollHorizontallyUntilVisible(<By locator for passwordOption>) and
clickOnElement(<By locator for passwordOption>) so the element is re-resolved if
it becomes stale (use the existing By field or add one named e.g.
passwordOptionLocator if missing).
ui-test/src/main/java/regclient/pages/english/DocumentUploadPageEnglish.java (1)

77-87: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

matches() may produce false negatives if content-desc has surrounding text.

The XPath uses contains(@content-desc,'Size:'), so the matched element's contentDescription could legitimately include extra text (e.g. a prefix/suffix). String.matches() requires the entire string to match the pattern, so any surrounding text makes this return false and would fail the downstream assertTrue(...isPacketSizeDisplayed()) in CreatePacketWithoutNetwork. Prefer a find()-based check.

🛡️ Proposed fix
 			String sizeText = packetSize.getAttribute("contentDescription");
-			return sizeText.matches("Size: \\d+(\\.\\d+)?\\s?(KB|MB)");
+			return sizeText != null
+					&& java.util.regex.Pattern.compile("Size:\\s*\\d+(\\.\\d+)?\\s?(KB|MB)")
+							.matcher(sizeText).find();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-test/src/main/java/regclient/pages/english/DocumentUploadPageEnglish.java`
around lines 77 - 87, The isPacketSizeDisplayed method currently uses
String.matches which requires the whole contentDescription to match and can
false-negative if there is surrounding text; update isPacketSizeDisplayed in
DocumentUploadPageEnglish to compile a Pattern like "Size:
\\d+(\\.\\d+)?\\s?(KB|MB)" and use Matcher.find() on
packetSize.getAttribute("contentDescription") (or String#contains with a looser
regex) to check for the size substring, keeping the
driver.findElement(By.xpath(...)) lookup and the existing exception handling.
ui-test/src/main/java/regclient/pages/english/ManageApplicationsPageEnglish.java (1)

314-326: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Match the application-count lookup to the page's accessibility locators.

This helper searches for textContains("Displaying"), but this page exposes the count as accessibility/content-desc (displayZeroApplication / displayOneApplication). In practice that means the method can keep scrolling even when the count is already visible.

Proposed fix
-			if (driver.findElements(MobileBy.AndroidUIAutomator("new UiSelector().textContains(\"Displaying\")"))
+			if (driver.findElements(MobileBy.AndroidUIAutomator("new UiSelector().descriptionContains(\"Displaying\")"))
 					.size() > 0) {
 				return;
 			}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	public void scrollTillDisplayingApplicationCountVisible() {

		for (int i = 0; i < 3; i++) {

			if (driver.findElements(MobileBy.AndroidUIAutomator("new UiSelector().descriptionContains(\"Displaying\")"))
					.size() > 0) {
				return;
			}

			driver.findElement(MobileBy.AndroidUIAutomator(
					"new UiScrollable(new UiSelector().className(\"android.widget.HorizontalScrollView\"))"
							 ".setAsHorizontalList()" + ".scrollBackward()"));
		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@ui-test/src/main/java/regclient/pages/english/ManageApplicationsPageEnglish.java`
around lines 314 - 326, In scrollTillDisplayingApplicationCountVisible() the
lookup uses textContains("Displaying") but the page exposes the count via
accessibility/content-desc keys (displayZeroApplication /
displayOneApplication), so update the visibility check to look for those
accessibility locators instead of text: query for
driver.findElements(MobileBy.AccessibilityId("displayZeroApplication")) and
driver.findElements(MobileBy.AccessibilityId("displayOneApplication")) (or a
single descriptionContains selector that matches either) and return when found;
keep the existing scrollBackward() loop and only scroll if neither accessibility
element is present.

@Prafulrakhade Prafulrakhade merged commit c77db8c into mosip:develop Jun 4, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants