Skip to content

W-22698013: DPoP automated UI tests (Phase 5) - #2959

Merged
wmathurin merged 12 commits into
forcedotcom:dpopfrom
wmathurin:dpop-phase5
Jul 10, 2026
Merged

W-22698013: DPoP automated UI tests (Phase 5)#2959
wmathurin merged 12 commits into
forcedotcom:dpopfrom
wmathurin:dpop-phase5

Conversation

@wmathurin

@wmathurin wmathurin commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

W-22698013: End-to-end automated UI tests for DPoP login flows in AuthFlowTester.

  • DPoP toggle in LoginOptions: removes unconditional setUseDPoP(true) from Application.onCreate(); tests toggle DPoP on/off through the existing Login Options screen, so all non-DPoP tests are unaffected
  • Two new ECAs on regular_auth (sdb38): ECA_JWT_DPOP (ecajwtdpop://success/done) and ECA_JWT_DPOP_RTR (ecajwtdpoprtr://success/done)
  • useDPoP Kotlin property: converted from Java-style field + isUseDPoP()/setUseDPoP() to @get:JvmName("isUseDPoP") var useDPoP: Boolean = false for consistency with forceAdvancedAuthentication
  • DPoP nonce surfaced in credentials card: UserCredentialsView now shows OAuth Token Type row and a DPoP section (nonce) for DPoP sessions
  • Assertions: validateOAuthValues asserts tokenType == "DPoP" and nonce non-empty; assertRevokeAndRefreshWorks(isDpop = true) asserts the nonce changes after each token refresh (proves server processed the DPoP proof)
  • All DPoP tests consolidated in DPoPLoginTests: basic login (hybrid/no-hybrid), DPoP+RTR, multi-user, migration, and restart — one suite owns the feature end-to-end, mirroring how RTRLoginTests owns all RTR scenarios

Test Coverage

Test Scenario
testECAJwtDPoP_Hybrid DPoP login (hybrid) → 2× revoke+refresh; nonce rotates
testECAJwtDPoP_NoHybrid DPoP login (no hybrid) → 2× revoke+refresh; nonce rotates
testECAJwtDPoPRtr_Hybrid DPoP+RTR (hybrid) → refresh token rotates; nonce rotates
testECAJwtDPoPRtr_NoHybrid DPoP+RTR (no hybrid) → refresh token rotates; nonce rotates
testECAJwtDPoP_MultiUser_UniqueTokens Two DPoP users → unique tokens; independent revoke+refresh per user
testMigrate_ECAJwtDPoP_AddMoreScopes DPoP scope upgrade → DPoP binding preserved
testMigrate_ECAJwtDPoP_To_ECAJwtDPoPRtr Migrate DPoP ECA → DPoP+RTR ECA
testECAJwtDPoP_WithRestart DPoP login → restart → EC key pair survives AndroidKeyStore; revoke+refresh works

Test plan

  • Build AuthFlowTester without errors
  • Run DPoPLoginTests — all 8 DPoP tests pass
  • Run RTRLoginTests — non-DPoP RTR tests still pass
  • Run MultiUserLoginTests — non-DPoP multi-user tests still pass
  • Run RefreshTokenMigrationTests — non-DPoP migration tests still pass
  • Run LoginWithRestartTests — non-DPoP restart tests still pass

wmathurin added 2 commits July 7, 2026 17:20
… toggle

- Add 'Use DPoP' toggle to LoginOptionsActivity (wires to
  SalesforceSDKManager.setUseDPoP); add string resource for its
  content description
- Remove unconditional setUseDPoP(true) from AuthFlowTesterApplication
  so non-DPoP tests are unaffected
- Add DPOP_AUTH to KnownLoginHostConfig, ECA_JWT_DPOP to KnownAppConfig,
  isDpop to AppConfig in UITestConfig.kt
- Add enableDPoP/disableDPoP to LoginOptionsPageObject
- Add useDPoP param to loginAndValidate(); reset setUseDPoP(false) in
  cleanup() in AuthFlowTest
- Rewrite DPoPLoginTests to follow RTRLoginTests pattern: driven by
  ui_test_config.json dpop_auth host + eca_jwt_dpop app config
- Add dpop_auth + eca_jwt_dpop entries to ui_test_config.json.sample
…AUTH

- AuthorizationPageObject: add DPOP_AUTH branch to when(knownLoginHostConfig)
  (uses Custom Tab path, same as ADVANCED_AUTH)
- MultiUserLoginTests: pass useDPoP = false explicitly to avoid positional
  mismatch after new parameter insertion
- RefreshTokenMigrationTests: add useDPoP to override signature and
  super call to match updated AuthFlowTest.loginAndValidate
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
1 Warning
⚠️ libs/SalesforceSDK/src/com/salesforce/androidsdk/ui/LoginOptionsActivity.kt#L424 - This method should only be accessed from tests or within private scope

Generated by 🚫 Danger

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Job Summary for Gradle

Pull Request :: test-android
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
SalesforceMobileSDK-Android native:NativeSampleApps:AuthFlowTester:assembleDebug 9.4.1 Build Scan not published
SalesforceMobileSDK-Android native:NativeSampleApps:AuthFlowTester:assembleAndroidTest 9.4.1 Build Scan not published

wmathurin added 6 commits July 7, 2026 21:52
…migration test suites

Config changes:
- Remove dpop_auth login host (DPoP is an ECA property, same org as regular_auth)
- Add ECA_JWT_DPOP_RTR to KnownAppConfig for DPoP+RTR combined testing
- Update eca_jwt_dpop redirectUri to ecajwtdpop://success/done and align
  scopes with eca_jwt_rtr; add eca_jwt_dpop_rtr entry to sample config

Infrastructure fixes:
- Remove DPOP_AUTH from KnownLoginHostConfig (no separate login host needed)
- Fix RefreshTokenMigrationTests override: forward useHybridAuthToken param
  instead of hardcoding false
- Add useDPoP param to addOtherUserAndValidate() in AuthFlowTest
- Revert AuthorizationPageObject to two-branch when (DPOP_AUTH removed)
- Fix DPoPLoginTests: drop knownLoginHostConfig=DPOP_AUTH (uses REGULAR_AUTH)

New tests:
- RTRLoginTests: testECAJwtDPoPRtr_Hybrid, testECAJwtDPoPRtr_NoHybrid
- MultiUserLoginTests: testECAJwtDPoP_MultiUser_UniqueTokens
- RefreshTokenMigrationTests: testMigrate_ECAJwtDPoP_AddMoreScopes,
  testMigrate_ECAJwtDPoP_To_ECAJwtDPoPRtr
…ests

Verifies that the DPoP key pair stored in AndroidKeyStore survives a
process kill/relaunch and that revoke+refresh still works after restart.
Add DPoPLoginTests suite section, expand RTRLoginTests/MultiUserLoginTests/
RefreshTokenMigrationTests/LoginWithRestartTests tables with DPoP entries,
add Use DPoP toggle to Login Options docs, and add ECA_JWT_DPOP/ECA_JWT_DPOP_RTR
to KnownAppConfig list.
… tests

Add OAuth Token Type row and DPoP section (with nonce) to UserCredentialsView,
wired to DPoPNonceCache. Add getDpopInfo() to AuthFlowTesterPageObject and extend
validateOAuthValues to assert tokenType=="DPoP" and nonce non-empty for DPoP apps.
Add isDpop param to assertRevokeAndRefreshWorks; asserts the nonce changes after each
token refresh cycle, proving the server processed the DPoP proof header. All DPoP
test call sites updated to pass isDpop=true.
RefreshTokenMigrationTests: add testMigrateCAUserAgent_To_ECAExtendedWebServer
and testMigrateCAUserAgent_To_BeaconExtendedWebServer. MultiUserLoginTests: add
testMultiUser_revokeOtherUserRefreshToken and testAdvancedAuthUser_HasBWFlag_
RegularAuthUser_DoesNot. RTRLoginTests: annotate testECAJwtRtr_Hybrid as @ignore
(W-22512846). All config enums were already in sync.
…edAuthentication

Replace private field + isUseDPoP()/setUseDPoP() with a public Kotlin var. Use
@get:JvmName("isUseDPoP") so Java callers (OAuth2.java, RestClient.java, unit test
mocks) remain unchanged. Kotlin call sites in LoginOptionsActivity and AuthFlowTest
now use property syntax (= value) matching all other SalesforceSDKManager toggles.
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Job Summary for Gradle

Pull Request :: test-android
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
SalesforceMobileSDK-Android libs:SalesforceSDK:lint 9.4.1 Build Scan not published
SalesforceMobileSDK-Android libs:SalesforceSDK:convertCodeCoverage 9.4.1 Build Scan not published
SalesforceMobileSDK-Android libs:SalesforceSDK:assembleAndroidTest 9.4.1 Build Scan not published

Move DPoP-related tests from RTRLoginTests, MultiUserLoginTests,
RefreshTokenMigrationTests, and LoginWithRestartTests into DPoPLoginTests,
which now owns all DPoP coverage end-to-end (basic login, RTR, multi-user,
migration, restart). This mirrors how RTRLoginTests owns all RTR scenarios.

Update README, spec, and plan to reflect the consolidated structure.
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Job Summary for Gradle

Pull Request :: test-android
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
SalesforceMobileSDK-Android libs:SalesforceSDK:lint 9.4.1 Build Scan not published
SalesforceMobileSDK-Android libs:SalesforceSDK:convertCodeCoverage 9.4.1 Build Scan not published
SalesforceMobileSDK-Android libs:SalesforceSDK:assembleAndroidTest 9.4.1 Build Scan not published

Extends adminLoginAndValidate with knownAppConfig and useDPoP parameters,
then adds testLoginForAdmin_DPoP verifying that the Login for Admins
Custom Tab hand-off works end-to-end with a DPoP-enabled ECA.
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Job Summary for Gradle

Pull Request :: test-android
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
SalesforceMobileSDK-Android libs:SalesforceSDK:lint 9.4.1 Build Scan not published
SalesforceMobileSDK-Android libs:SalesforceSDK:convertCodeCoverage 9.4.1 Build Scan not published
SalesforceMobileSDK-Android libs:SalesforceSDK:assembleAndroidTest 9.4.1 Build Scan not published

The useDPoP property conversion (from isUseDPoP()/setUseDPoP()) means
Kotlin callers must mock the property getter with `every { useDPoP }`
rather than `every { isUseDPoP() }`. Java callers still use isUseDPoP()
via the @get:JvmName annotation, but MockK stubs in Kotlin files need
the property syntax.
@wmathurin
wmathurin requested a review from sfdctaka July 9, 2026 23:04
Comment on lines +359 to +364
knownAppConfig = knownAppConfig,
scopeSelection = scopeSelection,
useWebServerFlow = useWebServerFlow,
useHybridAuthToken = useHybridAuthToken,
useDPoP = useDPoP,
knownLoginHostConfig = knownLoginHostConfig,

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: unnecessary.

Comment on lines +214 to +215
useHybridAuthToken = false,
useHybridAuthToken = useHybridAuthToken,

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.

Weren't we waiting for a server side bug to be fixed before useHybridAuthToken could be used?

…HybridAuthToken workaround

Revert unnecessary named-argument conversion in MultiUserLoginTests.
Restore useHybridAuthToken = false in RefreshTokenMigrationTests with a
TODO referencing W-20524841 (server bug blocking hybrid auth token use).
@wmathurin
wmathurin merged commit 2e796c5 into forcedotcom:dpop Jul 10, 2026
3 of 4 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.

3 participants