ProviderApprovalPushTest.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <?php
  2. namespace Tests\Feature;
  3. use App\Enums\ApprovalStatusEnum;
  4. use App\Enums\PushNotificationCategoryEnum;
  5. use App\Enums\PushNotificationTargetEnum;
  6. use App\Enums\UserTypeEnum;
  7. use App\Models\DeviceToken;
  8. use App\Models\Provider;
  9. use App\Models\PushNotificationLog;
  10. use App\Models\User;
  11. use App\Notifications\Push\Prestador\Transacional\CadastroAprovadoPush;
  12. use App\Services\ProviderService;
  13. use App\Services\PushNotificationService;
  14. use Illuminate\Foundation\Testing\RefreshDatabase;
  15. use Illuminate\Support\Facades\Mail;
  16. use Mockery\MockInterface;
  17. use Tests\TestCase;
  18. class ProviderApprovalPushTest extends TestCase
  19. {
  20. use RefreshDatabase;
  21. private ProviderService $service;
  22. protected function setUp(): void
  23. {
  24. parent::setUp();
  25. Mail::fake();
  26. $this->service = app(ProviderService::class);
  27. }
  28. public function test_aprovar_prestador_dispara_push_de_cadastro_aprovado(): void
  29. {
  30. $provider = $this->makeProvider();
  31. $this->withDeviceToken($provider->user);
  32. $push = $this->mockPushService();
  33. $push->shouldReceive('sendToUser')
  34. ->once()
  35. ->withArgs(function (User $user, $notification) use ($provider) {
  36. return $user->is($provider->user)
  37. && $notification instanceof CadastroAprovadoPush;
  38. });
  39. $approved = $this->service->approve($provider->id);
  40. $this->assertSame(ApprovalStatusEnum::ACCEPTED->value, $approved->approval_status->value);
  41. }
  42. public function test_update_para_accepted_dispara_push(): void
  43. {
  44. $provider = $this->makeProvider();
  45. $this->withDeviceToken($provider->user);
  46. $push = $this->mockPushService();
  47. $push->shouldReceive('sendToUser')->once();
  48. $this->service->update($provider->id, [
  49. 'approval_status' => ApprovalStatusEnum::ACCEPTED->value,
  50. ]);
  51. }
  52. public function test_update_que_nao_muda_o_status_nao_dispara_push(): void
  53. {
  54. $provider = $this->makeProvider();
  55. $this->withDeviceToken($provider->user);
  56. $push = $this->mockPushService();
  57. $push->shouldNotReceive('sendToUser');
  58. $this->service->update($provider->id, ['birth_date' => '1991-02-02']);
  59. }
  60. public function test_aprovar_prestador_ja_aprovado_nao_reenvia_push(): void
  61. {
  62. $provider = $this->makeProvider(ApprovalStatusEnum::ACCEPTED);
  63. $this->withDeviceToken($provider->user);
  64. $push = $this->mockPushService();
  65. $push->shouldNotReceive('sendToUser');
  66. $this->service->approve($provider->id);
  67. }
  68. /**
  69. * Rede de seguranca extra: mesmo que a transicao seja detectada de novo
  70. * (reprovar e reaprovar, por exemplo), o log impede o envio duplicado.
  71. */
  72. public function test_push_ja_registrada_no_log_nao_e_reenviada(): void
  73. {
  74. $provider = $this->makeProvider();
  75. $this->withDeviceToken($provider->user);
  76. PushNotificationLog::query()->create([
  77. 'label' => (new CadastroAprovadoPush)->label(),
  78. 'user_id' => $provider->user->id,
  79. 'target' => PushNotificationTargetEnum::PRESTADOR->value,
  80. 'category' => PushNotificationCategoryEnum::TRANSACIONAL->value,
  81. 'sent_at' => now()->subDay(),
  82. ]);
  83. $push = $this->mockPushService();
  84. $push->shouldNotReceive('sendToUser');
  85. $this->service->approve($provider->id);
  86. }
  87. public function test_prestador_sem_device_token_ativo_nao_dispara_push(): void
  88. {
  89. $provider = $this->makeProvider();
  90. $this->withDeviceToken($provider->user, active: false);
  91. $push = $this->mockPushService();
  92. $push->shouldNotReceive('sendToUser');
  93. $approved = $this->service->approve($provider->id);
  94. $this->assertSame(ApprovalStatusEnum::ACCEPTED->value, $approved->approval_status->value);
  95. }
  96. public function test_token_de_outro_app_nao_dispara_push_do_prestador(): void
  97. {
  98. $provider = $this->makeProvider();
  99. $this->withDeviceToken($provider->user, appType: PushNotificationTargetEnum::CLIENTE);
  100. $push = $this->mockPushService();
  101. $push->shouldNotReceive('sendToUser');
  102. $this->service->approve($provider->id);
  103. }
  104. public function test_falha_no_envio_da_push_nao_impede_a_aprovacao(): void
  105. {
  106. $provider = $this->makeProvider();
  107. $this->withDeviceToken($provider->user);
  108. $push = $this->mockPushService();
  109. $push->shouldReceive('sendToUser')
  110. ->once()
  111. ->andThrow(new \RuntimeException('FCM indisponivel'));
  112. $approved = $this->service->approve($provider->id);
  113. $this->assertSame(ApprovalStatusEnum::ACCEPTED->value, $approved->approval_status->value);
  114. }
  115. //
  116. private function mockPushService(): MockInterface
  117. {
  118. return $this->mock(PushNotificationService::class);
  119. }
  120. private function makeProvider(?ApprovalStatusEnum $status = null): Provider
  121. {
  122. $user = User::query()->create([
  123. 'name' => 'Prestador Teste',
  124. 'email' => 'prestador'.uniqid().'@teste.com',
  125. 'password' => 'secret',
  126. 'type' => UserTypeEnum::PROVIDER->value,
  127. ]);
  128. $provider = Provider::query()->create([
  129. 'user_id' => $user->id,
  130. 'document' => '06767310905',
  131. 'birth_date' => '1990-01-01',
  132. 'approval_status' => ($status ?? ApprovalStatusEnum::PENDING)->value,
  133. ]);
  134. return $provider->load('user');
  135. }
  136. private function withDeviceToken(
  137. User $user,
  138. bool $active = true,
  139. ?PushNotificationTargetEnum $appType = null,
  140. ): DeviceToken {
  141. return DeviceToken::query()->create([
  142. 'user_id' => $user->id,
  143. 'token' => 'tok_'.uniqid(),
  144. 'platform' => 'android',
  145. 'app_type' => ($appType ?? PushNotificationTargetEnum::PRESTADOR)->value,
  146. 'active' => $active,
  147. ]);
  148. }
  149. }