WebAuthnDeviceLostControllerTest.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. namespace Tests\Feature\Http\Auth;
  3. use App\Extensions\WebauthnCredentialBroker;
  4. use App\Http\Controllers\Auth\WebAuthnDeviceLostController;
  5. use App\Http\Requests\WebauthnDeviceLostRequest;
  6. use App\Models\User;
  7. use App\Notifications\WebauthnRecoveryNotification;
  8. use App\Providers\AuthServiceProvider;
  9. use App\Rules\CaseInsensitiveEmailExists;
  10. use Illuminate\Support\Facades\Notification;
  11. use PHPUnit\Framework\Attributes\CoversClass;
  12. use PHPUnit\Framework\Attributes\CoversMethod;
  13. use PHPUnit\Framework\Attributes\Test;
  14. use Tests\FeatureTestCase;
  15. /**
  16. * WebAuthnDeviceLostControllerTest test class
  17. */
  18. #[CoversMethod(User::class, 'sendWebauthnRecoveryNotification')]
  19. #[CoversClass(WebAuthnDeviceLostController::class)]
  20. #[CoversClass(WebauthnRecoveryNotification::class)]
  21. #[CoversClass(WebauthnCredentialBroker::class)]
  22. #[CoversClass(WebauthnDeviceLostRequest::class)]
  23. #[CoversClass(AuthServiceProvider::class)]
  24. #[CoversMethod(CaseInsensitiveEmailExists::class, 'validate')]
  25. class WebAuthnDeviceLostControllerTest extends FeatureTestCase
  26. {
  27. /**
  28. * @var \App\Models\User
  29. */
  30. protected $user;
  31. public function setUp() : void
  32. {
  33. parent::setUp();
  34. $this->user = User::factory()->create();
  35. }
  36. #[Test]
  37. public function test_sendRecoveryEmail_sends_notification_on_success()
  38. {
  39. Notification::fake();
  40. $response = $this->json('POST', '/webauthn/lost', [
  41. 'email' => $this->user->email,
  42. ]);
  43. Notification::assertSentTo($this->user, WebauthnRecoveryNotification::class);
  44. $response->assertStatus(200)
  45. ->assertJsonStructure([
  46. 'message',
  47. ]);
  48. $this->assertDatabaseHas(config('auth.passwords.webauthn.table'), [
  49. 'email' => $this->user->email,
  50. ]);
  51. }
  52. #[Test]
  53. public function test_sendRecoveryEmail_does_not_send_anything_to_unknown_email()
  54. {
  55. Notification::fake();
  56. $response = $this->json('POST', '/webauthn/lost', [
  57. 'email' => 'bad@email.com',
  58. ]);
  59. Notification::assertNothingSent();
  60. $response->assertStatus(422)
  61. ->assertJsonValidationErrors([
  62. 'email',
  63. ]);
  64. $this->assertDatabaseMissing(config('auth.passwords.webauthn.table'), [
  65. 'email' => 'bad@email.com',
  66. ]);
  67. }
  68. #[Test]
  69. public function test_sendRecoveryEmail_does_not_send_anything_to_invalid_email()
  70. {
  71. Notification::fake();
  72. $response = $this->json('POST', '/webauthn/lost', [
  73. 'email' => 'bad@email.com',
  74. ]);
  75. Notification::assertNothingSent();
  76. $response->assertStatus(422)
  77. ->assertJsonValidationErrors([
  78. 'email',
  79. ]);
  80. $this->assertDatabaseMissing(config('auth.passwords.webauthn.table'), [
  81. 'email' => 'bad@email.com',
  82. ]);
  83. }
  84. #[Test]
  85. public function test_sendRecoveryEmail_does_not_send_anything_to_not_WebAuthnAuthenticatable()
  86. {
  87. $mock = $this->mock(\App\Extensions\WebauthnCredentialBroker::class)->makePartial();
  88. $mock->shouldReceive('getUser')
  89. ->andReturn(new \Illuminate\Foundation\Auth\User);
  90. Notification::fake();
  91. $response = $this->json('POST', '/webauthn/lost', [
  92. 'email' => $this->user->email,
  93. ]);
  94. Notification::assertNothingSent();
  95. $response->assertStatus(422)
  96. ->assertJsonValidationErrors([
  97. 'email',
  98. ]);
  99. }
  100. #[Test]
  101. public function test_sendRecoveryEmail_is_throttled()
  102. {
  103. Notification::fake();
  104. $response = $this->json('POST', '/webauthn/lost', [
  105. 'email' => $this->user->email,
  106. ]);
  107. Notification::assertSentTo($this->user, WebauthnRecoveryNotification::class);
  108. $response->assertStatus(200)
  109. ->assertJsonStructure([
  110. 'message',
  111. ]);
  112. $this->assertDatabaseHas(config('auth.passwords.webauthn.table'), [
  113. 'email' => $this->user->email,
  114. ]);
  115. $this->json('POST', '/webauthn/lost', [
  116. 'email' => $this->user->email,
  117. ])
  118. ->assertStatus(422)
  119. ->assertJsonValidationErrorfor('email')
  120. ->assertJsonFragment([
  121. 'message' => __('passwords.throttled'),
  122. ]);
  123. }
  124. #[Test]
  125. public function test_error_if_no_broker_is_set()
  126. {
  127. $this->app['config']->set('auth.passwords.webauthn', null);
  128. $this->json('POST', '/webauthn/lost', [
  129. 'email' => $this->user->email,
  130. ])
  131. ->assertStatus(500);
  132. }
  133. }