133 lines
4.2 KiB
PHP
133 lines
4.2 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\Notification;
|
|
|
|
use App\Domains\Integration\Services\MailService;
|
|
use App\Domains\Notification\Services\NotificationMailService;
|
|
use App\Domains\Purchase\Models\Purchase;
|
|
use App\Domains\Ticket\Services\TicketPdfService;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Mockery;
|
|
use ReflectionMethod;
|
|
use RuntimeException;
|
|
use Tests\TestCase;
|
|
|
|
class NotificationMailServiceLoggingTest extends TestCase
|
|
{
|
|
private NotificationMailService $service;
|
|
|
|
private MailService $mailService;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$this->mailService = Mockery::mock(MailService::class);
|
|
$this->service = new NotificationMailService(
|
|
$this->mailService,
|
|
Mockery::mock(TicketPdfService::class),
|
|
);
|
|
}
|
|
|
|
public function test_it_logs_and_swallows_a_missing_purchase(): void
|
|
{
|
|
$this->createEmptyPurchasesTable();
|
|
|
|
Log::shouldReceive('channel')->once()->with('emails')->andReturnSelf();
|
|
Log::shouldReceive('warning')->once()->with(
|
|
'Notification email skipped.',
|
|
[
|
|
'purchase_id' => 123,
|
|
'reason' => 'purchase_not_found',
|
|
'missing_model' => Purchase::class,
|
|
'email_type' => 'purchase_paid',
|
|
],
|
|
);
|
|
|
|
$this->service->sendPurchasePaid(123);
|
|
}
|
|
|
|
public function test_missing_purchase_log_includes_the_requested_ticket_ids(): void
|
|
{
|
|
$this->createEmptyPurchasesTable();
|
|
|
|
Log::shouldReceive('channel')->once()->with('emails')->andReturnSelf();
|
|
Log::shouldReceive('warning')->once()->with(
|
|
'Notification email skipped.',
|
|
[
|
|
'purchase_id' => 123,
|
|
'requested_ticket_count' => 2,
|
|
'requested_ticket_ids' => [10, 11],
|
|
'reason' => 'purchase_not_found',
|
|
'missing_model' => Purchase::class,
|
|
'email_type' => 'tickets_available',
|
|
],
|
|
);
|
|
|
|
$this->service->sendTicketsAvailable(123, [10, 11]);
|
|
}
|
|
|
|
public function test_it_logs_successful_delivery_with_the_mailer(): void
|
|
{
|
|
$this->mailService->shouldReceive('mailerName')->once()->andReturn('smtp');
|
|
Log::shouldReceive('channel')->once()->with('emails')->andReturnSelf();
|
|
Log::shouldReceive('info')->once()->with(
|
|
'Notification email sent.',
|
|
[
|
|
'user_id' => 10,
|
|
'tenant_code' => 'tenant-test',
|
|
'email_type' => 'welcome',
|
|
'mailer' => 'smtp',
|
|
],
|
|
);
|
|
|
|
$this->sendLogged(
|
|
'welcome',
|
|
['user_id' => 10],
|
|
fn (): array => ['tenant_code' => 'tenant-test'],
|
|
);
|
|
}
|
|
|
|
public function test_it_logs_and_rethrows_delivery_failures(): void
|
|
{
|
|
$exception = new RuntimeException('SMTP unavailable.');
|
|
Log::shouldReceive('channel')->once()->with('emails')->andReturnSelf();
|
|
Log::shouldReceive('error')->once()->with(
|
|
'Notification email delivery failed.',
|
|
Mockery::on(fn (array $context): bool => $context['purchase_id'] === 123
|
|
&& $context['email_type'] === 'purchase_paid'
|
|
&& $context['exception'] === $exception),
|
|
);
|
|
|
|
$this->expectExceptionObject($exception);
|
|
|
|
$this->sendLogged('purchase_paid', ['purchase_id' => 123], function () use ($exception): array {
|
|
throw $exception;
|
|
});
|
|
}
|
|
|
|
/** @param array<string, mixed> $context */
|
|
private function sendLogged(string $emailType, array $context, callable $send): void
|
|
{
|
|
(new ReflectionMethod($this->service, 'sendLogged'))->invoke(
|
|
$this->service,
|
|
$emailType,
|
|
$context,
|
|
$send,
|
|
);
|
|
}
|
|
|
|
private function createEmptyPurchasesTable(): void
|
|
{
|
|
config([
|
|
'database.default' => 'sqlite',
|
|
'database.connections.sqlite.database' => ':memory:',
|
|
]);
|
|
Schema::connection('sqlite')->create('compras', function (Blueprint $table): void {
|
|
$table->id();
|
|
});
|
|
}
|
|
}
|