1
0
Files
breadcrumb-the-shire/modules/helpdesk/tests/Module/Helpdesk/Service/DomainDetailServiceTest.php
fs 693d33a0c8 feat(helpdesk): add domain detail page with customer, contract, and handover sections
New domain detail page showing customer info, contract data, linked handovers,
updates section, and related domains for the same customer. Data loaded async
with skeleton loading states. Includes DomainDetailService and tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 13:21:24 +02:00

206 lines
9.2 KiB
PHP

<?php
namespace MintyPHP\Tests\Module\Helpdesk\Service;
use MintyPHP\Module\Helpdesk\Repository\HandoverRepository;
use MintyPHP\Module\Helpdesk\Service\BcODataGateway;
use MintyPHP\Module\Helpdesk\Service\DomainDetailService;
use MintyPHP\Module\Helpdesk\Service\EffectiveHelpdeskSettingsService;
use PHPUnit\Framework\TestCase;
class DomainDetailServiceTest extends TestCase
{
private const TENANT_ID = 1;
private function createService(
?BcODataGateway $gateway = null,
?EffectiveHelpdeskSettingsService $settings = null,
?HandoverRepository $repository = null,
): DomainDetailService {
$gateway = $gateway ?? $this->createMock(BcODataGateway::class);
$settings = $settings ?? $this->createConfiguredSettings(true);
$repository = $repository ?? $this->createMock(HandoverRepository::class);
return new DomainDetailService($gateway, $settings, $repository);
}
private function createConfiguredSettings(bool $configured): EffectiveHelpdeskSettingsService
{
$mock = $this->createMock(EffectiveHelpdeskSettingsService::class);
$mock->method('isConfigured')->willReturn($configured);
return $mock;
}
// ── loadDomain tests ─────────────────────────────────────────
public function testLoadDomainHappyPath(): void
{
$gateway = $this->createMock(BcODataGateway::class);
$gateway->method('getDomain')->willReturn([
'No' => 'DNS00001',
'Customer_No' => 'D10001',
'Customer_Name' => 'Acme Corp',
'URL' => 'example.com',
'State' => 'Aktiv',
'Administration' => 'Intern',
]);
$service = $this->createService($gateway);
$result = $service->loadDomain('DNS00001');
$this->assertSame('success', $result['status']);
$this->assertSame('DNS00001', $result['domain']['No']);
$this->assertSame('example.com', $result['domain']['URL']);
}
public function testLoadDomainNotFound(): void
{
$gateway = $this->createMock(BcODataGateway::class);
$gateway->method('getDomain')->willReturn(null);
$service = $this->createService($gateway);
$result = $service->loadDomain('INVALID');
$this->assertSame('not_found', $result['status']);
}
public function testLoadDomainEmptyNo(): void
{
$service = $this->createService();
$result = $service->loadDomain('');
$this->assertSame('not_found', $result['status']);
}
public function testLoadDomainNotConfigured(): void
{
$service = $this->createService(settings: $this->createConfiguredSettings(false));
$result = $service->loadDomain('DNS00001');
$this->assertSame('not_configured', $result['status']);
}
public function testLoadDomainBcError(): void
{
$gateway = $this->createMock(BcODataGateway::class);
$gateway->method('getDomain')->willThrowException(new \RuntimeException('Connection failed'));
$service = $this->createService($gateway);
$result = $service->loadDomain('DNS00001');
$this->assertSame('error', $result['status']);
$this->assertSame('BC connection failed', $result['error']);
}
// ── loadDomainDetails tests ──────────────────────────────────
public function testLoadDomainDetailsHappyPath(): void
{
$gateway = $this->createMock(BcODataGateway::class);
$gateway->method('getCustomer')->willReturn([
'No' => 'D10001',
'Name' => 'Acme Corp',
'Address' => 'Main St 1',
]);
$gateway->method('listDomainContractLines')->willReturn([
['No' => 'DNS00001', 'Header_No' => 'V1000', 'PI_Header_Type' => 'WEBSITE', 'PI_Header_Description' => 'Website Contract', 'PI_Header_State' => 'Aktiv', 'Line_State' => 'Aktiv'],
['No' => 'DNS00002', 'Header_No' => 'V2000', 'PI_Header_Type' => 'SW&H', 'PI_Header_Description' => 'Other', 'PI_Header_State' => 'Aktiv', 'Line_State' => 'Aktiv'],
]);
$gateway->method('getDomainsForCustomer')->willReturn([
['No' => 'DNS00001', 'URL' => 'example.com', 'State' => 'Aktiv'],
['No' => 'DNS00002', 'URL' => 'other.com', 'State' => 'Aktiv'],
]);
$repo = $this->createMock(HandoverRepository::class);
$repo->method('findByDomainNo')->willReturn([
['id' => 1, 'product_code' => 'PROD-A', 'product_name' => 'Product A', 'product_bc_description' => '', 'status' => 'draft', 'created_by_name' => 'John', 'created_at' => '2026-01-01 10:00:00'],
['id' => 2, 'product_code' => 'PROD-A', 'product_name' => 'Product A', 'product_bc_description' => '', 'status' => 'completed', 'created_by_name' => 'Jane', 'created_at' => '2026-02-15 14:00:00'],
]);
$service = $this->createService($gateway, repository: $repo);
$result = $service->loadDomainDetails('DNS00001', 'D10001', self::TENANT_ID);
$this->assertTrue($result['ok']);
$this->assertSame('Acme Corp', $result['customer']['Name']);
$this->assertSame('WEBSITE', $result['contract']['contract_type']);
$this->assertSame('V1000', $result['contract']['contract_no']);
$this->assertCount(2, $result['handovers']);
$this->assertSame(2, $result['handover_stats']['total']);
$this->assertSame(1, $result['handover_stats']['draft']);
$this->assertSame(1, $result['handover_stats']['completed']);
$this->assertCount(1, $result['related_domains']);
$this->assertSame('DNS00002', $result['related_domains'][0]['No']);
}
public function testLoadDomainDetailsNoContract(): void
{
$gateway = $this->createMock(BcODataGateway::class);
$gateway->method('getCustomer')->willReturn(['No' => 'D10001', 'Name' => 'Acme']);
$gateway->method('listDomainContractLines')->willReturn([]);
$gateway->method('getDomainsForCustomer')->willReturn([]);
$repo = $this->createMock(HandoverRepository::class);
$repo->method('findByDomainNo')->willReturn([]);
$service = $this->createService($gateway, repository: $repo);
$result = $service->loadDomainDetails('DNS00001', 'D10001', self::TENANT_ID);
$this->assertTrue($result['ok']);
$this->assertNull($result['contract']);
$this->assertSame(0, $result['handover_stats']['total']);
$this->assertEmpty($result['related_domains']);
}
public function testLoadDomainDetailsEmptyDomainNo(): void
{
$service = $this->createService();
$result = $service->loadDomainDetails('', 'D10001', self::TENANT_ID);
$this->assertFalse($result['ok']);
$this->assertSame('Missing domain number', $result['error']);
}
public function testLoadDomainDetailsCustomerFetchFails(): void
{
$gateway = $this->createMock(BcODataGateway::class);
$gateway->method('getCustomer')->willThrowException(new \RuntimeException('BC error'));
$gateway->method('listDomainContractLines')->willReturn([]);
$gateway->method('getDomainsForCustomer')->willReturn([]);
$repo = $this->createMock(HandoverRepository::class);
$repo->method('findByDomainNo')->willReturn([]);
$service = $this->createService($gateway, repository: $repo);
$result = $service->loadDomainDetails('DNS00001', 'D10001', self::TENANT_ID);
$this->assertTrue($result['ok']);
$this->assertNull($result['customer']);
}
public function testLoadDomainDetailsHandoverStatAggregation(): void
{
$gateway = $this->createMock(BcODataGateway::class);
$gateway->method('getCustomer')->willReturn(null);
$gateway->method('listDomainContractLines')->willReturn([]);
$gateway->method('getDomainsForCustomer')->willReturn([]);
$repo = $this->createMock(HandoverRepository::class);
$repo->method('findByDomainNo')->willReturn([
['id' => 1, 'product_code' => 'P', 'product_name' => '', 'product_bc_description' => '', 'status' => 'draft', 'created_by_name' => '', 'created_at' => ''],
['id' => 2, 'product_code' => 'P', 'product_name' => '', 'product_bc_description' => '', 'status' => 'in_progress', 'created_by_name' => '', 'created_at' => ''],
['id' => 3, 'product_code' => 'P', 'product_name' => '', 'product_bc_description' => '', 'status' => 'in_progress', 'created_by_name' => '', 'created_at' => ''],
['id' => 4, 'product_code' => 'P', 'product_name' => '', 'product_bc_description' => '', 'status' => 'archived', 'created_by_name' => '', 'created_at' => ''],
]);
$service = $this->createService($gateway, repository: $repo);
$result = $service->loadDomainDetails('DNS00001', '', self::TENANT_ID);
$this->assertSame(4, $result['handover_stats']['total']);
$this->assertSame(1, $result['handover_stats']['draft']);
$this->assertSame(2, $result['handover_stats']['in_progress']);
$this->assertSame(0, $result['handover_stats']['completed']);
$this->assertSame(1, $result['handover_stats']['archived']);
}
}