Skip to content

Commit 0dbc8f8

Browse files
committed
addressed PR suggestions
1 parent fee6200 commit 0dbc8f8

File tree

4 files changed

+64
-64
lines changed

4 files changed

+64
-64
lines changed

CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
* Add AuthTab Support
66
* Upgrade `androidx.browser:browser` dependency version to 1.9.0
77
* Upgrade `compileSdkVersion` and `targetSdkVersion` to API 36
8-
* Add `AuthTabCallback` interface
98
* Replace `ChromeCustomTabsInternalClient.java` with `AuthTabInternalClient.kt`
109
* Add parameterized constructor `BrowserSwitchClient(ActivityResultCaller)` to initialize AuthTab support
1110
* Maintain default constructor `BrowserSwitchClient()` (without AuthTab support) for backward compatibility

browser-switch/src/main/java/com/braintreepayments/api/AuthTabCallback.kt

Lines changed: 0 additions & 11 deletions
This file was deleted.

browser-switch/src/main/java/com/braintreepayments/api/BrowserSwitchClient.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.braintreepayments.api;
22

3-
import android.app.Activity;
43
import android.content.ActivityNotFoundException;
54
import android.content.Context;
65
import android.content.Intent;
@@ -47,6 +46,8 @@ public BrowserSwitchClient() {
4746
* <p>IMPORTANT: This constructor enables the AuthTab functionality, which has several caveats:
4847
*
4948
* <ul>
49+
* <li><strong>This constructor must be called in the activity/fragment's {@code onCreate()} method</strong>
50+
* to properly register the activity result launcher before the activity/fragment is started.
5051
* <li>The caller must be an {@link ActivityResultCaller} to register for activity results.
5152
* <li>{@link LaunchType#ACTIVITY_NEW_TASK} is not supported when using AuthTab and will be ignored.
5253
* Only {@link LaunchType#ACTIVITY_CLEAR_TOP} is supported with AuthTab.
@@ -77,7 +78,14 @@ public BrowserSwitchClient(@NonNull ActivityResultCaller caller) {
7778
AuthTabInternalClient authTabInternalClient) {
7879
this.browserSwitchInspector = browserSwitchInspector;
7980
this.authTabInternalClient = authTabInternalClient;
80-
this.authTabCallbackResult = null;
81+
}
82+
83+
@VisibleForTesting
84+
BrowserSwitchClient(@NonNull ActivityResultCaller caller,
85+
BrowserSwitchInspector inspector,
86+
AuthTabInternalClient internal) {
87+
this(inspector, internal);
88+
initializeAuthTabLauncher(caller);
8189
}
8290

8391
/**
@@ -86,7 +94,7 @@ public BrowserSwitchClient(@NonNull ActivityResultCaller caller) {
8694
*
8795
* @param caller The ActivityResultCaller (Activity or Fragment) used to initialize the Auth Tab launcher
8896
*/
89-
public void initializeAuthTabLauncher(@NonNull ActivityResultCaller caller) {
97+
private void initializeAuthTabLauncher(@NonNull ActivityResultCaller caller) {
9098

9199
this.authTabLauncher = AuthTabIntent.registerActivityResultLauncher(
92100
caller,

browser-switch/src/test/java/com/braintreepayments/api/BrowserSwitchClientUnitTest.java

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,11 @@ public void initializeAuthTabLauncher_registersLauncherWithActivity() {
253253
any(ActivityResultCallback.class)
254254
)).thenReturn(mockLauncher);
255255

256-
BrowserSwitchClient sut = new BrowserSwitchClient(browserSwitchInspector, authTabInternalClient);
257-
258-
sut.initializeAuthTabLauncher((ActivityResultCaller) componentActivity);
256+
BrowserSwitchClient sut = new BrowserSwitchClient(
257+
componentActivity,
258+
browserSwitchInspector,
259+
authTabInternalClient
260+
);
259261

260262
mockedAuthTab.verify(() -> AuthTabIntent.registerActivityResultLauncher(
261263
eq(componentActivity),
@@ -281,27 +283,30 @@ public void start_withAuthTabLauncherInitialized_usesPendingAuthTabRequest() thr
281283
"return-url-scheme"
282284
)).thenReturn(true);
283285
when(authTabInternalClient.isAuthTabSupported(componentActivity)).thenReturn(true);
284-
285-
ArgumentCaptor<ActivityResultCallback> callbackCaptor =
286+
ArgumentCaptor<ActivityResultCallback<AuthTabIntent.AuthResult>> callbackCaptor =
286287
ArgumentCaptor.forClass(ActivityResultCallback.class);
287288
mockedAuthTab.when(() -> AuthTabIntent.registerActivityResultLauncher(
288289
eq(componentActivity),
289290
callbackCaptor.capture()
290291
)).thenReturn(mockLauncher);
292+
BrowserSwitchClient sut = new BrowserSwitchClient(
293+
componentActivity,
294+
browserSwitchInspector,
295+
authTabInternalClient
296+
);
291297

292-
BrowserSwitchClient sut = new BrowserSwitchClient(browserSwitchInspector, authTabInternalClient);
293-
294-
sut.initializeAuthTabLauncher((ActivityResultCaller) componentActivity);
298+
mockedAuthTab.verify(() -> AuthTabIntent.registerActivityResultLauncher(
299+
eq(componentActivity),
300+
any(ActivityResultCallback.class)
301+
));
295302

296303
JSONObject metadata = new JSONObject();
297304
BrowserSwitchOptions options = new BrowserSwitchOptions()
298305
.requestCode(123)
299306
.url(browserSwitchDestinationUrl)
300307
.returnUrlScheme("return-url-scheme")
301308
.metadata(metadata);
302-
303309
BrowserSwitchStartResult result = sut.start(componentActivity, options);
304-
305310
assertTrue(result instanceof BrowserSwitchStartResult.Started);
306311

307312
verify(authTabInternalClient).launchUrl(
@@ -315,10 +320,6 @@ public void start_withAuthTabLauncherInitialized_usesPendingAuthTabRequest() thr
315320

316321
String pendingRequestString = ((BrowserSwitchStartResult.Started) result).getPendingRequest();
317322
assertNotNull(pendingRequestString);
318-
319-
BrowserSwitchRequest decodedRequest = BrowserSwitchRequest.fromBase64EncodedJSON(pendingRequestString);
320-
assertEquals(123, decodedRequest.getRequestCode());
321-
assertEquals(browserSwitchDestinationUrl, decodedRequest.getUrl());
322323
}
323324
}
324325

@@ -328,27 +329,33 @@ public void authTabCallback_withResultOK_setsInternalCallbackResult() {
328329

329330
ArgumentCaptor<ActivityResultCallback<AuthTabIntent.AuthResult>> callbackCaptor =
330331
ArgumentCaptor.forClass(ActivityResultCallback.class);
331-
mockedAuthTab.when(() -> AuthTabIntent.registerActivityResultLauncher(
332-
eq(componentActivity),
333-
callbackCaptor.capture()
334-
)).thenReturn(mockLauncher);
335332

336333
when(browserSwitchInspector.isDeviceConfiguredForDeepLinking(
337334
componentActivity.getApplicationContext(),
338335
"return-url-scheme"
339336
)).thenReturn(true);
340337
when(authTabInternalClient.isAuthTabSupported(componentActivity)).thenReturn(true);
341338

342-
BrowserSwitchClient sut = new BrowserSwitchClient(browserSwitchInspector, authTabInternalClient);
343-
sut.initializeAuthTabLauncher((ActivityResultCaller) componentActivity);
339+
mockedAuthTab.when(() -> AuthTabIntent.registerActivityResultLauncher(
340+
eq(componentActivity),
341+
callbackCaptor.capture()
342+
)).thenReturn(mockLauncher);
343+
344+
BrowserSwitchClient sut = new BrowserSwitchClient(
345+
componentActivity,
346+
browserSwitchInspector,
347+
authTabInternalClient
348+
);
344349

345350
JSONObject metadata = new JSONObject();
346351
BrowserSwitchOptions options = new BrowserSwitchOptions()
347352
.requestCode(123)
348353
.url(browserSwitchDestinationUrl)
349354
.returnUrlScheme("return-url-scheme")
350355
.metadata(metadata);
351-
sut.start(componentActivity, options);
356+
357+
BrowserSwitchStartResult startResult = sut.start(componentActivity, options);
358+
String pendingRequest = ((BrowserSwitchStartResult.Started) startResult).getPendingRequest();
352359

353360
Uri resultUri = Uri.parse("return-url-scheme://success");
354361
AuthTabIntent.AuthResult mockAuthResult = mock(AuthTabIntent.AuthResult.class, withSettings()
@@ -358,7 +365,7 @@ public void authTabCallback_withResultOK_setsInternalCallbackResult() {
358365
callbackCaptor.getValue().onActivityResult(mockAuthResult);
359366

360367
Intent dummyIntent = new Intent();
361-
BrowserSwitchFinalResult capturedResult = sut.completeRequest(dummyIntent, "dummyPendingRequest");
368+
BrowserSwitchFinalResult capturedResult = sut.completeRequest(dummyIntent, pendingRequest);
362369
assertTrue(capturedResult instanceof BrowserSwitchFinalResult.Success);
363370

364371
BrowserSwitchFinalResult.Success successResult =
@@ -378,9 +385,11 @@ public void authTabCallback_withResultCanceled_callsCallbackWithNoResult() {
378385
callbackCaptor.capture()
379386
)).thenReturn(mockLauncher);
380387

381-
BrowserSwitchClient sut = new BrowserSwitchClient(browserSwitchInspector, authTabInternalClient);
382-
383-
sut.initializeAuthTabLauncher((ActivityResultCaller) componentActivity);
388+
BrowserSwitchClient sut = new BrowserSwitchClient(
389+
componentActivity,
390+
browserSwitchInspector,
391+
authTabInternalClient
392+
);
384393

385394
AuthTabIntent.AuthResult mockAuthResult = mock(AuthTabIntent.AuthResult.class, withSettings()
386395
.useConstructor(AuthTabIntent.RESULT_CANCELED, null)
@@ -396,7 +405,6 @@ public void authTabCallback_withResultCanceled_callsCallbackWithNoResult() {
396405

397406
@Test
398407
public void start_withoutAuthTabLauncher_fallsBackToCustomTabs() {
399-
400408
when(browserSwitchInspector.isDeviceConfiguredForDeepLinking(
401409
componentActivity.getApplicationContext(),
402410
"return-url-scheme"
@@ -432,7 +440,6 @@ public void start_whenAuthTabLauncherIsNull_fallsBackToCustomTabs() {
432440
"return-url-scheme"
433441
)).thenReturn(true);
434442

435-
// Explicitly ensure AuthTab is supported but we still fallback due to null launcher
436443
when(authTabInternalClient.isAuthTabSupported(componentActivity)).thenReturn(true);
437444

438445
BrowserSwitchClient sut = new BrowserSwitchClient(browserSwitchInspector, authTabInternalClient);
@@ -480,10 +487,11 @@ public void isAuthTabSupported_returnsTrueWhenLauncherInitialized() {
480487
any(ActivityResultCallback.class)
481488
)).thenReturn(mockLauncher);
482489

483-
BrowserSwitchClient sut = new BrowserSwitchClient(browserSwitchInspector,
484-
authTabInternalClient);
485-
486-
sut.initializeAuthTabLauncher((ActivityResultCaller) componentActivity);
490+
BrowserSwitchClient sut = new BrowserSwitchClient(
491+
componentActivity,
492+
browserSwitchInspector,
493+
authTabInternalClient
494+
);
487495

488496
boolean result = sut.isAuthTabSupported(applicationContext);
489497

@@ -495,39 +503,35 @@ public void isAuthTabSupported_returnsTrueWhenLauncherInitialized() {
495503
@Test
496504
public void isAuthTabSupported_returnsFalseWhenBrowserDoesNotSupportAuthTab() {
497505
try (MockedStatic<AuthTabIntent> mockedAuthTab = mockStatic(AuthTabIntent.class)) {
498-
when(authTabInternalClient.isAuthTabSupported(applicationContext)).thenReturn(false);
499-
500506
mockedAuthTab.when(() -> AuthTabIntent.registerActivityResultLauncher(
501-
any(ComponentActivity.class),
507+
any(ActivityResultCaller.class),
502508
any(ActivityResultCallback.class)
503509
)).thenReturn(mockLauncher);
504510

505-
BrowserSwitchClient sut = new BrowserSwitchClient(browserSwitchInspector,
506-
authTabInternalClient);
511+
when(authTabInternalClient.isAuthTabSupported(any())).thenReturn(false);
507512

508-
sut.initializeAuthTabLauncher((ActivityResultCaller) componentActivity);
513+
BrowserSwitchClient sut = new BrowserSwitchClient(
514+
componentActivity,
515+
browserSwitchInspector,
516+
authTabInternalClient
517+
);
509518

510-
boolean result = sut.isAuthTabSupported(applicationContext);
519+
boolean result = sut.isAuthTabSupported(componentActivity);
511520

512521
assertFalse(result);
513-
verify(authTabInternalClient).isAuthTabSupported(applicationContext);
514522
}
515523
}
516524

517525
@Test
518-
public void parameterizedConstructor_initializesAuthTabLauncher() {
526+
public void defaultConstructor_doesNotInitializeAuthTabLauncher() {
519527
try (MockedStatic<AuthTabIntent> mockedAuthTab = mockStatic(AuthTabIntent.class)) {
520-
mockedAuthTab.when(() -> AuthTabIntent.registerActivityResultLauncher(
521-
any(ComponentActivity.class),
522-
any(ActivityResultCallback.class)
523-
)).thenReturn(mockLauncher);
528+
BrowserSwitchClient sut = new BrowserSwitchClient();
524529

525-
BrowserSwitchClient sut = new BrowserSwitchClient((ActivityResultCaller) componentActivity);
530+
mockedAuthTab.verifyNoInteractions();
526531

527-
mockedAuthTab.verify(() -> AuthTabIntent.registerActivityResultLauncher(
528-
eq(componentActivity),
529-
any(ActivityResultCallback.class)
530-
));
532+
when(authTabInternalClient.isAuthTabSupported(applicationContext)).thenReturn(true);
533+
boolean result = sut.isAuthTabSupported(applicationContext);
534+
assertFalse(result);
531535
}
532536
}
533537

0 commit comments

Comments
 (0)