Files
portal-api/tests/Feature/TemplateSeederTest.php
T
baodev0andClaude Opus 5.5 30898ea46f feat: email gửi tay/nhắc gia hạn, gói hosting, sửa dữ liệu sản phẩm
- Gửi email theo template cho 1 khách, tab lịch sử email, nhắc gia hạn dịch vụ hàng loạt
- Mail lưu from/bcc/sent_by; mẫu MARKETING và mẫu cũ trong TemplateSeeder
- Gói hosting: giới hạn, trạng thái, lấy plan Plesk qua CLI gateway
- Backfill payment_method và ngày đơn hàng còn thiếu
- Bổ sung field CPU/RAM/Disk/Băng thông cho loại sản phẩm vps và cloud

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:32:05 +07:00

74 lines
3.1 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\Template;
use App\Services\Email\EmailTemplateRenderer;
use App\Services\Email\EmailTemplateService;
use App\Support\EmailScenarioRegistry;
use App\Support\MailPlaceholders;
use Database\Seeders\EmailTemplates\TemplateVariables;
use Database\Seeders\TemplateSeeder;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;
class TemplateSeederTest extends TestCase
{
use DatabaseTransactions;
public function test_seeder_covers_every_registered_scenario_with_required_variables(): void
{
$templates = collect(TemplateSeeder::templates())->keyBy('scenario');
$this->assertEqualsCanonicalizing(array_keys(EmailScenarioRegistry::SCENARIOS), $templates->keys()->all());
foreach (EmailScenarioRegistry::SCENARIOS as $scenario => $definition) {
$item = $templates[$scenario];
$this->assertSame([], EmailScenarioRegistry::missingVariables($definition['required_variables'], $item['subject'], $item['message']), $scenario);
$this->assertStringContainsString('class="NoiDungKM"', $item['message'], $scenario);
$this->assertStringContainsString('class="Footer"', $item['message'], $scenario);
}
}
public function test_legacy_templates_use_the_shared_shell(): void
{
foreach (TemplateSeeder::legacyTemplates() as $item) {
$this->assertNull(EmailScenarioRegistry::find($item['scenario']), $item['scenario']);
$this->assertStringContainsString('class="Header"', $item['message'], $item['scenario']);
$this->assertStringContainsString('class="Footer"', $item['message'], $item['scenario']);
}
}
public function test_every_placeholder_has_a_variable_definition(): void
{
foreach ([...TemplateSeeder::templates(), ...TemplateSeeder::legacyTemplates()] as $item) {
$unknown = array_diff(MailPlaceholders::extract($item['subject'], $item['message']), array_keys(TemplateVariables::DEFINITIONS));
$this->assertSame([], array_values($unknown), $item['scenario']);
}
}
public function test_seeded_templates_render_and_rerun_updates_in_place(): void
{
$this->seed(TemplateSeeder::class);
$countAfterFirstRun = Template::count();
$this->seed(TemplateSeeder::class);
$this->assertSame($countAfterFirstRun, Template::count());
$service = app(EmailTemplateService::class);
$renderer = app(EmailTemplateRenderer::class);
foreach (array_keys(EmailScenarioRegistry::SCENARIOS) as $scenario) {
if ($scenario === 'layout') {
continue;
}
$template = $service->loadTemplate($scenario);
$rendered = $renderer->render($template, []);
$this->assertDoesNotMatchRegularExpression(MailPlaceholders::PATTERN, $rendered['subject'] . $rendered['html'], $scenario);
}
$this->assertSame('html', $service->loadTemplate('invoice_notification')->variables()['pay_button']['type']);
$this->assertSame('string', $service->loadTemplate('manual_deposit_status')->variables()['status_label']['type']);
}
}