Skip to content

Commit 21a8532

Browse files
committed
Updtaed UT cases as per review comment
1 parent b01245f commit 21a8532

2 files changed

Lines changed: 129 additions & 34 deletions

File tree

auth0/src/main/java/com/auth0/android/provider/WebAuthProvider.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,25 @@ public object WebAuthProvider {
246246
pendingLogoutResult.set(null)
247247
}
248248

249+
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
250+
internal fun setPendingLoginResult(credentials: Credentials) {
251+
pendingLoginResult.set(PendingResult.Success(credentials))
252+
}
253+
254+
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
255+
internal fun setPendingLogoutResult() {
256+
pendingLogoutResult.set(PendingResult.Success(null))
257+
}
258+
259+
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
260+
internal fun hasPendingLoginResult(): Boolean = pendingLoginResult.get() != null
261+
262+
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
263+
internal fun hasPendingLogoutResult(): Boolean = pendingLogoutResult.get() != null
264+
265+
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
266+
internal fun callbacksCount(): Int = callbacks.size
267+
249268
public class LogoutBuilder internal constructor(private val account: Auth0) {
250269
private var scheme = "https"
251270
private var returnToUrl: String? = null

auth0/src/test/java/com/auth0/android/provider/WebAuthProviderTest.kt

Lines changed: 110 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3070,8 +3070,10 @@ public class WebAuthProviderTest {
30703070
verify(options, Mockito.never()).copyWithEphemeralBrowsing()
30713071
}
30723072

3073+
// --- LifecycleAwareCallback tests ---
3074+
30733075
@Test
3074-
public fun shouldCacheLoginResultWhenLifecycleCallbackIsDetachedOnDestroy() {
3076+
public fun shouldInvokeOnDetachedWithLoginResultAfterDestroy() {
30753077
val credentials = Mockito.mock(Credentials::class.java)
30763078
var capturedSuccess: Credentials? = null
30773079
var capturedError: AuthenticationException? = null
@@ -3094,11 +3096,11 @@ public class WebAuthProviderTest {
30943096

30953097
Assert.assertEquals(credentials, capturedSuccess)
30963098
Assert.assertNull(capturedError)
3097-
verify(callback, Mockito.never()).onSuccess(any()) // old callback never called
3099+
verify(callback, Mockito.never()).onSuccess(any())
30983100
}
30993101

31003102
@Test
3101-
public fun shouldCacheLoginFailureWhenLifecycleCallbackIsDetachedOnDestroy() {
3103+
public fun shouldInvokeOnDetachedWithLoginFailureAfterDestroy() {
31023104
val error = AuthenticationException("canceled", "User canceled")
31033105
var capturedSuccess: Credentials? = null
31043106
var capturedError: AuthenticationException? = null
@@ -3167,8 +3169,8 @@ public class WebAuthProviderTest {
31673169
}
31683170

31693171
@Test
3170-
public fun shouldCacheLogoutSuccessWhenLifecycleCallbackIsDetachedOnDestroy() {
3171-
var capturedSuccess = false
3172+
public fun shouldInvokeOnDetachedWithLogoutSuccessAfterDestroy() {
3173+
var onDetachedCalled = false
31723174
var capturedError: AuthenticationException? = null
31733175

31743176
val lifecycleOwner = Mockito.mock(LifecycleOwner::class.java)
@@ -3179,23 +3181,23 @@ public class WebAuthProviderTest {
31793181
delegateCallback = voidCallback,
31803182
lifecycleOwner = lifecycleOwner,
31813183
onDetached = { _, error ->
3184+
onDetachedCalled = true
31823185
capturedError = error
3183-
if (error == null) capturedSuccess = true
31843186
}
31853187
)
31863188

31873189
lifecycleCallback.onDestroy(lifecycleOwner)
31883190
lifecycleCallback.onSuccess(null)
31893191

3190-
Assert.assertTrue(capturedSuccess)
3192+
Assert.assertTrue(onDetachedCalled)
31913193
Assert.assertNull(capturedError)
31923194
verify(voidCallback, Mockito.never()).onSuccess(any())
31933195
}
31943196

31953197
@Test
3196-
public fun shouldCacheLogoutFailureWhenLifecycleCallbackIsDetachedOnDestroy() {
3198+
public fun shouldInvokeOnDetachedWithLogoutFailureAfterDestroy() {
31973199
val error = AuthenticationException("canceled", "User closed the browser")
3198-
var capturedSuccess = false
3200+
var onDetachedCalled = false
31993201
var capturedError: AuthenticationException? = null
32003202

32013203
val lifecycleOwner = Mockito.mock(LifecycleOwner::class.java)
@@ -3206,15 +3208,15 @@ public class WebAuthProviderTest {
32063208
delegateCallback = voidCallback,
32073209
lifecycleOwner = lifecycleOwner,
32083210
onDetached = { _, detachedError ->
3211+
onDetachedCalled = true
32093212
capturedError = detachedError
3210-
if (detachedError == null) capturedSuccess = true
32113213
}
32123214
)
32133215

32143216
lifecycleCallback.onDestroy(lifecycleOwner)
32153217
lifecycleCallback.onFailure(error)
32163218

3217-
Assert.assertFalse(capturedSuccess)
3219+
Assert.assertTrue(onDetachedCalled)
32183220
Assert.assertEquals(error, capturedError)
32193221
verify(voidCallback, Mockito.never()).onFailure(any())
32203222
}
@@ -3271,25 +3273,72 @@ public class WebAuthProviderTest {
32713273
verify(lifecycle).removeObserver(lifecycleCallback)
32723274
}
32733275

3276+
32743277
@Test
3275-
public fun shouldClearStaleResultWhenNewLoginStarts() {
3276-
// Start a new login — should not crash or deliver stale data
3277-
login(account).start(activity, callback)
3278+
public fun shouldWrapCallbackWithLifecycleAwareCallbackWhenStartedWithLifecycleOwner() {
3279+
val lifecycle = Mockito.mock(Lifecycle::class.java)
3280+
val lifecycleActivity = Mockito.mock(TestLifecycleOwnerActivity::class.java)
3281+
Mockito.`when`(lifecycleActivity.lifecycle).thenReturn(lifecycle)
3282+
Mockito.`when`(lifecycleActivity.applicationContext).thenReturn(lifecycleActivity)
3283+
Mockito.`when`(lifecycleActivity.packageName).thenReturn("com.auth0.test")
3284+
Mockito.doReturn(false).`when`(lifecycleActivity).bindService(any(), any(), ArgumentMatchers.anyInt())
3285+
BrowserPickerTest.setupBrowserContext(lifecycleActivity, listOf("com.auth0.browser"), null, null)
32783286

3279-
// The new callback should not have received any stale result
3280-
verify(callback, Mockito.never()).onSuccess(any())
3287+
login(account).start(lifecycleActivity, callback)
3288+
3289+
verify(lifecycle).addObserver(any<LifecycleAwareCallback<Credentials>>())
32813290
}
32823291

3292+
32833293
@Test
3284-
public fun shouldClearStaleResultWhenNewLogoutStarts() {
3285-
// Start a new logout — should not crash or deliver stale data
3286-
logout(account).start(activity, voidCallback)
3294+
public fun shouldRegisterLifecycleObserverOnRegisterCallbacks() {
3295+
val lifecycleOwner = Mockito.mock(LifecycleOwner::class.java)
3296+
val lifecycle = Mockito.mock(Lifecycle::class.java)
3297+
Mockito.`when`(lifecycleOwner.lifecycle).thenReturn(lifecycle)
32873298

3288-
verify(voidCallback, Mockito.never()).onSuccess(any())
3299+
WebAuthProvider.registerCallbacks(lifecycleOwner, loginCallback = callback, logoutCallback = voidCallback)
3300+
3301+
verify(lifecycle).addObserver(isA<DefaultLifecycleObserver>())
32893302
}
32903303

32913304
@Test
3292-
public fun shouldNotDeliverLoginResultOnResumeWhenNoPendingResult() {
3305+
public fun shouldRemoveLifecycleObserverOnDestroyAfterRegisterCallbacks() {
3306+
val lifecycleOwner = Mockito.mock(LifecycleOwner::class.java)
3307+
val lifecycle = Mockito.mock(Lifecycle::class.java)
3308+
Mockito.`when`(lifecycleOwner.lifecycle).thenReturn(lifecycle)
3309+
3310+
val observerCaptor = argumentCaptor<DefaultLifecycleObserver>()
3311+
WebAuthProvider.registerCallbacks(lifecycleOwner, loginCallback = callback, logoutCallback = voidCallback)
3312+
verify(lifecycle).addObserver(observerCaptor.capture())
3313+
3314+
observerCaptor.firstValue.onDestroy(lifecycleOwner)
3315+
3316+
verify(lifecycle).removeObserver(observerCaptor.firstValue)
3317+
}
3318+
3319+
@Test
3320+
public fun shouldRemoveLoginCallbackFromCallbacksOnDestroy() {
3321+
val lifecycleOwner = Mockito.mock(LifecycleOwner::class.java)
3322+
val lifecycle = Mockito.mock(Lifecycle::class.java)
3323+
Mockito.`when`(lifecycleOwner.lifecycle).thenReturn(lifecycle)
3324+
3325+
val observerCaptor = argumentCaptor<DefaultLifecycleObserver>()
3326+
WebAuthProvider.registerCallbacks(lifecycleOwner, loginCallback = callback, logoutCallback = voidCallback)
3327+
verify(lifecycle).addObserver(observerCaptor.capture())
3328+
3329+
Assert.assertEquals(1, WebAuthProvider.callbacksCount())
3330+
3331+
observerCaptor.firstValue.onDestroy(lifecycleOwner)
3332+
3333+
Assert.assertEquals(0, WebAuthProvider.callbacksCount())
3334+
}
3335+
3336+
3337+
@Test
3338+
public fun shouldDeliverPendingLoginResultOnResume() {
3339+
val credentials = Mockito.mock(Credentials::class.java)
3340+
WebAuthProvider.setPendingLoginResult(credentials)
3341+
32933342
val lifecycleOwner = Mockito.mock(LifecycleOwner::class.java)
32943343
val lifecycle = Mockito.mock(Lifecycle::class.java)
32953344
Mockito.`when`(lifecycleOwner.lifecycle).thenReturn(lifecycle)
@@ -3298,14 +3347,16 @@ public class WebAuthProviderTest {
32983347
WebAuthProvider.registerCallbacks(lifecycleOwner, loginCallback = callback, logoutCallback = voidCallback)
32993348
verify(lifecycle).addObserver(observerCaptor.capture())
33003349

3301-
// Trigger onResume with no pending result — should not deliver anything
33023350
observerCaptor.firstValue.onResume(lifecycleOwner)
3303-
verify(callback, Mockito.never()).onSuccess(any())
3304-
verify(callback, Mockito.never()).onFailure(any())
3351+
3352+
verify(callback).onSuccess(credentials)
3353+
Assert.assertFalse(WebAuthProvider.hasPendingLoginResult())
33053354
}
33063355

33073356
@Test
3308-
public fun shouldNotDeliverLogoutResultOnResumeWhenNoPendingResult() {
3357+
public fun shouldDeliverPendingLogoutResultOnResume() {
3358+
WebAuthProvider.setPendingLogoutResult()
3359+
33093360
val lifecycleOwner = Mockito.mock(LifecycleOwner::class.java)
33103361
val lifecycle = Mockito.mock(Lifecycle::class.java)
33113362
Mockito.`when`(lifecycleOwner.lifecycle).thenReturn(lifecycle)
@@ -3315,23 +3366,28 @@ public class WebAuthProviderTest {
33153366
verify(lifecycle).addObserver(observerCaptor.capture())
33163367

33173368
observerCaptor.firstValue.onResume(lifecycleOwner)
3318-
verify(voidCallback, Mockito.never()).onSuccess(any())
3319-
verify(voidCallback, Mockito.never()).onFailure(any())
3369+
3370+
verify(voidCallback).onSuccess(null)
3371+
Assert.assertFalse(WebAuthProvider.hasPendingLogoutResult())
33203372
}
33213373

33223374
@Test
3323-
public fun shouldRegisterLifecycleObserverOnRegisterCallbacks() {
3375+
public fun shouldNotDeliverLoginResultOnResumeWhenNoPendingResult() {
33243376
val lifecycleOwner = Mockito.mock(LifecycleOwner::class.java)
33253377
val lifecycle = Mockito.mock(Lifecycle::class.java)
33263378
Mockito.`when`(lifecycleOwner.lifecycle).thenReturn(lifecycle)
33273379

3380+
val observerCaptor = argumentCaptor<DefaultLifecycleObserver>()
33283381
WebAuthProvider.registerCallbacks(lifecycleOwner, loginCallback = callback, logoutCallback = voidCallback)
3382+
verify(lifecycle).addObserver(observerCaptor.capture())
33293383

3330-
verify(lifecycle).addObserver(any())
3384+
observerCaptor.firstValue.onResume(lifecycleOwner)
3385+
verify(callback, Mockito.never()).onSuccess(any())
3386+
verify(callback, Mockito.never()).onFailure(any())
33313387
}
33323388

33333389
@Test
3334-
public fun shouldRemoveLifecycleObserverOnDestroyAfterRegisterCallbacks() {
3390+
public fun shouldNotDeliverLogoutResultOnResumeWhenNoPendingResult() {
33353391
val lifecycleOwner = Mockito.mock(LifecycleOwner::class.java)
33363392
val lifecycle = Mockito.mock(Lifecycle::class.java)
33373393
Mockito.`when`(lifecycleOwner.lifecycle).thenReturn(lifecycle)
@@ -3340,16 +3396,36 @@ public class WebAuthProviderTest {
33403396
WebAuthProvider.registerCallbacks(lifecycleOwner, loginCallback = callback, logoutCallback = voidCallback)
33413397
verify(lifecycle).addObserver(observerCaptor.capture())
33423398

3343-
// Simulate onDestroy
3344-
observerCaptor.firstValue.onDestroy(lifecycleOwner)
3399+
observerCaptor.firstValue.onResume(lifecycleOwner)
3400+
verify(voidCallback, Mockito.never()).onSuccess(any())
3401+
verify(voidCallback, Mockito.never()).onFailure(any())
3402+
}
33453403

3346-
verify(lifecycle).removeObserver(observerCaptor.firstValue)
3404+
@Test
3405+
public fun shouldClearPendingLoginResultOnNewLoginStart() {
3406+
val credentials = Mockito.mock(Credentials::class.java)
3407+
WebAuthProvider.setPendingLoginResult(credentials)
3408+
Assert.assertTrue(WebAuthProvider.hasPendingLoginResult())
3409+
3410+
login(account).start(activity, callback)
3411+
3412+
Assert.assertFalse(WebAuthProvider.hasPendingLoginResult())
33473413
}
33483414

3415+
@Test
3416+
public fun shouldClearPendingLogoutResultOnNewLogoutStart() {
3417+
WebAuthProvider.setPendingLogoutResult()
3418+
Assert.assertTrue(WebAuthProvider.hasPendingLogoutResult())
33493419

3420+
logout(account).start(activity, voidCallback)
3421+
3422+
Assert.assertFalse(WebAuthProvider.hasPendingLogoutResult())
3423+
}
33503424

33513425
private companion object {
33523426
private const val KEY_STATE = "state"
33533427
private const val KEY_NONCE = "nonce"
33543428
}
3355-
}
3429+
}
3430+
3431+
internal abstract class TestLifecycleOwnerActivity : Activity(), LifecycleOwner

0 commit comments

Comments
 (0)