Files
portal-api/tests/Feature/Api/Admin/DnsManager/ProvisionDnsDomainTest.php
baodev0andClaude Opus 5.5 94614d9cb3 feat: khởi tạo/huỷ domain Plesk qua job, gửi mail hoá đơn qua queue, đính kèm triển khai
- ProvisionDnsDomainJob/SuspendDnsDomainJob: tạo domain admin lên Plesk, huỷ = suspend (is_created=3)
- Khách xem zone DNS được gán ở /dich-vu/domain, quản lý bản ghi A/AAAA/CNAME/TXT/MX/SRV
- send-mail hoá đơn đẩy SendInvoiceMailJob, preview + sửa nội dung, ghi mail.order_id
- invoice_attachments.type (payment_proof/deployment)
- CacheService xoá theo SCAN pattern, Redis không persistent mặc định
- Backfill transactions.public_code

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

168 lines
6.2 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Feature\Api\Admin\DnsManager;
use App\Jobs\DnsManager\ProvisionDnsDomainJob;
use App\Jobs\DnsManager\SuspendDnsDomainJob;
use App\Models\DnsDomain;
use App\Models\User;
use App\Services\Plesk\PleskDomainService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Queue;
use Mockery;
use Spatie\Permission\Models\Role;
use Tests\TestCase;
class ProvisionDnsDomainTest extends TestCase
{
use RefreshDatabase;
private int $serverId;
protected function setUp(): void
{
parent::setUp();
$this->serverId = DB::table('dns_manager_servers')->insertGetId(['ip_address' => '10.0.0.1', 'password' => 'x']);
}
private function domain(): DnsDomain
{
return DnsDomain::create(['domain_name' => 'example.vn', 'dns_manager_server_id' => $this->serverId, 'is_created' => 0]);
}
private function admin(): User
{
Role::firstOrCreate(['name' => 'Full Administrator', 'guard_name' => 'admin']);
$admin = User::factory()->create();
$admin->assignRole('Full Administrator');
return $admin;
}
public function test_destroy_cancels_domain_and_queues_plesk_suspend(): void
{
Queue::fake();
$domain = $this->domain();
$domain->update(['plesk_id' => 55, 'is_created' => DnsDomain::STATUS_CREATED]);
$customerId = \App\Models\Customer::factory()->create()->id;
$domain->customer()->attach($customerId);
$this->actingAs($this->admin(), 'admin')
->deleteJson("/api/v1/administrator/domains/{$domain->id}")
->assertOk();
$this->assertDatabaseHas('dns_manager_domain', ['id' => $domain->id, 'is_created' => DnsDomain::STATUS_CANCELLED]);
$this->assertDatabaseHas('dns_domain_user', ['domain_id' => $domain->id, 'user_id' => $customerId]);
Queue::assertPushed(SuspendDnsDomainJob::class, fn ($job) => $job->domainId === $domain->id);
}
public function test_destroy_without_plesk_domain_only_cancels(): void
{
Queue::fake();
$domain = $this->domain();
$this->actingAs($this->admin(), 'admin')
->deleteJson("/api/v1/administrator/domains/{$domain->id}")
->assertOk();
$this->assertDatabaseHas('dns_manager_domain', ['id' => $domain->id, 'is_created' => DnsDomain::STATUS_CANCELLED]);
Queue::assertNotPushed(SuspendDnsDomainJob::class);
}
public function test_suspend_job_calls_plesk_for_cancelled_domain(): void
{
$domain = $this->domain();
$domain->update(['is_created' => DnsDomain::STATUS_CANCELLED]);
$plesk = Mockery::mock(PleskDomainService::class);
$plesk->shouldReceive('suspend')->once()->with(Mockery::any(), 'example.vn')->andReturn(true);
(new SuspendDnsDomainJob($domain->id))->handle($plesk);
}
public function test_suspend_job_skips_domain_reactivated_before_it_ran(): void
{
$domain = $this->domain();
$plesk = Mockery::mock(PleskDomainService::class);
$plesk->shouldNotReceive('suspend');
(new SuspendDnsDomainJob($domain->id))->handle($plesk);
$this->addToAssertionCount(1);
}
public function test_store_queues_provisioning_on_selected_server(): void
{
Queue::fake();
$id = $this->actingAs($this->admin(), 'admin')
->postJson('/api/v1/administrator/domains', ['domain_name' => 'example.vn', 'dns_manager_server_id' => $this->serverId])
->assertCreated()
->assertJsonPath('data.provisioning_queued', true)
->json('data.id');
Queue::assertPushed(ProvisionDnsDomainJob::class, fn ($job) => $job->domainId === $id);
}
public function test_job_creates_domain_on_plesk_when_missing(): void
{
$domain = $this->domain();
$plesk = Mockery::mock(PleskDomainService::class);
$plesk->shouldReceive('getDomainInfo')->once()->andReturn(false);
$plesk->shouldReceive('createDomain')->once()->with(Mockery::any(), ['domain_name' => 'example.vn'])->andReturn(['id' => 55, 'guid' => 'g']);
(new ProvisionDnsDomainJob($domain->id))->handle($plesk);
$this->assertDatabaseHas('dns_manager_domain', ['id' => $domain->id, 'plesk_id' => 55, 'is_created' => 1]);
}
public function test_job_links_existing_plesk_domain_without_creating(): void
{
$domain = $this->domain();
$plesk = Mockery::mock(PleskDomainService::class);
$plesk->shouldReceive('getDomainInfo')->once()->andReturn(['id' => 77, 'name' => 'example.vn']);
$plesk->shouldNotReceive('createDomain');
(new ProvisionDnsDomainJob($domain->id))->handle($plesk);
$this->assertDatabaseHas('dns_manager_domain', ['id' => $domain->id, 'plesk_id' => 77, 'is_created' => 1]);
}
public function test_job_fails_and_keeps_domain_uncreated_when_plesk_rejects(): void
{
$domain = $this->domain();
$plesk = Mockery::mock(PleskDomainService::class);
$plesk->shouldReceive('getDomainInfo')->andReturn(false);
$plesk->shouldReceive('createDomain')->andReturn(false);
$plesk->shouldReceive('getLastError')->andReturn('boom');
$this->expectExceptionMessage('boom');
try {
(new ProvisionDnsDomainJob($domain->id))->handle($plesk);
} finally {
$this->assertDatabaseHas('dns_manager_domain', ['id' => $domain->id, 'plesk_id' => null, 'is_created' => 0]);
}
}
public function test_provision_endpoint_requeues_only_uncreated_active_domains(): void
{
Queue::fake();
$admin = $this->admin();
$domain = $this->domain();
$url = "/api/v1/administrator/domains/{$domain->id}/provision";
$this->actingAs($admin, 'admin')->postJson($url)->assertOk();
Queue::assertPushed(ProvisionDnsDomainJob::class, 1);
$domain->update(['plesk_id' => 9]);
$this->actingAs($admin, 'admin')->postJson($url)->assertStatus(422);
$domain->update(['plesk_id' => null, 'is_created' => DnsDomain::STATUS_CANCELLED]);
$this->actingAs($admin, 'admin')->postJson($url)->assertStatus(422);
Queue::assertPushed(ProvisionDnsDomainJob::class, 1);
}
}