PluginProbe
Packeta / trunk
Packeta vtrunk
2.3.2 2.3.1 trunk 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3.0 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 All 56 releases
packeta / tests / Module / Labels / CarrierLabelServiceTest.php

CarrierLabelServiceTest.php in Packeta trunk, at tests/Module/Labels/CarrierLabelServiceTest.php

507 lines 14.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Tests\Packetery\Module\Labels;
6
7 use Packetery\Core\Api\Soap\Client;
8 use Packetery\Core\Api\Soap\Request;
9 use Packetery\Core\Api\Soap\Response;
10 use Packetery\Core\Log;
11 use Packetery\Core\Log\ILogger;
12 use Packetery\Module\Framework\WpAdapter;
13 use Packetery\Module\Labels\CarrierLabelService;
14 use Packetery\Module\MessageManager;
15 use Packetery\Module\Order\Repository;
16 use PHPUnit\Framework\Attributes\DataProvider;
17 use PHPUnit\Framework\MockObject\MockObject;
18 use PHPUnit\Framework\TestCase;
19 use ReflectionMethod;
20
21 class CarrierLabelServiceTest extends TestCase {
22
23 private Client|MockObject $soapApiClient;
24 private MessageManager|MockObject $messageManager;
25 private ILogger|MockObject $logger;
26 private Repository|MockObject $orderRepository;
27 private CarrierLabelService $carrierLabelService;
28
29 private function createCarrierLabelService(): void {
30 $this->soapApiClient = $this->createMock( Client::class );
31 $this->messageManager = $this->createMock( MessageManager::class );
32 $this->logger = $this->createMock( ILogger::class );
33 $this->orderRepository = $this->createMock( Repository::class );
34 $wpAdapterMock = $this->createMock( WpAdapter::class );
35
36 $wpAdapterMock->method( '__' )
37 ->willReturnCallback(
38 static fn( string $text ): string => $text
39 );
40
41 $this->carrierLabelService = new CarrierLabelService(
42 $this->soapApiClient,
43 $this->messageManager,
44 $this->logger,
45 $this->orderRepository,
46 $wpAdapterMock
47 );
48 }
49
50 /**
51 * @return array<string, array{
52 * packetIds: array<string, string>,
53 * existingOrders: array<string, array<string, string>>,
54 * apiResponses: array<array<string, mixed>>,
55 * expectedResult: array<string, array{packetId: string, courierNumber: string}>
56 * }>
57 */
58 public static function provideDataForGetPacketIdsWithCourierNumbers(): array {
59 $carrierNumberOnSuccess = 'CN123456';
60 $successResponse = [
61 'class' => Response\PacketCourierNumber::class,
62 'hasFault' => false,
63 'hasWrongPassword' => false,
64 'getNumber' => $carrierNumberOnSuccess,
65 ];
66
67 $wrongPasswordResponse = [
68 'class' => Response\PacketCourierNumber::class,
69 'hasFault' => true,
70 'hasWrongPassword' => true,
71 'getFaultString' => 'Wrong password',
72 ];
73
74 $generalErrorResponse = [
75 'class' => Response\PacketCourierNumber::class,
76 'hasFault' => true,
77 'hasWrongPassword' => false,
78 'getFaultString' => 'General error',
79 ];
80
81 return [
82 'existing_carrier_numbers' => [
83 'packetIds' => [
84 '1' => 'P123',
85 '2' => 'P456',
86 ],
87 'existingOrders' => [
88 '1' => [ 'carrierNumber' => 'CN123' ],
89 '2' => [ 'carrierNumber' => 'CN456' ],
90 ],
91 'apiResponseConfigs' => [],
92 'expectedResult' => [
93 '1' => [
94 'packetId' => 'P123',
95 'courierNumber' => 'CN123',
96 ],
97 '2' => [
98 'packetId' => 'P456',
99 'courierNumber' => 'CN456',
100 ],
101 ],
102 ],
103 'api_success' => [
104 'packetIds' => [ '1' => 'P123' ],
105 'existingOrders' => [],
106 'apiResponseConfigs' => [ $successResponse ],
107 'expectedResult' => [
108 '1' => [
109 'packetId' => 'P123',
110 'courierNumber' => $carrierNumberOnSuccess,
111 ],
112 ],
113 ],
114 'wrong_password_error' => [
115 'packetIds' => [ '1' => 'P123' ],
116 'existingOrders' => [],
117 'apiResponseConfigs' => [ $wrongPasswordResponse ],
118 'expectedResult' => [],
119 ],
120 'general_error' => [
121 'packetIds' => [
122 '1' => 'P123',
123 '2' => 'P456',
124 ],
125 'existingOrders' => [],
126 'apiResponseConfigs' => [ $generalErrorResponse, $successResponse ],
127 'expectedResult' => [
128 '2' => [
129 'packetId' => 'P456',
130 'courierNumber' => $carrierNumberOnSuccess,
131 ],
132 ],
133 ],
134 'mixed_scenario' => [
135 'packetIds' => [
136 '1' => 'P123',
137 '2' => 'P456',
138 '3' => 'P789',
139 ],
140 'existingOrders' => [
141 '1' => [ 'carrierNumber' => 'CN123' ],
142 ],
143 'apiResponseConfigs' => [ $generalErrorResponse, $successResponse ],
144 'expectedResult' => [
145 '1' => [
146 'packetId' => 'P123',
147 'courierNumber' => 'CN123',
148 ],
149 '3' => [
150 'packetId' => 'P789',
151 'courierNumber' => $carrierNumberOnSuccess,
152 ],
153 ],
154 ],
155 ];
156 }
157
158 #[DataProvider( 'provideDataForGetPacketIdsWithCourierNumbers' )]
159 public function testGetPacketIdsWithCourierNumbers(
160 array $packetIds,
161 array $existingOrders,
162 array $apiResponseConfigs,
163 array $expectedResult
164 ): void {
165 $this->createCarrierLabelService();
166
167 $orderRepositoryMap = [];
168 foreach ( $existingOrders as $orderId => $orderData ) {
169 $order = $this->createMock( \Packetery\Core\Entity\Order::class );
170 $order->method( 'getCarrierNumber' )->willReturn( $orderData['carrierNumber'] ?? null );
171 $orderRepositoryMap[] = [ (int) $orderId, $order ];
172 }
173
174 if ( ! empty( $orderRepositoryMap ) ) {
175 $this->orderRepository->method( 'getByIdWithValidCarrier' )
176 ->willReturnMap( $orderRepositoryMap );
177 }
178
179 $apiResponses = [];
180 foreach ( $apiResponseConfigs as $config ) {
181 $response = $this->createMock( $config['class'] );
182 foreach ( $config as $method => $returnValue ) {
183 if ( $method !== 'class' ) {
184 $response->method( $method )->willReturn( $returnValue );
185 }
186 }
187 $apiResponses[] = $response;
188 }
189
190 $packetIdToResponseMap = [];
191 $apiCallIndex = 0;
192 foreach ( $packetIds as $orderId => $packetId ) {
193 if ( isset( $existingOrders[ $orderId ]['carrierNumber'] ) ) {
194 continue;
195 }
196
197 if ( isset( $apiResponses[ $apiCallIndex ] ) ) {
198 $response = $apiResponses[ $apiCallIndex ];
199
200 if ( $response->hasWrongPassword() ) {
201 $this->messageManager->expects( $this->once() )
202 ->method( 'flash_message' )
203 ->with( $this->isType( 'string' ), MessageManager::TYPE_ERROR );
204 }
205
206 $packetIdToResponseMap[ $packetId ] = $response;
207 $apiCallIndex++;
208 }
209 }
210
211 $this->soapApiClient->method( 'packetCourierNumber' )
212 ->willReturnCallback(
213 function ( Request\PacketCourierNumber $request ) use ( $packetIdToResponseMap ) {
214 $packetId = $request->getPacketId();
215 if ( isset( $packetIdToResponseMap[ $packetId ] ) ) {
216 return $packetIdToResponseMap[ $packetId ];
217 }
218 $this->fail( "Unexpected packet ID: $packetId" );
219 }
220 );
221
222 if ( ! empty( $apiResponses ) ) {
223 $wcOrder = $this->createMock( \WC_Order::class );
224 $wcOrder->method( 'add_order_note' )->willReturn( true );
225 $wcOrder->method( 'save' )->willReturn( true );
226 $this->orderRepository->method( 'getWcOrderById' )->willReturn( $wcOrder );
227
228 $order = $this->createMock( \Packetery\Core\Entity\Order::class );
229 $this->orderRepository->method( 'getByWcOrderWithValidCarrier' )->willReturn( $order );
230 }
231
232 $result = $this->carrierLabelService->getPacketIdsWithCourierNumbers( $packetIds );
233 $this->assertEquals( $expectedResult, $result );
234 }
235
236 /**
237 * @return array<string, array{
238 * hasOrder: bool,
239 * carrierNumber: ?string,
240 * expectedResult: ?array{packetId: string, courierNumber: string}
241 * }>
242 */
243 public static function provideDataForGetExistingCarrierNumber(): array {
244 return [
245 'order_with_carrier_number' => [
246 'hasOrder' => true,
247 'carrierNumber' => 'CN123',
248 'expectedResult' => [
249 'packetId' => 'P123',
250 'courierNumber' => 'CN123',
251 ],
252 ],
253 'order_without_carrier_number' => [
254 'hasOrder' => true,
255 'carrierNumber' => null,
256 'expectedResult' => null,
257 ],
258 'no_order' => [
259 'hasOrder' => false,
260 'carrierNumber' => null,
261 'expectedResult' => null,
262 ],
263 ];
264 }
265
266 #[DataProvider( 'provideDataForGetExistingCarrierNumber' )]
267 public function testGetExistingCarrierNumber(
268 bool $hasOrder,
269 ?string $carrierNumber,
270 ?array $expectedResult
271 ): void {
272 $this->createCarrierLabelService();
273
274 $order = null;
275 if ( $hasOrder ) {
276 $order = $this->createMock( \Packetery\Core\Entity\Order::class );
277 $order->method( 'getCarrierNumber' )
278 ->willReturn( $carrierNumber );
279 }
280
281 $this->orderRepository->method( 'getByIdWithValidCarrier' )
282 ->willReturn( $order );
283
284 $method = new ReflectionMethod( CarrierLabelService::class, 'getExistingCarrierNumber' );
285 $method->setAccessible( true );
286
287 $result = $method->invoke( $this->carrierLabelService, 123, 'P123' );
288 $this->assertEquals( $expectedResult, $result );
289 }
290
291 /**
292 * @return array<string, array{
293 * hasWrongPassword: bool,
294 * faultString: string,
295 * hasWcOrder: bool,
296 * hasOrder: bool,
297 * expectedResult: bool
298 * }>
299 */
300 public static function provideDataForHandleApiError(): array {
301 return [
302 'wrong_password' => [
303 'hasWrongPassword' => true,
304 'faultString' => 'Wrong password',
305 'hasWcOrder' => false,
306 'hasOrder' => false,
307 'expectedResult' => false,
308 ],
309 'general_error_with_order' => [
310 'hasWrongPassword' => false,
311 'faultString' => 'General error',
312 'hasWcOrder' => true,
313 'hasOrder' => true,
314 'expectedResult' => true,
315 ],
316 'general_error_without_order' => [
317 'hasWrongPassword' => false,
318 'faultString' => 'General error',
319 'hasWcOrder' => false,
320 'hasOrder' => false,
321 'expectedResult' => true,
322 ],
323 ];
324 }
325
326 #[DataProvider( 'provideDataForHandleApiError' )]
327 public function testHandleApiError(
328 bool $hasWrongPassword,
329 string $faultString,
330 bool $hasWcOrder,
331 bool $hasOrder,
332 bool $expectedResult
333 ): void {
334 $this->createCarrierLabelService();
335
336 $request = $this->createMock( Request\PacketCourierNumber::class );
337 $response = $this->createMock( Response\PacketCourierNumber::class );
338
339 $response->method( 'hasWrongPassword' )->willReturn( $hasWrongPassword );
340 $response->method( 'getFaultString' )->willReturn( $faultString );
341
342 $wcOrder = null;
343 if ( $hasWcOrder ) {
344 $wcOrder = $this->createMock( \WC_Order::class );
345 $wcOrder->method( 'add_order_note' )->willReturn( true );
346 $wcOrder->method( 'save' )->willReturn( true );
347 }
348
349 $order = null;
350 if ( $hasOrder ) {
351 $order = $this->createMock( \Packetery\Core\Entity\Order::class );
352 $order->expects( $this->once() )->method( 'updateApiErrorMessage' );
353 }
354
355 $this->orderRepository->method( 'getWcOrderById' )->willReturn( $wcOrder );
356 $this->orderRepository->method( 'getByWcOrderWithValidCarrier' )->willReturn( $order );
357
358 if ( $hasWrongPassword ) {
359 $this->messageManager->expects( $this->once() )
360 ->method( 'flash_message' )
361 ->with( $this->isType( 'string' ), MessageManager::TYPE_ERROR );
362 } else {
363 $this->messageManager->expects( $this->never() )
364 ->method( 'flash_message' );
365 }
366
367 $method = new ReflectionMethod( CarrierLabelService::class, 'handleApiError' );
368 $method->setAccessible( true );
369
370 $result = $method->invoke( $this->carrierLabelService, $request, $response, 123, 'P123' );
371 $this->assertEquals( $expectedResult, $result );
372 }
373
374 /**
375 * @return array<string, array{
376 * packetId: string,
377 * faultString: string,
378 * orderId: int
379 * }>
380 */
381 public static function provideDataForLogError(): array {
382 return [
383 'basic_error' => [
384 'packetId' => 'P123',
385 'faultString' => 'Error message',
386 'orderId' => 123,
387 ],
388 'different_error' => [
389 'packetId' => 'P456',
390 'faultString' => 'Another error',
391 'orderId' => 456,
392 ],
393 ];
394 }
395
396 #[DataProvider( 'provideDataForLogError' )]
397 public function testLogError(
398 string $packetId,
399 string $faultString,
400 int $orderId
401 ): void {
402 $this->createCarrierLabelService();
403
404 $request = $this->createMock( Request\PacketCourierNumber::class );
405 $response = $this->createMock( Response\PacketCourierNumber::class );
406
407 $request->method( 'getPacketId' )->willReturn( $packetId );
408 $response->method( 'getFaultString' )->willReturn( $faultString );
409
410 $this->logger->expects( $this->once() )
411 ->method( 'add' )
412 ->with(
413 $this->callback(
414 fn( $record ) => $record instanceof Log\Record
415 && $record->action === Log\Record::ACTION_CARRIER_NUMBER_RETRIEVING
416 && $record->status === Log\Record::STATUS_ERROR
417 && $record->params['packetId'] === $packetId
418 && $record->params['errorMessage'] === $faultString
419 && $record->orderId === $orderId
420 )
421 );
422
423 $method = new ReflectionMethod( CarrierLabelService::class, 'logError' );
424 $method->setAccessible( true );
425
426 $method->invoke( $this->carrierLabelService, $request, $response, $orderId );
427 }
428
429 /**
430 * @return array<string, array{
431 * responseNumber: string,
432 * packetId: string,
433 * hasWcOrder: bool,
434 * hasOrder: bool,
435 * expectedResult: array{packetId: string, courierNumber: string}
436 * }>
437 */
438 public static function provideDataForHandleApiSuccess(): array {
439 return [
440 'with_order' => [
441 'responseNumber' => 'CN123',
442 'packetId' => 'P123',
443 'hasWcOrder' => true,
444 'hasOrder' => true,
445 'expectedResult' => [
446 'packetId' => 'P123',
447 'courierNumber' => 'CN123',
448 ],
449 ],
450 'without_order' => [
451 'responseNumber' => 'CN456',
452 'packetId' => 'P456',
453 'hasWcOrder' => false,
454 'hasOrder' => false,
455 'expectedResult' => [
456 'packetId' => 'P456',
457 'courierNumber' => 'CN456',
458 ],
459 ],
460 ];
461 }
462
463 #[DataProvider( 'provideDataForHandleApiSuccess' )]
464 public function testHandleApiSuccess(
465 string $responseNumber,
466 string $packetId,
467 bool $hasWcOrder,
468 bool $hasOrder,
469 array $expectedResult
470 ): void {
471 $this->createCarrierLabelService();
472
473 $response = $this->createMock( Response\PacketCourierNumber::class );
474
475 $wcOrder = null;
476 if ( $hasWcOrder ) {
477 $wcOrder = $this->createMock( \WC_Order::class );
478 $wcOrder->expects( $this->once() )
479 ->method( 'add_order_note' );
480 $wcOrder->expects( $this->once() )
481 ->method( 'save' );
482 }
483
484 $order = null;
485 if ( $hasOrder ) {
486 $order = $this->createMock( \Packetery\Core\Entity\Order::class );
487 $order->expects( $this->once() )
488 ->method( 'setCarrierNumber' )
489 ->with( $responseNumber );
490
491 $this->orderRepository->expects( $this->once() )
492 ->method( 'save' )
493 ->with( $order );
494 }
495
496 $response->method( 'getNumber' )->willReturn( $responseNumber );
497 $this->orderRepository->method( 'getWcOrderById' )->willReturn( $wcOrder );
498 $this->orderRepository->method( 'getByWcOrderWithValidCarrier' )->willReturn( $order );
499
500 $method = new ReflectionMethod( CarrierLabelService::class, 'handleApiSuccess' );
501 $method->setAccessible( true );
502
503 $result = $method->invoke( $this->carrierLabelService, $response, 123, $packetId );
504 $this->assertEquals( $expectedResult, $result );
505 }
506 }
507