fix(test): handle non-dismissable login picker in Chrome Custom Tab page object - #2990
Merged
wmathurin merged 5 commits intoAug 13, 2026
Merged
Conversation
…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
force-pushed
the
fix-chrome-tab-picker-backout
branch
from
August 13, 2026 03:19
64dd94a to
3160b2b
Compare
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
force-pushed
the
fix-chrome-tab-picker-backout
branch
from
August 13, 2026 03:21
3160b2b to
cc0322c
Compare
…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.
brandonpage
approved these changes
Aug 13, 2026
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 |
Contributor
There was a problem hiding this comment.
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. |
Contributor
There was a problem hiding this comment.
NIT: couldn't hurt to log here.
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
Test plan