|
@@ -0,0 +1,206 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+
|
|
|
|
|
+namespace Tests\Feature;
|
|
|
|
|
+
|
|
|
|
|
+use App\Enums\ApprovalStatusEnum;
|
|
|
|
|
+use App\Enums\PushNotificationCategoryEnum;
|
|
|
|
|
+use App\Enums\PushNotificationTargetEnum;
|
|
|
|
|
+use App\Enums\UserTypeEnum;
|
|
|
|
|
+use App\Models\DeviceToken;
|
|
|
|
|
+use App\Models\Provider;
|
|
|
|
|
+use App\Models\PushNotificationLog;
|
|
|
|
|
+use App\Models\User;
|
|
|
|
|
+use App\Notifications\Push\Prestador\Transacional\CadastroAprovadoPush;
|
|
|
|
|
+use App\Services\ProviderService;
|
|
|
|
|
+use App\Services\PushNotificationService;
|
|
|
|
|
+use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
|
+use Illuminate\Support\Facades\Mail;
|
|
|
|
|
+use Mockery\MockInterface;
|
|
|
|
|
+use Tests\TestCase;
|
|
|
|
|
+
|
|
|
|
|
+class ProviderApprovalPushTest extends TestCase
|
|
|
|
|
+{
|
|
|
|
|
+ use RefreshDatabase;
|
|
|
|
|
+
|
|
|
|
|
+ private ProviderService $service;
|
|
|
|
|
+
|
|
|
|
|
+ protected function setUp(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ parent::setUp();
|
|
|
|
|
+
|
|
|
|
|
+ Mail::fake();
|
|
|
|
|
+
|
|
|
|
|
+ $this->service = app(ProviderService::class);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function test_aprovar_prestador_dispara_push_de_cadastro_aprovado(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $provider = $this->makeProvider();
|
|
|
|
|
+
|
|
|
|
|
+ $this->withDeviceToken($provider->user);
|
|
|
|
|
+
|
|
|
|
|
+ $push = $this->mockPushService();
|
|
|
|
|
+
|
|
|
|
|
+ $push->shouldReceive('sendToUser')
|
|
|
|
|
+ ->once()
|
|
|
|
|
+ ->withArgs(function (User $user, $notification) use ($provider) {
|
|
|
|
|
+ return $user->is($provider->user)
|
|
|
|
|
+ && $notification instanceof CadastroAprovadoPush;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ $approved = $this->service->approve($provider->id);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertSame(ApprovalStatusEnum::ACCEPTED->value, $approved->approval_status->value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function test_update_para_accepted_dispara_push(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $provider = $this->makeProvider();
|
|
|
|
|
+
|
|
|
|
|
+ $this->withDeviceToken($provider->user);
|
|
|
|
|
+
|
|
|
|
|
+ $push = $this->mockPushService();
|
|
|
|
|
+
|
|
|
|
|
+ $push->shouldReceive('sendToUser')->once();
|
|
|
|
|
+
|
|
|
|
|
+ $this->service->update($provider->id, [
|
|
|
|
|
+ 'approval_status' => ApprovalStatusEnum::ACCEPTED->value,
|
|
|
|
|
+ ]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function test_update_que_nao_muda_o_status_nao_dispara_push(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $provider = $this->makeProvider();
|
|
|
|
|
+
|
|
|
|
|
+ $this->withDeviceToken($provider->user);
|
|
|
|
|
+
|
|
|
|
|
+ $push = $this->mockPushService();
|
|
|
|
|
+
|
|
|
|
|
+ $push->shouldNotReceive('sendToUser');
|
|
|
|
|
+
|
|
|
|
|
+ $this->service->update($provider->id, ['birth_date' => '1991-02-02']);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function test_aprovar_prestador_ja_aprovado_nao_reenvia_push(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $provider = $this->makeProvider(ApprovalStatusEnum::ACCEPTED);
|
|
|
|
|
+
|
|
|
|
|
+ $this->withDeviceToken($provider->user);
|
|
|
|
|
+
|
|
|
|
|
+ $push = $this->mockPushService();
|
|
|
|
|
+
|
|
|
|
|
+ $push->shouldNotReceive('sendToUser');
|
|
|
|
|
+
|
|
|
|
|
+ $this->service->approve($provider->id);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Rede de seguranca extra: mesmo que a transicao seja detectada de novo
|
|
|
|
|
+ * (reprovar e reaprovar, por exemplo), o log impede o envio duplicado.
|
|
|
|
|
+ */
|
|
|
|
|
+ public function test_push_ja_registrada_no_log_nao_e_reenviada(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $provider = $this->makeProvider();
|
|
|
|
|
+
|
|
|
|
|
+ $this->withDeviceToken($provider->user);
|
|
|
|
|
+
|
|
|
|
|
+ PushNotificationLog::query()->create([
|
|
|
|
|
+ 'label' => (new CadastroAprovadoPush)->label(),
|
|
|
|
|
+ 'user_id' => $provider->user->id,
|
|
|
|
|
+ 'target' => PushNotificationTargetEnum::PRESTADOR->value,
|
|
|
|
|
+ 'category' => PushNotificationCategoryEnum::TRANSACIONAL->value,
|
|
|
|
|
+ 'sent_at' => now()->subDay(),
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ $push = $this->mockPushService();
|
|
|
|
|
+
|
|
|
|
|
+ $push->shouldNotReceive('sendToUser');
|
|
|
|
|
+
|
|
|
|
|
+ $this->service->approve($provider->id);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function test_prestador_sem_device_token_ativo_nao_dispara_push(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $provider = $this->makeProvider();
|
|
|
|
|
+
|
|
|
|
|
+ $this->withDeviceToken($provider->user, active: false);
|
|
|
|
|
+
|
|
|
|
|
+ $push = $this->mockPushService();
|
|
|
|
|
+
|
|
|
|
|
+ $push->shouldNotReceive('sendToUser');
|
|
|
|
|
+
|
|
|
|
|
+ $approved = $this->service->approve($provider->id);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertSame(ApprovalStatusEnum::ACCEPTED->value, $approved->approval_status->value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function test_token_de_outro_app_nao_dispara_push_do_prestador(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $provider = $this->makeProvider();
|
|
|
|
|
+
|
|
|
|
|
+ $this->withDeviceToken($provider->user, appType: PushNotificationTargetEnum::CLIENTE);
|
|
|
|
|
+
|
|
|
|
|
+ $push = $this->mockPushService();
|
|
|
|
|
+
|
|
|
|
|
+ $push->shouldNotReceive('sendToUser');
|
|
|
|
|
+
|
|
|
|
|
+ $this->service->approve($provider->id);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function test_falha_no_envio_da_push_nao_impede_a_aprovacao(): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $provider = $this->makeProvider();
|
|
|
|
|
+
|
|
|
|
|
+ $this->withDeviceToken($provider->user);
|
|
|
|
|
+
|
|
|
|
|
+ $push = $this->mockPushService();
|
|
|
|
|
+
|
|
|
|
|
+ $push->shouldReceive('sendToUser')
|
|
|
|
|
+ ->once()
|
|
|
|
|
+ ->andThrow(new \RuntimeException('FCM indisponivel'));
|
|
|
|
|
+
|
|
|
|
|
+ $approved = $this->service->approve($provider->id);
|
|
|
|
|
+
|
|
|
|
|
+ $this->assertSame(ApprovalStatusEnum::ACCEPTED->value, $approved->approval_status->value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //
|
|
|
|
|
+
|
|
|
|
|
+ private function mockPushService(): MockInterface
|
|
|
|
|
+ {
|
|
|
|
|
+ return $this->mock(PushNotificationService::class);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function makeProvider(?ApprovalStatusEnum $status = null): Provider
|
|
|
|
|
+ {
|
|
|
|
|
+ $user = User::query()->create([
|
|
|
|
|
+ 'name' => 'Prestador Teste',
|
|
|
|
|
+ 'email' => 'prestador'.uniqid().'@teste.com',
|
|
|
|
|
+ 'password' => 'secret',
|
|
|
|
|
+ 'type' => UserTypeEnum::PROVIDER->value,
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ $provider = Provider::query()->create([
|
|
|
|
|
+ 'user_id' => $user->id,
|
|
|
|
|
+ 'document' => '06767310905',
|
|
|
|
|
+ 'birth_date' => '1990-01-01',
|
|
|
|
|
+ 'approval_status' => ($status ?? ApprovalStatusEnum::PENDING)->value,
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ return $provider->load('user');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function withDeviceToken(
|
|
|
|
|
+ User $user,
|
|
|
|
|
+ bool $active = true,
|
|
|
|
|
+ ?PushNotificationTargetEnum $appType = null,
|
|
|
|
|
+ ): DeviceToken {
|
|
|
|
|
+ return DeviceToken::query()->create([
|
|
|
|
|
+ 'user_id' => $user->id,
|
|
|
|
|
+ 'token' => 'tok_'.uniqid(),
|
|
|
|
|
+ 'platform' => 'android',
|
|
|
|
|
+ 'app_type' => ($appType ?? PushNotificationTargetEnum::PRESTADOR)->value,
|
|
|
|
|
+ 'active' => $active,
|
|
|
|
|
+ ]);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|