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']); } }