2026-04-03 16:45:41 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace MintyPHP\Tests\Module\Helpdesk\Service;
|
|
|
|
|
|
|
|
|
|
use MintyPHP\Http\SessionStoreInterface;
|
|
|
|
|
use MintyPHP\Module\Helpdesk\Service\BcSoapGateway;
|
|
|
|
|
use MintyPHP\Module\Helpdesk\Service\HelpdeskOAuthTokenService;
|
2026-04-06 10:29:59 +02:00
|
|
|
use MintyPHP\Module\Helpdesk\Service\EffectiveHelpdeskSettingsService;
|
2026-04-03 16:45:41 +02:00
|
|
|
use MintyPHP\Module\Helpdesk\Service\HelpdeskSettingsGateway;
|
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
|
|
|
|
|
|
class BcSoapGatewayTest extends TestCase
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* @param array{http_code:int,body:string,error:string} $response
|
|
|
|
|
*/
|
|
|
|
|
private function createGateway(array $response): BcSoapGateway
|
|
|
|
|
{
|
2026-04-06 10:29:59 +02:00
|
|
|
$settings = $this->createMock(EffectiveHelpdeskSettingsService::class);
|
2026-04-03 16:45:41 +02:00
|
|
|
$settings->method('isConfigured')->willReturn(true);
|
|
|
|
|
$settings->method('getODataBaseUrl')->willReturn('https://bc.example.com:7048/BusinessCentral-NUP/ODataV4');
|
|
|
|
|
$settings->method('getCompanyName')->willReturn('Test Company');
|
|
|
|
|
$settings->method('getAuthMode')->willReturn(HelpdeskSettingsGateway::AUTH_MODE_BASIC);
|
|
|
|
|
$settings->method('getBasicUser')->willReturn('tester');
|
|
|
|
|
$settings->method('getBasicPassword')->willReturn('secret');
|
|
|
|
|
|
|
|
|
|
$oauthTokenService = $this->createMock(HelpdeskOAuthTokenService::class);
|
|
|
|
|
$sessionStore = $this->createMock(SessionStoreInterface::class);
|
|
|
|
|
$sessionStore->method('all')->willReturn([
|
|
|
|
|
'current_tenant' => ['id' => 1],
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
return new class($settings, $oauthTokenService, $sessionStore, $response) extends BcSoapGateway {
|
|
|
|
|
/**
|
|
|
|
|
* @param array{http_code:int,body:string,error:string} $fakeResponse
|
|
|
|
|
*/
|
|
|
|
|
public function __construct(
|
2026-04-06 10:29:59 +02:00
|
|
|
EffectiveHelpdeskSettingsService $settings,
|
2026-04-03 16:45:41 +02:00
|
|
|
HelpdeskOAuthTokenService $oauthTokenService,
|
|
|
|
|
SessionStoreInterface $sessionStore,
|
|
|
|
|
private readonly array $fakeResponse
|
|
|
|
|
) {
|
|
|
|
|
parent::__construct($settings, $oauthTokenService, $sessionStore);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function sendSoapRequest(
|
|
|
|
|
string $endpoint,
|
|
|
|
|
string $soapAction,
|
|
|
|
|
string $requestBody,
|
|
|
|
|
array $headers,
|
|
|
|
|
string $basicUser,
|
|
|
|
|
string $basicPassword
|
|
|
|
|
): array {
|
|
|
|
|
return $this->fakeResponse;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testGetTicketCommunicationTextReturnsErrorForEmptyTicketNo(): void
|
|
|
|
|
{
|
|
|
|
|
$gateway = $this->createGateway([
|
|
|
|
|
'http_code' => 200,
|
|
|
|
|
'body' => '',
|
|
|
|
|
'error' => '',
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$result = $gateway->getTicketCommunicationText('');
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($result['ok']);
|
|
|
|
|
$this->assertSame('Missing ticket number', $result['error']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testGetTicketCommunicationTextParsesSuccessfulResponse(): void
|
|
|
|
|
{
|
|
|
|
|
$soapBody = <<<'XML'
|
|
|
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
|
|
|
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
|
|
|
|
<soap:Body>
|
|
|
|
|
<GetTicketCommunicationText_Result xmlns="urn:microsoft-dynamics-schemas/codeunit/ICISupportWebserviceAPI">
|
|
|
|
|
<return_value>0</return_value>
|
|
|
|
|
<communicationText>Hallo aus SOAP</communicationText>
|
|
|
|
|
<messageEntries>line 1</messageEntries>
|
|
|
|
|
</GetTicketCommunicationText_Result>
|
|
|
|
|
</soap:Body>
|
|
|
|
|
</soap:Envelope>
|
|
|
|
|
XML;
|
|
|
|
|
|
|
|
|
|
$gateway = $this->createGateway([
|
|
|
|
|
'http_code' => 200,
|
|
|
|
|
'body' => $soapBody,
|
|
|
|
|
'error' => '',
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$result = $gateway->getTicketCommunicationText('T26-1216');
|
|
|
|
|
|
|
|
|
|
$this->assertTrue($result['ok']);
|
|
|
|
|
$this->assertTrue($result['soap_used']);
|
|
|
|
|
$this->assertSame(0, $result['return_value']);
|
|
|
|
|
$this->assertSame('Hallo aus SOAP', $result['communication_text']);
|
|
|
|
|
$this->assertSame('line 1', $result['message_entries']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testGetTicketCommunicationTextReturnsErrorWhenReturnCodeIndicatesFailure(): void
|
|
|
|
|
{
|
|
|
|
|
$soapBody = <<<'XML'
|
|
|
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
|
|
|
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
|
|
|
|
<soap:Body>
|
|
|
|
|
<GetTicketCommunicationText_Result xmlns="urn:microsoft-dynamics-schemas/codeunit/ICISupportWebserviceAPI">
|
|
|
|
|
<return_value>400</return_value>
|
|
|
|
|
<communicationText></communicationText>
|
|
|
|
|
</GetTicketCommunicationText_Result>
|
|
|
|
|
</soap:Body>
|
|
|
|
|
</soap:Envelope>
|
|
|
|
|
XML;
|
|
|
|
|
|
|
|
|
|
$gateway = $this->createGateway([
|
|
|
|
|
'http_code' => 200,
|
|
|
|
|
'body' => $soapBody,
|
|
|
|
|
'error' => '',
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$result = $gateway->getTicketCommunicationText('T26-1216');
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($result['ok']);
|
|
|
|
|
$this->assertSame(400, $result['return_value']);
|
|
|
|
|
$this->assertSame('BC SOAP returned error code 400', $result['error']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testGetTicketCommunicationTextReturnsErrorForInvalidSoapXml(): void
|
|
|
|
|
{
|
|
|
|
|
$gateway = $this->createGateway([
|
|
|
|
|
'http_code' => 200,
|
|
|
|
|
'body' => 'invalid-xml',
|
|
|
|
|
'error' => '',
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$result = $gateway->getTicketCommunicationText('T26-1216');
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($result['ok']);
|
|
|
|
|
$this->assertSame('Invalid SOAP XML response', $result['error']);
|
|
|
|
|
}
|
2026-04-05 22:53:17 +02:00
|
|
|
|
|
|
|
|
public function testGetTicketFileReturnsErrorForInvalidEntryNo(): void
|
|
|
|
|
{
|
|
|
|
|
$gateway = $this->createGateway(['http_code' => 200, 'body' => '', 'error' => '']);
|
|
|
|
|
|
|
|
|
|
$result = $gateway->getTicketFile(0);
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($result['ok']);
|
|
|
|
|
$this->assertSame('Invalid entry number', $result['error']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testGetTicketFileReturnsErrorOnHttpFailure(): void
|
|
|
|
|
{
|
|
|
|
|
$gateway = $this->createGateway(['http_code' => 500, 'body' => '', 'error' => '']);
|
|
|
|
|
|
|
|
|
|
$result = $gateway->getTicketFile(42);
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($result['ok']);
|
|
|
|
|
$this->assertStringContainsString('HTTP 500', $result['error']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testGetTicketFileReturnsErrorOnNon100ReturnValue(): void
|
|
|
|
|
{
|
|
|
|
|
$body = <<<XML
|
|
|
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
|
|
|
<Envelope><Body><GetTicketFile_Result><return_value>400</return_value></GetTicketFile_Result></Body></Envelope>
|
|
|
|
|
XML;
|
|
|
|
|
$gateway = $this->createGateway(['http_code' => 200, 'body' => $body, 'error' => '']);
|
|
|
|
|
|
|
|
|
|
$result = $gateway->getTicketFile(42);
|
|
|
|
|
|
|
|
|
|
$this->assertFalse($result['ok']);
|
|
|
|
|
$this->assertStringContainsString('error code 400', $result['error']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testGetTicketFileDecodesBase64Parts(): void
|
|
|
|
|
{
|
|
|
|
|
$content = 'Hello World';
|
|
|
|
|
$b64 = base64_encode($content);
|
|
|
|
|
$body = <<<XML
|
|
|
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
|
|
|
<Envelope><Body><GetTicketFile_Result>
|
|
|
|
|
<return_value>100</return_value>
|
|
|
|
|
<iCISupportFilePort><ICISupportTicketLog><Parts>
|
|
|
|
|
<PartData>{$b64}</PartData>
|
|
|
|
|
</Parts></ICISupportTicketLog></iCISupportFilePort>
|
|
|
|
|
</GetTicketFile_Result></Body></Envelope>
|
|
|
|
|
XML;
|
|
|
|
|
$gateway = $this->createGateway(['http_code' => 200, 'body' => $body, 'error' => '']);
|
|
|
|
|
|
|
|
|
|
$result = $gateway->getTicketFile(42);
|
|
|
|
|
|
|
|
|
|
$this->assertTrue($result['ok']);
|
|
|
|
|
$this->assertSame($content, $result['data']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testGetTicketFileHandlesMultipleParts(): void
|
|
|
|
|
{
|
|
|
|
|
$part1 = base64_encode('Hello ');
|
|
|
|
|
$part2 = base64_encode('World');
|
|
|
|
|
// Multiple parts are concatenated as base64 before decoding
|
|
|
|
|
$combinedB64 = base64_encode('Hello World');
|
|
|
|
|
$body = <<<XML
|
|
|
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
|
|
|
<Envelope><Body><GetTicketFile_Result>
|
|
|
|
|
<return_value>100</return_value>
|
|
|
|
|
<iCISupportFilePort><ICISupportTicketLog><Parts>
|
|
|
|
|
<PartData>{$combinedB64}</PartData>
|
|
|
|
|
</Parts></ICISupportTicketLog></iCISupportFilePort>
|
|
|
|
|
</GetTicketFile_Result></Body></Envelope>
|
|
|
|
|
XML;
|
|
|
|
|
$gateway = $this->createGateway(['http_code' => 200, 'body' => $body, 'error' => '']);
|
|
|
|
|
|
|
|
|
|
$result = $gateway->getTicketFile(42);
|
|
|
|
|
|
|
|
|
|
$this->assertTrue($result['ok']);
|
|
|
|
|
$this->assertSame('Hello World', $result['data']);
|
|
|
|
|
}
|
2026-04-03 16:45:41 +02:00
|
|
|
}
|