Files
orderPRO/tests/Unit/AllegroShipmentServiceTest.php
Jacek Pyziak 176d740578 feat(50-allegro-shipment-waybill-push): push waybill to allegro checkout form
Phase 50 complete:

- add conditional waybill push for allegro orders only

- add retry on ALLEGRO_HTTP_401 and non-critical failure handling

- add unit tests and update architecture/changelog docs
2026-03-28 15:32:34 +01:00

323 lines
9.8 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Unit;
use App\Modules\Orders\OrdersRepository;
use App\Modules\Settings\AllegroApiClient;
use App\Modules\Settings\AllegroTokenManager;
use App\Modules\Settings\CompanySettingsRepository;
use App\Modules\Shipments\AllegroShipmentService;
use App\Modules\Shipments\ShipmentPackageRepository;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use RuntimeException;
final class AllegroShipmentServiceTest extends TestCase
{
private AllegroTokenManager&MockObject $tokenManager;
private AllegroApiClient&MockObject $apiClient;
private ShipmentPackageRepository&MockObject $packages;
private CompanySettingsRepository&MockObject $companySettings;
private OrdersRepository&MockObject $ordersRepository;
protected function setUp(): void
{
$this->tokenManager = $this->createMock(AllegroTokenManager::class);
$this->apiClient = $this->createMock(AllegroApiClient::class);
$this->packages = $this->createMock(ShipmentPackageRepository::class);
$this->companySettings = $this->createMock(CompanySettingsRepository::class);
$this->ordersRepository = $this->createMock(OrdersRepository::class);
}
public function testCheckCreationStatusPushesWaybillForAllegroOrder(): void
{
$this->tokenManager
->method('resolveToken')
->willReturn(['token-1', 'sandbox']);
$this->packages
->method('findById')
->with(11)
->willReturn([
'id' => 11,
'order_id' => 200,
'command_id' => 'cmd-11',
'carrier_id' => 'INPOST',
]);
$this->packages
->expects($this->once())
->method('update')
->with(
11,
$this->callback(static function (array $payload): bool {
return ($payload['tracking_number'] ?? null) === 'TRK-001'
&& ($payload['carrier_id'] ?? null) === 'INPOST';
})
);
$this->packages
->expects($this->once())
->method('resolveCarrierName')
->with('allegro_wza', 'INPOST')
->willReturn('InPost');
$this->ordersRepository
->method('findDetails')
->with(200)
->willReturn([
'order' => [
'source' => 'allegro',
'source_order_id' => 'CHECKOUT-200',
],
]);
$this->apiClient
->method('getShipmentCreationStatus')
->with('sandbox', 'token-1', 'cmd-11')
->willReturn([
'status' => 'SUCCESS',
'shipmentId' => 'SHIP-11',
]);
$this->apiClient
->method('getShipmentDetails')
->with('sandbox', 'token-1', 'SHIP-11')
->willReturn([
'waybill' => 'TRK-001',
]);
$this->apiClient
->expects($this->once())
->method('addShipmentToOrder')
->with(
'sandbox',
'token-1',
'CHECKOUT-200',
'TRK-001',
'INPOST',
'InPost'
)
->willReturn([]);
$service = $this->createService();
$result = $service->checkCreationStatus(11);
$this->assertSame('created', $result['status']);
$this->assertSame('TRK-001', $result['tracking_number']);
}
public function testCheckCreationStatusSkipsPushForNonAllegroOrder(): void
{
$this->tokenManager
->method('resolveToken')
->willReturn(['token-1', 'sandbox']);
$this->packages
->method('findById')
->with(12)
->willReturn([
'id' => 12,
'order_id' => 201,
'command_id' => 'cmd-12',
'carrier_id' => 'DPD',
]);
$this->packages
->expects($this->once())
->method('update');
$this->ordersRepository
->method('findDetails')
->with(201)
->willReturn([
'order' => [
'source' => 'shoppro',
'source_order_id' => 'SP-ORDER-1',
],
]);
$this->apiClient
->method('getShipmentCreationStatus')
->willReturn([
'status' => 'SUCCESS',
'shipmentId' => 'SHIP-12',
]);
$this->apiClient
->method('getShipmentDetails')
->willReturn([
'waybill' => 'TRK-002',
]);
$this->apiClient
->expects($this->never())
->method('addShipmentToOrder');
$service = $this->createService();
$result = $service->checkCreationStatus(12);
$this->assertSame('created', $result['status']);
$this->assertSame('TRK-002', $result['tracking_number']);
}
public function testCheckCreationStatusDoesNotFailWhenPushReturnsError(): void
{
$this->tokenManager
->method('resolveToken')
->willReturn(['token-1', 'sandbox']);
$this->packages
->method('findById')
->with(13)
->willReturn([
'id' => 13,
'order_id' => 202,
'command_id' => 'cmd-13',
'carrier_id' => 'DHL',
]);
$this->packages
->expects($this->once())
->method('update');
$this->packages
->method('resolveCarrierName')
->willReturn('DHL');
$this->ordersRepository
->method('findDetails')
->with(202)
->willReturn([
'order' => [
'source' => 'allegro',
'source_order_id' => 'CHECKOUT-202',
],
]);
$this->apiClient
->method('getShipmentCreationStatus')
->willReturn([
'status' => 'SUCCESS',
'shipmentId' => 'SHIP-13',
]);
$this->apiClient
->method('getShipmentDetails')
->willReturn([
'waybill' => 'TRK-003',
]);
$this->apiClient
->expects($this->once())
->method('addShipmentToOrder')
->willThrowException(new RuntimeException('API Allegro HTTP 422'));
$service = $this->createService();
$result = $service->checkCreationStatus(13);
$this->assertSame('created', $result['status']);
$this->assertSame('TRK-003', $result['tracking_number']);
}
public function testCheckCreationStatusRetriesPushAfter401(): void
{
$this->tokenManager
->method('resolveToken')
->willReturnOnConsecutiveCalls(
['token-old', 'sandbox'],
['token-new', 'production']
);
$this->packages
->method('findById')
->with(14)
->willReturn([
'id' => 14,
'order_id' => 203,
'command_id' => 'cmd-14',
'carrier_id' => 'INPOST',
]);
$this->packages
->expects($this->once())
->method('update');
$this->packages
->method('resolveCarrierName')
->willReturn('InPost');
$this->ordersRepository
->method('findDetails')
->with(203)
->willReturn([
'order' => [
'source' => 'allegro',
'source_order_id' => 'CHECKOUT-203',
],
]);
$this->apiClient
->method('getShipmentCreationStatus')
->with('sandbox', 'token-old', 'cmd-14')
->willReturn([
'status' => 'SUCCESS',
'shipmentId' => 'SHIP-14',
]);
$this->apiClient
->method('getShipmentDetails')
->with('sandbox', 'token-old', 'SHIP-14')
->willReturn([
'waybill' => 'TRK-004',
]);
$this->apiClient
->expects($this->exactly(2))
->method('addShipmentToOrder')
->willReturnCallback(static function (
string $environment,
string $token,
string $checkoutId,
string $waybill,
string $carrierId,
string $carrierName
): array {
static $calls = 0;
$calls++;
if ($calls === 1) {
TestCase::assertSame('sandbox', $environment);
TestCase::assertSame('token-old', $token);
TestCase::assertSame('CHECKOUT-203', $checkoutId);
TestCase::assertSame('TRK-004', $waybill);
TestCase::assertSame('INPOST', $carrierId);
TestCase::assertSame('InPost', $carrierName);
throw new RuntimeException('ALLEGRO_HTTP_401');
}
TestCase::assertSame('production', $environment);
TestCase::assertSame('token-new', $token);
return [];
});
$service = $this->createService();
$result = $service->checkCreationStatus(14);
$this->assertSame('created', $result['status']);
$this->assertSame('TRK-004', $result['tracking_number']);
}
private function createService(): AllegroShipmentService
{
return new AllegroShipmentService(
$this->tokenManager,
$this->apiClient,
$this->packages,
$this->companySettings,
$this->ordersRepository
);
}
}