Skip to content

fix(test): handle non-dismissable login picker in Chrome Custom Tab page object - #2990

Merged
wmathurin merged 5 commits into
forcedotcom:devfrom
wmathurin:fix-chrome-tab-picker-backout
Aug 13, 2026
Merged

fix(test): handle non-dismissable login picker in Chrome Custom Tab page object#2990
wmathurin merged 5 commits into
forcedotcom:devfrom
wmathurin:fix-chrome-tab-picker-backout

Conversation

@wmathurin

@wmathurin wmathurin commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Root cause: PR #2983 (merged Aug 11) made the login-server picker non-dismissable — it removed the close button from `LoginServerPicker` and blocked swipe-to-dismiss. After a Chrome Custom Tab closes (via `backOutToLoginActivity`), the SDK raises the picker. Tests that then called `openLoginOptions()` or `changeServerByUrl()` were failing because both methods tried to tap `MORE_OPTIONS_BUTTON` in the top app bar, which is behind the picker's modal scrim.

Fixes:

  • `ChromeCustomTabPageObject.backOutToLoginActivity()`: simplified — closes the tab and waits for either the picker or the top bar to be reachable, without trying to dismiss the picker (which is intentionally non-dismissable).
  • `LoginPageObject.openLoginOptions()`: detects whether the picker is showing before tapping the top bar. If it is, routes through `PICKER_DEV_SUPPORT_BUTTON` (the debug-only "Developer Support" button in the picker header, added alongside the non-dismissable picker change) instead of the blocked `MORE_OPTIONS_BUTTON` path.
  • `LoginPageObject.changeServerByUrl()`: detects whether the picker is already showing (e.g. left up by `backOutToLoginActivity`) and skips the open-picker steps, selecting the server directly.

Test plan

  • `testECAJwt_SubsetScopes_NotHybrid` — previously failing, now passes (22s on Pixel 9 Pro XL AVD API 35)
  • Broader test suite (other tests that exercise the `backOutToLoginActivity → openLoginOptions/changeServerByUrl` path) should be validated in CI

…age object

Since PR forcedotcom#2983, the login-server picker is modal and non-dismissable — it
has no close button, and the top app bar's overflow menu is behind its scrim.
Tests that called backOutToLoginActivity() followed by openLoginOptions()
were failing because openLoginOptions() tried to tap MORE_OPTIONS_BUTTON
while the picker was covering it.

Fix: backOutToLoginActivity() now simply closes the Chrome tab and waits
for either the picker or the top bar to be reachable (whichever the SDK
raises). openLoginOptions() then detects whether the picker is showing and,
if so, routes through PICKER_DEV_SUPPORT_BUTTON (the debug-only button in
the picker's own header) instead of the obscured top-bar path.
@wmathurin
wmathurin force-pushed the fix-chrome-tab-picker-backout branch from 64dd94a to 3160b2b Compare August 13, 2026 03:19
changeServerByUrl() now detects if the login-server picker is already
visible (left open by backOutToLoginActivity() after a tab close) and
skips the MORE_OPTIONS_BUTTON → MENU_ITEM_PICK_SERVER path, which is
blocked by the picker's modal scrim. If already showing, it selects
the server directly.
@wmathurin
wmathurin force-pushed the fix-chrome-tab-picker-backout branch from 3160b2b to cc0322c Compare August 13, 2026 03:21
@wmathurin
wmathurin requested a review from brandonpage August 13, 2026 03:23
…h needed

After backOutToLoginActivity() the server picker can be left showing.
ensureRegularAuthServer() was calling setSelectedLoginServer() directly,
which doesn't close the picker UI — leaving it covering the WebView for
in-app WebView tests (User Agent Flow, forceAdvancedAuthentication=false).

Fix: detect whether the picker is showing; if so, dismiss it via
changeServerByUrl() (tapping the row triggers reloadWebView and closes
the sheet) rather than calling setSelectedLoginServer() directly.
- Increased TIMEOUT_MS from 10/15s to 15/20s (local/FTL) and added
  WEBVIEW_ACTION_TIMEOUT_MS (45s local / 60s FTL) in BasePageObject to
  handle "Atom evaluation returned null" failures when the login form
  takes longer than the old 10s budget to render after a server-picker
  dismissal triggers a WebView reload.
- Added waitForPageLoad() in LoginPageObject (watches LOADING_INDICATOR
  appear/disappear) and waitForLoginScreen() (waits for MORE_OPTIONS_BUTTON);
  login() now calls waitForPageLoad() before setting the username and uses
  WEBVIEW_ACTION_TIMEOUT_MS for the retry budget.
- In AuthFlowTest.ensureRegularAuthServer(), after changeServerByUrl() for
  the picker-is-showing path, calls loginPage.waitForLoginScreen() to ensure
  the Compose hierarchy is fully settled before returning.
- Fixed UITestConfig Json parser to use Json { ignoreUnknownKeys = true }
  so unknown fields in ui_test_config.json do not crash parsing on this branch.
Comment on lines +55 to +61
* Extended timeout for Espresso WebView actions ([retryWebAction]) that wait for
* server-rendered login page content. The Salesforce sandbox login page can take up to
* ~30 s to render interactive form elements after [onPageFinished] fires; this budget
* covers that latency with headroom for both local emulators and Firebase Test Lab.
*/
val WEBVIEW_ACTION_TIMEOUT_MS: Long by lazy {
if (isFtl) 60_000 else 45_000

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Have you actually seen it take 30 seconds? I don't think I have. It really does not matter much since this is the max time it will wait.

Comment on lines +125 to +126
// Best-effort: if the top bar is not reachable within the timeout the caller's
// subsequent actions will fail with descriptive messages.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

NIT: couldn't hurt to log here.

@brandonpage

Copy link
Copy Markdown
Contributor

We may still need to update the test run timeouts here and the other 3 places in the same file.

- Soften "up to ~30 s" to "20–30 s" in WEBVIEW_ACTION_TIMEOUT_MS kdoc
  (aligns with the same observation in waitForPageLoad's comment)
- Add Log.w in waitForLoginScreen catch block per reviewer request
@wmathurin
wmathurin merged commit 48bef2a into forcedotcom:dev Aug 13, 2026
8 of 9 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.

2 participants