From 36cbbe7b5d444a0f04b940deb6d500d2f394b681 Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Fri, 3 Jul 2026 21:30:00 -0500 Subject: [PATCH] test(onboarding): assert the Outlook onboarding button launches the browser Extends #274's AccountPickerScreenTest with an Espresso-Intents check that tapping Outlook fires AppAuth's authorization intent. AppAuth always routes through its own AuthorizationManagementActivity before it ever reaches a real browser, so that component name is the one characteristic of the launch that's both guaranteed and installed-browser-independent; matching it also lets the test stub a canceled result so no real browser opens. Verified against the real OutlookAuthManager + AppAuth 0.11.1 on a google_apis API 29 emulator (the same image CI's managed devices use). Redirect handling, token exchange, and account creation stay out of scope per #276. Closes #276 Co-Authored-By: Claude Opus 4.8 --- .../accountsetup/AccountPickerScreenTest.kt | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/app/src/androidTest/kotlin/org/libremail/ui/accountsetup/AccountPickerScreenTest.kt b/app/src/androidTest/kotlin/org/libremail/ui/accountsetup/AccountPickerScreenTest.kt index c06369a..089658c 100644 --- a/app/src/androidTest/kotlin/org/libremail/ui/accountsetup/AccountPickerScreenTest.kt +++ b/app/src/androidTest/kotlin/org/libremail/ui/accountsetup/AccountPickerScreenTest.kt @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later package org.libremail.ui.accountsetup +import android.app.Activity +import android.app.Instrumentation import android.content.Context import androidx.activity.ComponentActivity import androidx.compose.ui.test.assertIsDisplayed @@ -8,8 +10,11 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollTo +import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry +import net.openid.appauth.AuthorizationManagementActivity import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -23,7 +28,8 @@ import org.libremail.ui.theme.LibreMailTheme * End-to-end UI test for the account-vendor picker used by onboarding and "Add account". Drives the * real [AccountPickerScreen] + [AccountSetupViewModel]: every setup choice is listed, tapping an * app-password vendor routes to [onPickProvider] with that [MailProvider], and tapping "Other" - * routes to [onManualSetup]. The Outlook row is deliberately not tapped (it launches a browser). + * routes to [onManualSetup]. Tapping Outlook is covered separately, below, guarded by + * Espresso-Intents so no real browser ever opens. */ @RunWith(AndroidJUnit4::class) class AccountPickerScreenTest { @@ -81,4 +87,36 @@ class AccountPickerScreenTest { composeTestRule.waitUntil(5_000) { manualRequested } } + + /** + * Tapping Outlook must fire the browser-launch intent for Microsoft sign-in (#276). + * [OutlookAuthManager.createAuthIntent] delegates to AppAuth, whose + * `AuthorizationService.getAuthorizationRequestIntent()` never returns a bare browser intent: it + * always wraps it in an intent targeting AppAuth's own [AuthorizationManagementActivity], which + * only starts the actual browser/Custom Tab once it resumes. That component name is therefore the + * one characteristic of the launch that's both guaranteed (every Outlook tap goes through it) and + * stable (it doesn't depend on which browser, if any, is installed on the test device) — matching + * it both confirms the tap started the AppAuth authorization flow and, by stubbing a canceled + * result, stops [AuthorizationManagementActivity] from ever resuming and opening a real browser. + * The OAuth redirect, token exchange, and account creation a real sign-in would trigger next are + * deliberately out of scope here (see #276). + */ + @Test + fun tappingOutlook_launchesTheAppAuthBrowserIntent() { + setContent() + + Intents.init() + try { + Intents.intending(hasComponent(AuthorizationManagementActivity::class.java.name)) + .respondWith(Instrumentation.ActivityResult(Activity.RESULT_CANCELED, null)) + + composeTestRule.onNodeWithText(string(R.string.account_setup_outlook)) + .performScrollTo() + .performClick() + + Intents.intended(hasComponent(AuthorizationManagementActivity::class.java.name)) + } finally { + Intents.release() + } + } } -- 2.47.3