Skip to content

Add UI Tests#2847

Open
brandonpage wants to merge 6 commits intoforcedotcom:devfrom
brandonpage:compose-ui-test
Open

Add UI Tests#2847
brandonpage wants to merge 6 commits intoforcedotcom:devfrom
brandonpage:compose-ui-test

Conversation

@brandonpage
Copy link
Contributor

@brandonpage brandonpage commented Mar 6, 2026

Tests added:

  • BootConfigLoginTests - tests that use the (as currently defined) CA Opaque app in AuthFlowTester's bootconfig.xml as is.
  • CAScopeSelectionLoginTests - Connected App tests with mixed scopes, flow and hybrid token options.
  • ECALoginTests - ECA Opaque and JWT tests with various login options.
  • BeaconLoginTests - Beacon Opaque and JWT tests with various login options.
  • MultiUserLoginTests - Tests with multiple users logged in. Different app types, scopes, etc are used.
    • The Token Migration tests in this class also ensure that auth tokens are stored/retained correctly since the account, rest client, etc are recreated on user switch. This is important since it is not possible to restart or cold boot the app mid test (like iOS does) with Compose UI Test or Espresso.

The new testMultiUser_tokenMigration_backgroundUser test uncovered the fact that token migration would always set the specified user as the current user. That has been fixed in this PR and unit tests have been added to cover the SDK code change.

To make the above test possible the test app UI was updated to allow for user selection when migrating:
share_5015376007694299033

Other Noteworthy Changes:

  • AuthFlowTester now has a README.md that describes the UI Tests coverage and how to use the app for manual testing.
  • CI has been updated to make efficient use of as many test users as are provided in ui_test_config.json. All users will be used at once for single user tests and the MultiUserLoginTests are batched to run as many as possible but avoid runs using the same user simultaneously.
  • CI will run a handful of individual tests (5 as of now) on a single API level for PRs.
  • The AuthFlowTester debug APK is now archived on every test run.

There are separate WIs for Advanced Auth and Welcome test that will be finished soon.

@github-actions
Copy link

github-actions bot commented Mar 6, 2026

1 Warning
⚠️ Big PR, try to keep changes smaller if you can.

Generated by 🚫 Danger

sidCookieName = callbackUrlParams.get(SID_COOKIE_NAME);
parentSid = callbackUrlParams.get(PARENT_SID);
tokenFormat = callbackUrlParams.get(TOKEN_FORMAT);
tokenFormat = callbackUrlParams.getOrDefault(TOKEN_FORMAT, "");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was a bug that came out of UI testing. The tokenFormat for opaque tokens would either be empty string or null depending on when/where the user was created so it won't be null anywhere after this change.

verify(exactly = 0) { startMainActivity.invoke() }
}

@Test
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unit Tests for SDK change.

// Init user logging
updateLoggingPrefs(account)
if (tokenMigration) {
userAccountManager.persistAccount(account)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the main SDK change. It avoids changing the current user and sending the user switch broadcast that should not be done for token migration.

* separate process that Espresso and Compose Test APIs cannot access.
*/
class CustomTabPageObject {
class ChromeCustomTabPageObject(composeTestRule: ComposeTestRule): LoginPageObject(composeTestRule) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The AdvancedAuthLoginTests are not included in this PR (still a little org setup to finish and a Firebase complication to work around) but will be in the next.

Comment on lines +40 to +45
val isFtl: Boolean by lazy {
Settings.System.getString(
InstrumentationRegistry.getInstrumentation().targetContext.contentResolver,
/* name = */ "firebase.test.lab"
) == "true"
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This nifty trick allows us to do things like set different timeout values for local vs CI runs or skip tests in certain scenarios (I am seeing a lot of instances of Chrome crashing on lower API levels in Firebase :/).

import com.salesforce.samples.authflowtester.testUtility.KnownAppConfig.CA_OPAQUE
import org.junit.Rule

abstract class AuthFlowTest {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

New base test class that handles all of the boiler-plate setup and common verification functions.

Comment on lines +65 to +70
val user: KnownUserConfig by lazy {
val minSdk = InstrumentationRegistry.getInstrumentation().targetContext
.applicationInfo.minSdkVersion
val userNumber = (Build.VERSION.SDK_INT - minSdk) % KnownUserConfig.values().count()
KnownUserConfig.values()[userNumber]
}
Copy link
Contributor Author

@brandonpage brandonpage Mar 6, 2026

Choose a reason for hiding this comment

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

This might look a little strange, but it ensures each test runs uses a different user. By starting at minSdkVersion we can basically count up and never have a collision:

API 28 -> User 1
API 29 -> User 2
...

reusable-ui-workfow.yaml runs batches with a max size to match the number of users (for single user tests).

Comment on lines +73 to +76
val otherUser: KnownUserConfig by lazy {
val userNumber = (user.ordinal + 1) % KnownUserConfig.values().count()
KnownUserConfig.values()[userNumber]
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Multi-User tests are run separately and the bash in reusable-ui-workfow.yaml groups API level to avoid collisions. So the groups look like:

[API 28, API 30], [API 32, API 34], ... [API 33, API 35], etc.

Since we can only run 2 levels at a time like this I should really add a 6th user, it would decrease test time for multi-user by 50%.

@brandonpage
Copy link
Contributor Author

As always, the tests will not run with the latest yaml configuration for security (but I will update you with the results from my fork).

@wmathurin @JohnsonEricAtSalesforce As I was experimenting and testing the new (complicated) bash batching that we could avoid the above limitation by moving all of the bash from yaml to scripts. As long as the name (and parameters) of those scripts don't change the updates would be immediately seen on PRs. As long as we don't run them before the permission check it should be safe. It could make local testing a bit easier too. Thoughts?

@codecov
Copy link

codecov bot commented Mar 6, 2026

Codecov Report

❌ Patch coverage is 88.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.60%. Comparing base (115372e) to head (0164066).

Files with missing lines Patch % Lines
...esforce/androidsdk/auth/AuthenticationUtilities.kt 87.50% 0 Missing and 3 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##                dev    #2847      +/-   ##
============================================
+ Coverage     64.56%   64.60%   +0.03%     
  Complexity     2925     2925              
============================================
  Files           222      222              
  Lines         17338    17352      +14     
  Branches       2474     2475       +1     
============================================
+ Hits          11195    11210      +15     
+ Misses         4936     4934       -2     
- Partials       1207     1208       +1     
Components Coverage Δ
Analytics 47.92% <ø> (ø)
SalesforceSDK 59.14% <88.00%> (+0.07%) ⬆️
Hybrid 59.05% <ø> (ø)
SmartStore 78.20% <ø> (ø)
MobileSync 81.68% <ø> (ø)
React 52.36% <ø> (ø)
Files with missing lines Coverage Δ
...SDK/src/com/salesforce/androidsdk/auth/OAuth2.java 77.27% <100.00%> (+0.32%) ⬆️
...esforce/androidsdk/auth/AuthenticationUtilities.kt 54.92% <87.50%> (+3.52%) ⬆️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

1 participant