Files
portal-api/tests/Feature/EmailTemplateServiceTest.php
T
2026-09-09 16:56:22 +07:00

130 lines
4.8 KiB
PHP

<?php
namespace Tests\Feature;
use App\Exceptions\InvalidTemplateVariableException;
use App\Jobs\Mail\SendTemplateEmailJob;
use App\Mail\GenericTemplateMail;
use App\Models\Template;
use App\Services\Email\EmailTemplateService;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;
class EmailTemplateServiceTest extends TestCase
{
use DatabaseTransactions;
private function makeTemplate(array $overrides = []): Template
{
return Template::create(array_merge([
'type_id' => 0,
'scenario' => 'unit_test_scenario_' . uniqid(),
'format' => 'html',
'name' => 'Test scenario',
'subject' => 'Xin chào {{full_name}}',
'message' => '<p>Chào {{full_name}}, mời truy cập {{login_url}}</p>',
'metadata' => [
'variables' => [
['key' => 'full_name', 'label' => 'Họ tên', 'type' => 'string', 'example' => 'Quý khách'],
['key' => 'login_url', 'label' => 'Link đăng nhập', 'type' => 'url', 'example' => 'https://example.com'],
],
],
'status' => 1,
], $overrides));
}
public function test_send_dispatches_job_to_queue(): void
{
Bus::fake();
$template = $this->makeTemplate();
app(EmailTemplateService::class)->send($template->scenario, 'user@example.com', [
'full_name' => 'Nguyễn Văn A',
'login_url' => 'https://portal.tgs.com.vn/login',
]);
Bus::assertDispatched(SendTemplateEmailJob::class, fn (SendTemplateEmailJob $job) => $job->scenario === $template->scenario
&& $job->to === ['user@example.com']
&& $job->data['full_name'] === 'Nguyễn Văn A');
}
public function test_job_renders_and_sends_mail_with_template_sender_config(): void
{
Mail::fake();
$template = $this->makeTemplate([
'metadata' => [
'variables' => [
['key' => 'full_name', 'label' => 'Họ tên', 'type' => 'string'],
['key' => 'login_url', 'label' => 'Link', 'type' => 'url'],
],
'mail' => [
'from_email' => 'noreply@tgs.com.vn',
'from_name' => 'Thế Giới Số',
'reply_to' => 'support@tgs.com.vn',
'reply_to_name' => 'TGS Support',
],
],
]);
(new SendTemplateEmailJob($template->scenario, ['user@example.com'], [
'full_name' => 'Nguyễn Văn A',
'login_url' => 'https://portal.tgs.com.vn/login',
]))->handle(app(EmailTemplateService::class), app(\App\Services\Email\EmailTemplateRenderer::class));
Mail::assertSent(GenericTemplateMail::class, function (GenericTemplateMail $mail) {
$mail->assertTo('user@example.com');
$envelope = $mail->envelope();
return $envelope->subject === 'Xin chào Nguyễn Văn A'
&& $envelope->from->address === 'noreply@tgs.com.vn'
&& $envelope->replyTo[0]->address === 'support@tgs.com.vn'
&& str_contains($mail->renderedHtml, 'Nguyễn Văn A');
});
}
public function test_job_falls_back_to_system_default_sender_when_template_has_no_mail_config(): void
{
Mail::fake();
$template = $this->makeTemplate();
(new SendTemplateEmailJob($template->scenario, ['user@example.com'], [
'full_name' => 'A',
'login_url' => 'https://example.com',
]))->handle(app(EmailTemplateService::class), app(\App\Services\Email\EmailTemplateRenderer::class));
Mail::assertSent(GenericTemplateMail::class, function (GenericTemplateMail $mail) {
return $mail->envelope()->from === null;
});
}
public function test_preview_throws_for_undeclared_variable(): void
{
$template = $this->makeTemplate([
'message' => '<p>{{full_name}} {{not_declared}}</p>',
]);
$this->expectException(InvalidTemplateVariableException::class);
app(EmailTemplateService::class)->preview($template->scenario, ['full_name' => 'A']);
}
public function test_load_template_is_cached_by_scenario(): void
{
$template = $this->makeTemplate();
$service = app(EmailTemplateService::class);
$first = $service->loadTemplate($template->scenario);
$this->assertSame('Xin chào {{full_name}}', $first->subject);
$template->update(['subject' => 'Đã đổi']); // model event must bust the cache
$second = $service->loadTemplate($template->scenario);
$this->assertSame('Đã đổi', $second->subject);
}
}