Phase 104 complete: - Backend: ApaczkaShipmentService::buildOptionsPayload() mapuje weekend_delivery -> option[19] = 1 w payloadzie API Apaczka v2 - Stala OPTION_KEYS jako rozszerzalne mapowanie pole formularza -> id opcji Apaczki - Frontend: checkbox "Dostawa w weekend (sobota)" w prepare.php widoczny tylko dla supplier=INPOST + paczkomat (door_to_point=1 lub point_to_point=1) - JS toggle oparty na atrybutach data-supplier/data-paczkomat z resetem stanu - 3 nowe testy jednostkowe pokrywajace mapowanie buildOptionsPayload (phpunit OK 11/11) - Hotfix integracyjny po UAT: ShipmentController::create() nie przekazywal pola weekend_delivery z requestu do formData providera (root cause: reczna lista pol w controllerze) - Dokumentacja zaktualizowana (DOCS/ARCHITECTURE.md, DOCS/TECH_CHANGELOG.md) DEFER-104-01: rozwazyc test integracyjny pelnego flow controller -> service lub refactor na request->all(). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
140 lines
4.4 KiB
PHP
140 lines
4.4 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit;
|
|
|
|
use App\Core\Exceptions\ShipmentException;
|
|
use App\Modules\Orders\OrdersRepository;
|
|
use App\Modules\Settings\ApaczkaApiClient;
|
|
use App\Modules\Settings\ApaczkaIntegrationRepository;
|
|
use App\Modules\Settings\CompanySettingsRepository;
|
|
use App\Modules\Shipments\ApaczkaShipmentService;
|
|
use App\Modules\Shipments\ShipmentPackageRepository;
|
|
use PHPUnit\Framework\TestCase;
|
|
use ReflectionMethod;
|
|
|
|
final class ApaczkaShipmentServiceTest extends TestCase
|
|
{
|
|
private ApaczkaShipmentService $service;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->service = new ApaczkaShipmentService(
|
|
$this->createMock(ApaczkaIntegrationRepository::class),
|
|
$this->createMock(ApaczkaApiClient::class),
|
|
$this->createMock(ShipmentPackageRepository::class),
|
|
$this->createMock(CompanySettingsRepository::class),
|
|
$this->createMock(OrdersRepository::class)
|
|
);
|
|
}
|
|
|
|
private function invokeTruncate(string $street): string
|
|
{
|
|
$method = new ReflectionMethod(ApaczkaShipmentService::class, 'truncateStreetForPoint');
|
|
$method->setAccessible(true);
|
|
|
|
return (string) $method->invoke($this->service, $street);
|
|
}
|
|
|
|
private function invokeAssert(string $street): void
|
|
{
|
|
$method = new ReflectionMethod(ApaczkaShipmentService::class, 'assertStreetWithinCourierLimit');
|
|
$method->setAccessible(true);
|
|
$method->invoke($this->service, $street);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $formData
|
|
* @return array<int, int>
|
|
*/
|
|
private function invokeBuildOptions(array $formData): array
|
|
{
|
|
$method = new ReflectionMethod(ApaczkaShipmentService::class, 'buildOptionsPayload');
|
|
$method->setAccessible(true);
|
|
/** @var array<int, int> $result */
|
|
$result = $method->invoke($this->service, $formData);
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function testTruncateStreetForPointShortensLongValue(): void
|
|
{
|
|
$input = 'Punkt odbioru POP-XYZ123 przy al. Jerozolimskich 55A/12';
|
|
$result = $this->invokeTruncate($input);
|
|
|
|
$this->assertLessThanOrEqual(30, mb_strlen($result, 'UTF-8'));
|
|
$this->assertStringStartsWith('Punkt odbioru', $result);
|
|
}
|
|
|
|
public function testTruncateStreetForPointPreservesShortValue(): void
|
|
{
|
|
$this->assertSame('Polna 5', $this->invokeTruncate('Polna 5'));
|
|
}
|
|
|
|
public function testTruncateStreetForPointBoundary30(): void
|
|
{
|
|
$input = str_repeat('A', 30);
|
|
|
|
$result = $this->invokeTruncate($input);
|
|
|
|
$this->assertSame(30, mb_strlen($result, 'UTF-8'));
|
|
$this->assertSame($input, $result);
|
|
}
|
|
|
|
public function testTruncateStreetForPointUtf8Safe(): void
|
|
{
|
|
$input = 'Ulica Żółtych Słoneczników Małych 12345';
|
|
$this->assertGreaterThan(30, mb_strlen($input, 'UTF-8'));
|
|
|
|
$result = $this->invokeTruncate($input);
|
|
|
|
$this->assertSame(30, mb_strlen($result, 'UTF-8'));
|
|
$this->assertTrue(mb_check_encoding($result, 'UTF-8'));
|
|
}
|
|
|
|
public function testTruncateStreetForPointRtrimTrailingSpace(): void
|
|
{
|
|
$input = str_repeat('A', 29) . ' XYZ';
|
|
|
|
$result = $this->invokeTruncate($input);
|
|
|
|
$this->assertSame(29, mb_strlen($result, 'UTF-8'));
|
|
$this->assertSame(str_repeat('A', 29), $result);
|
|
}
|
|
|
|
public function testAssertStreetWithinCourierLimitAcceptsShort(): void
|
|
{
|
|
$this->invokeAssert('Polna 5');
|
|
$this->addToAssertionCount(1);
|
|
}
|
|
|
|
public function testAssertStreetWithinCourierLimitAcceptsBoundary30(): void
|
|
{
|
|
$this->invokeAssert(str_repeat('A', 30));
|
|
$this->addToAssertionCount(1);
|
|
}
|
|
|
|
public function testAssertStreetWithinCourierLimitRejectsLong(): void
|
|
{
|
|
$this->expectException(ShipmentException::class);
|
|
$this->expectExceptionMessageMatches('/przekracza 30 znakow/');
|
|
|
|
$this->invokeAssert('Ul. Generała Pilota Józefa Kowalskiego 6/1');
|
|
}
|
|
|
|
public function testBuildOptionsPayloadWeekendEnabled(): void
|
|
{
|
|
$this->assertSame([19 => 1], $this->invokeBuildOptions(['weekend_delivery' => '1']));
|
|
}
|
|
|
|
public function testBuildOptionsPayloadWeekendDisabled(): void
|
|
{
|
|
$this->assertSame([], $this->invokeBuildOptions(['weekend_delivery' => '0']));
|
|
}
|
|
|
|
public function testBuildOptionsPayloadEmptyForm(): void
|
|
{
|
|
$this->assertSame([], $this->invokeBuildOptions([]));
|
|
}
|
|
}
|