@@ -21,6 +21,9 @@ import com.amplifyframework.auth.AuthUserAttributeKey.email
21
21
import com.amplifyframework.auth.AuthUserAttributeKey.emailVerified
22
22
import com.amplifyframework.auth.MFAType
23
23
import com.amplifyframework.auth.exceptions.UnknownException
24
+ import com.amplifyframework.auth.result.AuthResetPasswordResult
25
+ import com.amplifyframework.auth.result.step.AuthNextResetPasswordStep
26
+ import com.amplifyframework.auth.result.step.AuthResetPasswordStep
24
27
import com.amplifyframework.auth.result.step.AuthSignInStep
25
28
import com.amplifyframework.ui.authenticator.auth.VerificationMechanism
26
29
import com.amplifyframework.ui.authenticator.enums.AuthenticatorStep
@@ -353,6 +356,125 @@ class AuthenticatorViewModelTest {
353
356
}
354
357
355
358
// endregion
359
+ // region password reset tests
360
+
361
+ @Test
362
+ fun `Sign in with temporary password requires password reset` () = runTest {
363
+ coEvery { authProvider.fetchAuthSession() } returns Success (mockAuthSession(isSignedIn = false ))
364
+ coEvery { authProvider.signIn(any(), any()) } returns Success (
365
+ mockSignInResult(
366
+ signInStep = AuthSignInStep .RESET_PASSWORD
367
+ )
368
+ )
369
+
370
+ viewModel.start(mockAuthenticatorConfiguration(initialStep = AuthenticatorStep .SignIn ))
371
+
372
+ viewModel.signIn(" username" , " password" )
373
+ viewModel.currentStep shouldBe AuthenticatorStep .PasswordReset
374
+ }
375
+
376
+ @Test
377
+ fun `Password reset returns a result of DONE, state should be sign in` () = runTest {
378
+ coEvery { authProvider.fetchAuthSession() } returns Success (mockAuthSession(isSignedIn = false ))
379
+ coEvery { authProvider.resetPassword(any()) } returns Success (
380
+ AuthResetPasswordResult (
381
+ true ,
382
+ AuthNextResetPasswordStep (AuthResetPasswordStep .DONE , emptyMap(), null )
383
+ )
384
+ )
385
+ viewModel.start(mockAuthenticatorConfiguration(initialStep = AuthenticatorStep .PasswordReset ))
386
+
387
+ viewModel.resetPassword(" username" )
388
+ viewModel.currentStep shouldBe AuthenticatorStep .SignIn
389
+ }
390
+
391
+ @Test
392
+ fun `Password reset fails with an error, state should stay in PasswordReset` () = runTest {
393
+ coEvery { authProvider.fetchAuthSession() } returns Success (mockAuthSession(isSignedIn = false ))
394
+ coEvery { authProvider.resetPassword(any()) } returns Error (
395
+ mockk<UnknownException > {
396
+ every { cause } returns mockk<HttpException > {
397
+ every { cause } returns mockk<UnknownHostException >()
398
+ }
399
+ }
400
+ )
401
+ viewModel.start(mockAuthenticatorConfiguration(initialStep = AuthenticatorStep .PasswordReset ))
402
+
403
+ viewModel.resetPassword(" username" )
404
+ viewModel.currentStep shouldBe AuthenticatorStep .PasswordReset
405
+ }
406
+
407
+ @Test
408
+ fun `Password reset confirmation succeeds, sign in succeeds, state should be signed in` () = runTest {
409
+ coEvery { authProvider.fetchAuthSession() } returns Success (mockAuthSession(isSignedIn = false ))
410
+ coEvery { authProvider.resetPassword(any()) } returns Success (
411
+ AuthResetPasswordResult (
412
+ true ,
413
+ AuthNextResetPasswordStep (AuthResetPasswordStep .CONFIRM_RESET_PASSWORD_WITH_CODE , emptyMap(), null )
414
+ )
415
+ )
416
+
417
+ coEvery { authProvider.confirmResetPassword(any(), any(), any()) } returns Success (Unit )
418
+ coEvery { authProvider.signIn(any(), any()) } returns Success (mockSignInResult())
419
+
420
+ viewModel.start(mockAuthenticatorConfiguration(initialStep = AuthenticatorStep .PasswordReset ))
421
+
422
+ viewModel.resetPassword(" username" )
423
+ viewModel.confirmResetPassword(" username" , " password" , " code" )
424
+ viewModel.currentStep shouldBe AuthenticatorStep .SignedIn
425
+ }
426
+
427
+ @Test
428
+ fun `Password reset confirmation fails, state should stay in PasswordResetConfirm` () = runTest {
429
+ coEvery { authProvider.fetchAuthSession() } returns Success (mockAuthSession(isSignedIn = false ))
430
+ coEvery { authProvider.resetPassword(any()) } returns Success (
431
+ AuthResetPasswordResult (
432
+ true ,
433
+ AuthNextResetPasswordStep (AuthResetPasswordStep .CONFIRM_RESET_PASSWORD_WITH_CODE , emptyMap(), null )
434
+ )
435
+ )
436
+
437
+ coEvery { authProvider.confirmResetPassword(any(), any(), any()) } returns Error (
438
+ mockk<UnknownException > {
439
+ every { cause } returns mockk<HttpException > {
440
+ every { cause } returns mockk<UnknownHostException >()
441
+ }
442
+ }
443
+ )
444
+
445
+ viewModel.start(mockAuthenticatorConfiguration(initialStep = AuthenticatorStep .PasswordReset ))
446
+
447
+ viewModel.resetPassword(" username" )
448
+ viewModel.confirmResetPassword(" username" , " password" , " code" )
449
+ viewModel.currentStep shouldBe AuthenticatorStep .PasswordResetConfirm
450
+ }
451
+
452
+ @Test
453
+ fun `Password reset confirmation succeeds, sign in fails, state should be sign in` () = runTest {
454
+ coEvery { authProvider.fetchAuthSession() } returns Success (mockAuthSession(isSignedIn = false ))
455
+ coEvery { authProvider.resetPassword(any()) } returns Success (
456
+ AuthResetPasswordResult (
457
+ true ,
458
+ AuthNextResetPasswordStep (AuthResetPasswordStep .CONFIRM_RESET_PASSWORD_WITH_CODE , emptyMap(), null )
459
+ )
460
+ )
461
+
462
+ coEvery { authProvider.confirmResetPassword(any(), any(), any()) } returns Success (Unit )
463
+ coEvery { authProvider.signIn(any(), any()) } returns Error (
464
+ mockk<UnknownException > {
465
+ every { cause } returns mockk<HttpException > {
466
+ every { cause } returns mockk<UnknownHostException >()
467
+ }
468
+ }
469
+ )
470
+
471
+ viewModel.start(mockAuthenticatorConfiguration(initialStep = AuthenticatorStep .PasswordReset ))
472
+
473
+ viewModel.resetPassword(" username" )
474
+ viewModel.confirmResetPassword(" username" , " password" , " code" )
475
+ viewModel.currentStep shouldBe AuthenticatorStep .SignIn
476
+ }
477
+ // endregion
356
478
// region helpers
357
479
private val AuthenticatorViewModel .currentStep: AuthenticatorStep
358
480
get() = stepState.value.step
0 commit comments