update
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Feature\Api\Admin\Customer;
|
||||
|
||||
use App\Models\Customer;
|
||||
use App\Models\ModuleVmware;
|
||||
use App\Models\Service;
|
||||
use App\Models\User;
|
||||
use App\Models\VirtualMachines;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\Permission\Models\Role;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssignServiceVmTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
private User $admin;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Role::firstOrCreate(['name' => 'Full Administrator', 'guard_name' => 'admin']);
|
||||
$this->admin = User::factory()->create();
|
||||
$this->admin->assignRole('Full Administrator');
|
||||
}
|
||||
|
||||
private function vm(string $vmId): VirtualMachines
|
||||
{
|
||||
Schema::disableForeignKeyConstraints();
|
||||
|
||||
return VirtualMachines::create([
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'vm_id' => $vmId,
|
||||
'name' => "name-{$vmId}",
|
||||
'cpu' => 2,
|
||||
'ram_mb' => 2048,
|
||||
'is_template' => 0,
|
||||
'is_system' => 0,
|
||||
'datacenter_id' => 1,
|
||||
'host_id' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
private function assign(Customer $customer, Service $service, VirtualMachines $vm)
|
||||
{
|
||||
return $this->actingAs($this->admin, 'admin')->putJson(
|
||||
"/api/v1/administrator/customers/{$customer->uuid}/services/{$service->id}",
|
||||
['virtual_machine_id' => $vm->id],
|
||||
);
|
||||
}
|
||||
|
||||
public function test_assigns_and_reassigns_vm_and_rejects_vm_of_another_service(): void
|
||||
{
|
||||
$customer = Customer::factory()->create();
|
||||
$service = Service::create(['customer_id' => $customer->id, 'status' => 'active']);
|
||||
$first = $this->vm('vm-1');
|
||||
$second = $this->vm('vm-2');
|
||||
|
||||
$this->assign($customer, $service, $first)->assertOk();
|
||||
$service->refresh();
|
||||
$moduleId = $service->vm_id;
|
||||
$this->assertNotNull($moduleId);
|
||||
$this->assertSame($service->id, (int) ModuleVmware::find($moduleId)->service_id);
|
||||
|
||||
$this->assign($customer, $service, $second)->assertOk();
|
||||
$service->refresh();
|
||||
$this->assertSame($moduleId, $service->vm_id);
|
||||
$this->assertSame('vm-2', ModuleVmware::find($moduleId)->vmware_id);
|
||||
|
||||
$other = Service::create(['customer_id' => $customer->id, 'status' => 'active']);
|
||||
$this->assign($customer, $other, $second)->assertStatus(422);
|
||||
$this->assertNull($other->refresh()->vm_id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Feature\Api\Service;
|
||||
|
||||
use App\Http\Services\vCenter as VCenterService;
|
||||
use App\Models\Customer;
|
||||
use App\Models\ModuleVmware;
|
||||
use App\Models\Order;
|
||||
use App\Models\OrderItem;
|
||||
use App\Models\Service;
|
||||
use App\Models\vCenter;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Str;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ConsoleTicketResolvesVmTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_console_ticket_uses_service_vm_when_order_is_soft_deleted(): void
|
||||
{
|
||||
$customer = Customer::factory()->create();
|
||||
$order = Order::create(['order_num' => 'ORD-' . Str::random(10), 'customer_id' => $customer->id]);
|
||||
$orderItem = OrderItem::create(['order_id' => $order->id]);
|
||||
$vcenter = vCenter::create(['host' => 'vc.test', 'user' => 'u', 'password' => 'p', 'status' => 1]);
|
||||
$vm = ModuleVmware::create([
|
||||
'name' => 'vm',
|
||||
'customer_id' => $customer->id,
|
||||
'order_id' => $order->id,
|
||||
'vmware_id' => 'vm-1',
|
||||
'vcenter_id' => $vcenter->id,
|
||||
'status' => 1,
|
||||
]);
|
||||
$service = Service::create([
|
||||
'customer_id' => $customer->id,
|
||||
'order_item_id' => $orderItem->id,
|
||||
'vm_id' => $vm->id,
|
||||
'status' => 'active',
|
||||
]);
|
||||
$order->delete();
|
||||
|
||||
$this->mock(VCenterService::class)->shouldReceive('loginServer')->once()->andReturnFalse();
|
||||
|
||||
$this->actingAs($customer, 'client')
|
||||
->withHeaders(['x-access-token' => $this->buildClientAccessToken()])
|
||||
->getJson("/v1/client/client-service/{$service->uuid}/console-ticket")
|
||||
->assertOk()
|
||||
->assertJsonPath('message', 'Không thể đăng nhập vào vCenter');
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,11 @@ use App\Enums\Order\OrderStatus;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Order;
|
||||
use App\Jobs\Mail\SendTemplateEmailJob;
|
||||
use App\Services\InvoiceReminderService;
|
||||
use App\Support\AutoEmailGate;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
use Tests\TestCase;
|
||||
|
||||
@@ -25,6 +28,32 @@ class InvoiceReminderTest extends TestCase
|
||||
// không phụ thuộc template có trong DB hay không.
|
||||
Queue::fake();
|
||||
config(['billing.reminder_offsets' => [-7, -3, 0, 3]]);
|
||||
$this->setAutoDisabled([]);
|
||||
}
|
||||
|
||||
private function setAutoDisabled(array $scenarios): void
|
||||
{
|
||||
DB::table('setting')->updateOrInsert(['key' => 'email_settings'], ['value' => json_encode(['auto_disabled' => $scenarios])]);
|
||||
}
|
||||
|
||||
public function test_disabled_automatic_reminder_is_not_sent_and_step_stays(): void
|
||||
{
|
||||
$this->setAutoDisabled([InvoiceReminderService::SCENARIO]);
|
||||
$invoice = $this->makeInvoice(now()->addDays(5));
|
||||
|
||||
$this->artisan('invoices:send-reminders')->assertExitCode(0);
|
||||
|
||||
$this->assertSame(0, (int) $invoice->fresh()->reminder_step);
|
||||
Queue::assertNotPushed(SendTemplateEmailJob::class);
|
||||
}
|
||||
|
||||
public function test_manual_reminder_is_sent_while_automatic_is_disabled(): void
|
||||
{
|
||||
$this->setAutoDisabled([InvoiceReminderService::SCENARIO]);
|
||||
$invoice = $this->makeInvoice(now()->addDays(5));
|
||||
AutoEmailGate::markManual();
|
||||
|
||||
$this->assertTrue(app(InvoiceReminderService::class)->remind($invoice, force: true));
|
||||
}
|
||||
|
||||
public function test_no_reminder_is_sent_before_the_first_offset(): void
|
||||
|
||||
@@ -15,6 +15,7 @@ use App\Models\Service;
|
||||
use App\Repositories\Api\Order\OrderRepository;
|
||||
use App\Services\InvoiceReminderService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
use Tests\TestCase;
|
||||
|
||||
@@ -31,6 +32,7 @@ class PostWhmcsSyncSafetyTest extends TestCase
|
||||
parent::setUp();
|
||||
Queue::fake();
|
||||
config(['billing.reminder_offsets' => [-7, -3, 0, 3, 7]]);
|
||||
DB::table('setting')->updateOrInsert(['key' => 'email_settings'], ['value' => json_encode(['auto_disabled' => []])]);
|
||||
}
|
||||
|
||||
/** Hoá đơn quá hạn nhiều năm KHÔNG được mở lại chuỗi nhắc nợ. */
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Mail\ExpiryService;
|
||||
use App\Mail\GenericTemplateMail;
|
||||
use App\Models\Setting;
|
||||
use App\Support\AutoEmailGate;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Tests\TestCase;
|
||||
|
||||
class MailEnabledToggleTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
|
||||
private function setMailEnabled(bool $enabled): void
|
||||
{
|
||||
$setting = Setting::firstOrNew(['key' => 'email_settings']);
|
||||
$current = $setting->value ? json_decode($setting->value, true) : [];
|
||||
$setting->value = json_encode(array_merge($current, ['mail_enabled' => $enabled]));
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
private function disableAuto(array $scenarios): void
|
||||
{
|
||||
$setting = Setting::firstOrNew(['key' => 'email_settings']);
|
||||
$current = $setting->value ? json_decode($setting->value, true) : [];
|
||||
$setting->value = json_encode(array_merge($current, ['mail_enabled' => true, 'auto_disabled' => $scenarios]));
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
private function send(?string $scenario = null): mixed
|
||||
{
|
||||
return Mail::to('user@example.com')->send(new GenericTemplateMail('Subject', '<p>Body</p>', [], $scenario));
|
||||
}
|
||||
|
||||
public function test_mail_is_blocked_when_disabled(): void
|
||||
{
|
||||
$this->setMailEnabled(false);
|
||||
|
||||
$this->assertNull($this->send());
|
||||
$this->assertCount(0, Mail::mailer()->getSymfonyTransport()->messages());
|
||||
}
|
||||
|
||||
public function test_mail_is_sent_when_enabled(): void
|
||||
{
|
||||
$this->setMailEnabled(true);
|
||||
|
||||
$this->assertNotNull($this->send());
|
||||
$this->assertCount(1, Mail::mailer()->getSymfonyTransport()->messages());
|
||||
}
|
||||
|
||||
public function test_disabled_scenario_is_blocked_but_others_are_sent(): void
|
||||
{
|
||||
$this->disableAuto(['invoice_payment_reminder']);
|
||||
|
||||
$this->assertNull($this->send('invoice_payment_reminder'));
|
||||
$this->assertNotNull($this->send('order_created'));
|
||||
$this->assertNotNull($this->send());
|
||||
}
|
||||
|
||||
public function test_manual_send_bypasses_disabled_scenario(): void
|
||||
{
|
||||
$this->disableAuto(['invoice_payment_reminder']);
|
||||
AutoEmailGate::markManual();
|
||||
|
||||
$this->assertNotNull($this->send('invoice_payment_reminder'));
|
||||
}
|
||||
|
||||
public function test_template_mailable_exposes_its_scenario(): void
|
||||
{
|
||||
$this->assertSame('service_expiry', (new ExpiryService(0, []))->buildViewData()[AutoEmailGate::SCENARIO_DATA_KEY]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?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_every_placeholder_has_a_variable_definition(): void
|
||||
{
|
||||
foreach (TemplateSeeder::templates() 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']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user