Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
CarrierTest.php
Go to the documentation of this file.
1 <?php
7 
8 use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
12 use Magento\Directory\Model\CountryFactory;
13 use Magento\Directory\Model\CurrencyFactory;
24 use Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory as RateErrorFactory;
26 use Magento\Quote\Model\Quote\Address\RateResult\MethodFactory;
27 use Magento\Shipping\Model\Rate\Result as RateResult;
28 use Magento\Shipping\Model\Rate\ResultFactory as RateResultFactory;
29 use Magento\Shipping\Model\Simplexml\ElementFactory;
32 use Magento\Shipping\Model\Tracking\Result\ErrorFactory;
34 use Magento\Shipping\Model\Tracking\Result\StatusFactory;
35 use Magento\Shipping\Model\Tracking\ResultFactory;
38 use PHPUnit_Framework_MockObject_MockObject as MockObject;
39 use Psr\Log\LoggerInterface;
40 
46 class CarrierTest extends \PHPUnit\Framework\TestCase
47 {
51  private $helper;
52 
56  private $carrier;
57 
61  private $scope;
62 
66  private $error;
67 
71  private $errorFactory;
72 
76  private $trackErrorFactory;
77 
81  private $statusFactory;
82 
86  private $result;
87 
91  private $soapClient;
92 
96  private $serializer;
97 
101  private $logger;
102 
103  protected function setUp()
104  {
105  $this->helper = new ObjectManager($this);
106  $this->scope = $this->getMockBuilder(ScopeConfigInterface::class)
107  ->disableOriginalConstructor()
108  ->getMock();
109 
110  $this->scope->expects($this->any())
111  ->method('getValue')
112  ->willReturnCallback([$this, 'scopeConfigGetValue']);
113 
114  $countryFactory = $this->getCountryFactory();
115  $rateFactory = $this->getRateFactory();
116  $storeManager = $this->getStoreManager();
117  $resultFactory = $this->getResultFactory();
118  $this->initRateErrorFactory();
119 
120  $rateMethodFactory = $this->getRateMethodFactory();
121 
122  $this->trackErrorFactory = $this->getMockBuilder(ErrorFactory::class)
123  ->disableOriginalConstructor()
124  ->setMethods(['create'])
125  ->getMock();
126 
127  $this->statusFactory = $this->getMockBuilder(StatusFactory::class)
128  ->disableOriginalConstructor()
129  ->setMethods(['create'])
130  ->getMock();
131 
132  $elementFactory = $this->getMockBuilder(ElementFactory::class)
133  ->disableOriginalConstructor()
134  ->getMock();
135 
136  $collectionFactory = $this->getMockBuilder(CollectionFactory::class)
137  ->disableOriginalConstructor()
138  ->getMock();
139 
140  $regionFactory = $this->getMockBuilder(RegionFactory::class)
141  ->disableOriginalConstructor()
142  ->getMock();
143 
144  $currencyFactory = $this->getMockBuilder(CurrencyFactory::class)
145  ->disableOriginalConstructor()
146  ->getMock();
147 
148  $data = $this->getMockBuilder(Data::class)
149  ->disableOriginalConstructor()
150  ->getMock();
151 
152  $stockRegistry = $this->getMockBuilder(StockRegistry::class)
153  ->disableOriginalConstructor()
154  ->getMock();
155 
156  $reader = $this->getMockBuilder(Reader::class)
157  ->disableOriginalConstructor()
158  ->getMock();
159 
160  $this->serializer = $this->getMockBuilder(Json::class)
161  ->disableOriginalConstructor()
162  ->getMock();
163 
164  $this->logger = $this->getMockForAbstractClass(LoggerInterface::class);
165 
166  $this->carrier = $this->getMockBuilder(Carrier::class)
167  ->setMethods(['_createSoapClient'])
168  ->setConstructorArgs(
169  [
170  'scopeConfig' => $this->scope,
171  'rateErrorFactory' => $this->errorFactory,
172  'logger' => $this->logger,
173  'xmlSecurity' => new Security(),
174  'xmlElFactory' => $elementFactory,
175  'rateFactory' => $rateFactory,
176  'rateMethodFactory' => $rateMethodFactory,
177  'trackFactory' => $resultFactory,
178  'trackErrorFactory' => $this->trackErrorFactory,
179  'trackStatusFactory' => $this->statusFactory,
180  'regionFactory' => $regionFactory,
181  'countryFactory' => $countryFactory,
182  'currencyFactory' => $currencyFactory,
183  'directoryData' => $data,
184  'stockRegistry' => $stockRegistry,
185  'storeManager' => $storeManager,
186  'configReader' => $reader,
187  'productCollectionFactory' => $collectionFactory,
188  'data' => [],
189  'serializer' => $this->serializer,
190  ]
191  )->getMock();
192  $this->soapClient = $this->getMockBuilder(\SoapClient::class)
193  ->disableOriginalConstructor()
194  ->setMethods(['getRates', 'track'])
195  ->getMock();
196  $this->carrier->method('_createSoapClient')
197  ->willReturn($this->soapClient);
198  }
199 
200  public function testSetRequestWithoutCity()
201  {
202  $request = $this->getMockBuilder(RateRequest::class)
203  ->disableOriginalConstructor()
204  ->setMethods(['getDestCity'])
205  ->getMock();
206  $request->expects($this->once())
207  ->method('getDestCity')
208  ->willReturn(null);
209  $this->carrier->setRequest($request);
210  }
211 
212  public function testSetRequestWithCity()
213  {
214  $request = $this->getMockBuilder(RateRequest::class)
215  ->disableOriginalConstructor()
216  ->setMethods(['getDestCity'])
217  ->getMock();
218  $request->expects($this->exactly(2))
219  ->method('getDestCity')
220  ->willReturn('Small Town');
221  $this->carrier->setRequest($request);
222  }
223 
230  public function scopeConfigGetValue(string $path)
231  {
232  $pathMap = [
233  'carriers/fedex/showmethod' => 1,
234  'carriers/fedex/allowed_methods' => 'ServiceType',
235  'carriers/fedex/debug' => 1,
236  ];
237 
238  return isset($pathMap[$path]) ? $pathMap[$path] : null;
239  }
240 
248  public function testCollectRatesRateAmountOriginBased($amount, $rateType, $expected, $callNum = 1)
249  {
250  $this->scope->expects($this->any())
251  ->method('isSetFlag')
252  ->willReturn(true);
253 
254  // @codingStandardsIgnoreStart
255  $netAmount = new \stdClass();
256  $netAmount->Amount = $amount;
257 
258  $totalNetCharge = new \stdClass();
259  $totalNetCharge->TotalNetCharge = $netAmount;
260  $totalNetCharge->RateType = $rateType;
261 
262  $ratedShipmentDetail = new \stdClass();
263  $ratedShipmentDetail->ShipmentRateDetail = $totalNetCharge;
264 
265  $rate = new \stdClass();
266  $rate->ServiceType = 'ServiceType';
267  $rate->RatedShipmentDetails = [$ratedShipmentDetail];
268 
269  $response = new \stdClass();
270  $response->HighestSeverity = 'SUCCESS';
271  $response->RateReplyDetails = $rate;
272  // @codingStandardsIgnoreEnd
273 
274  $this->serializer->method('serialize')
275  ->willReturn('CollectRateString' . $amount);
276 
277  $request = $this->getMockBuilder(RateRequest::class)
278  ->disableOriginalConstructor()
279  ->getMock();
280 
281  $this->soapClient->expects($this->exactly($callNum))
282  ->method('getRates')
283  ->willReturn($response);
284 
285  $allRates1 = $this->carrier->collectRates($request)->getAllRates();
286  foreach ($allRates1 as $rate) {
287  $this->assertEquals($expected, $rate->getData('cost'));
288  }
289  }
290 
295  public function collectRatesDataProvider()
296  {
297  return [
298  [10.0, 'RATED_ACCOUNT_PACKAGE', 10],
299  [10.0, 'RATED_ACCOUNT_PACKAGE', 10, 0],
300  [11.50, 'PAYOR_ACCOUNT_PACKAGE', 11.5],
301  [11.50, 'PAYOR_ACCOUNT_PACKAGE', 11.5, 0],
302  [100.01, 'RATED_ACCOUNT_SHIPMENT', 100.01],
303  [100.01, 'RATED_ACCOUNT_SHIPMENT', 100.01, 0],
304  [32.2, 'PAYOR_ACCOUNT_SHIPMENT', 32.2],
305  [32.2, 'PAYOR_ACCOUNT_SHIPMENT', 32.2, 0],
306  [15.0, 'RATED_LIST_PACKAGE', 15],
307  [15.0, 'RATED_LIST_PACKAGE', 15, 0],
308  [123.25, 'PAYOR_LIST_PACKAGE', 123.25],
309  [123.25, 'PAYOR_LIST_PACKAGE', 123.25, 0],
310  [12.12, 'RATED_LIST_SHIPMENT', 12.12],
311  [12.12, 'RATED_LIST_SHIPMENT', 12.12, 0],
312  [38.9, 'PAYOR_LIST_SHIPMENT', 38.9],
313  [38.9, 'PAYOR_LIST_SHIPMENT', 38.9, 0],
314  ];
315  }
316 
318  {
319  $this->scope->expects($this->once())
320  ->method('isSetFlag')
321  ->willReturn(false);
322 
323  $this->error->expects($this->once())
324  ->method('setCarrier')
325  ->with('fedex');
326  $this->error->expects($this->once())
327  ->method('setCarrierTitle');
328  $this->error->expects($this->once())
329  ->method('setErrorMessage');
330 
331  $request = new RateRequest();
332  $request->setPackageWeight(1);
333 
334  $this->assertSame($this->error, $this->carrier->collectRates($request));
335  }
336 
343  public function testFilterDebugData($data, array $maskFields, $expected)
344  {
345  $refClass = new \ReflectionClass(Carrier::class);
346  $property = $refClass->getProperty('_debugReplacePrivateDataKeys');
347  $property->setAccessible(true);
348  $property->setValue($this->carrier, $maskFields);
349 
350  $refMethod = $refClass->getMethod('filterDebugData');
351  $refMethod->setAccessible(true);
352  $result = $refMethod->invoke($this->carrier, $data);
353  $this->assertEquals($expected, $result);
354  }
355 
359  public function logDataProvider()
360  {
361  return [
362  [
363  [
364  'WebAuthenticationDetail' => [
365  'UserCredential' => [
366  'Key' => 'testKey',
367  'Password' => 'testPassword',
368  ],
369  ],
370  'ClientDetail' => [
371  'AccountNumber' => 4121213,
372  'MeterNumber' => 'testMeterNumber',
373  ],
374  ],
375  ['Key', 'Password', 'MeterNumber'],
376  [
377  'WebAuthenticationDetail' => [
378  'UserCredential' => [
379  'Key' => '****',
380  'Password' => '****',
381  ],
382  ],
383  'ClientDetail' => [
384  'AccountNumber' => 4121213,
385  'MeterNumber' => '****',
386  ],
387  ],
388  ],
389  ];
390  }
391 
392  public function testGetTrackingErrorResponse()
393  {
394  $tracking = '123456789012';
395  $errorMessage = 'Tracking information is unavailable.';
396 
397  // @codingStandardsIgnoreStart
398  $response = new \stdClass();
399  $response->HighestSeverity = 'ERROR';
400  $response->Notifications = new \stdClass();
401  $response->Notifications->Message = $errorMessage;
402  // @codingStandardsIgnoreEnd
403 
404  $error = $this->helper->getObject(Error::class);
405  $this->trackErrorFactory->expects($this->once())
406  ->method('create')
407  ->willReturn($error);
408 
409  $this->carrier->getTracking($tracking);
410  $tracks = $this->carrier->getResult()->getAllTrackings();
411 
412  $this->assertEquals(1, count($tracks));
413 
415  $current = $tracks[0];
416  $this->assertInstanceOf(Error::class, $current);
417  $this->assertEquals(__($errorMessage), $current->getErrorMessage());
418  }
419 
427  public function testGetTracking($tracking, $shipTimeStamp, $expectedDate, $expectedTime, $callNum = 1)
428  {
429  // @codingStandardsIgnoreStart
430  $response = new \stdClass();
431  $response->HighestSeverity = 'SUCCESS';
432  $response->CompletedTrackDetails = new \stdClass();
433 
434  $trackDetails = new \stdClass();
435  $trackDetails->ShipTimestamp = $shipTimeStamp;
436  $trackDetails->DeliverySignatureName = 'signature';
437 
438  $trackDetails->StatusDetail = new \stdClass();
439  $trackDetails->StatusDetail->Description = 'SUCCESS';
440 
441  $trackDetails->Service = new \stdClass();
442  $trackDetails->Service->Description = 'ground';
443  $trackDetails->EstimatedDeliveryTimestamp = $shipTimeStamp;
444 
445  $trackDetails->EstimatedDeliveryAddress = new \stdClass();
446  $trackDetails->EstimatedDeliveryAddress->City = 'Culver City';
447  $trackDetails->EstimatedDeliveryAddress->StateOrProvinceCode = 'CA';
448  $trackDetails->EstimatedDeliveryAddress->CountryCode = 'US';
449 
450  $trackDetails->PackageWeight = new \stdClass();
451  $trackDetails->PackageWeight->Value = 23;
452  $trackDetails->PackageWeight->Units = 'LB';
453 
454  $response->CompletedTrackDetails->TrackDetails = [$trackDetails];
455  // @codingStandardsIgnoreEnd
456 
457  $this->soapClient->expects($this->exactly($callNum))
458  ->method('track')
459  ->willReturn($response);
460 
461  $this->serializer->method('serialize')
462  ->willReturn('TrackingString' . $tracking);
463 
464  $status = $this->helper->getObject(Status::class);
465  $this->statusFactory->method('create')
466  ->willReturn($status);
467 
468  $tracks = $this->carrier->getTracking($tracking)->getAllTrackings();
469  $this->assertEquals(1, count($tracks));
470 
471  $current = $tracks[0];
472  $fields = [
473  'signedby',
474  'status',
475  'service',
476  'deliverylocation',
477  'weight',
478  ];
479  array_walk($fields, function ($field) use ($current) {
480  $this->assertNotEmpty($current[$field]);
481  });
482 
483  $this->assertEquals($expectedDate, $current['deliverydate']);
484  $this->assertEquals($expectedTime, $current['deliverytime']);
485  $this->assertEquals($expectedDate, $current['shippeddate']);
486  }
487 
493  public function shipDateDataProvider()
494  {
495  return [
496  'tracking1' => [
497  'tracking1',
498  'shipTimestamp' => '2016-08-05T14:06:35+01:00',
499  'expectedDate' => '2016-08-05',
500  '13:06:35',
501  ],
502  'tracking1-again' => [
503  'tracking1',
504  'shipTimestamp' => '2016-08-05T02:06:35+03:00',
505  'expectedDate' => '2016-08-05',
506  '13:06:35',
507  0,
508  ],
509  'tracking2' => [
510  'tracking2',
511  'shipTimestamp' => '2016-08-05T02:06:35+03:00',
512  'expectedDate' => '2016-08-04',
513  '23:06:35',
514  ],
515  'tracking3' => [
516  'tracking3',
517  'shipTimestamp' => '2016-08-05T14:06:35',
518  'expectedDate' => '2016-08-05',
519  '14:06:35',
520  ],
521  'tracking4' => [
522  'tracking4',
523  'shipTimestamp' => '2016-08-05 14:06:35',
524  'expectedDate' => null,
525  null,
526  ],
527  'tracking5' => [
528  'tracking5',
529  'shipTimestamp' => '2016-08-05 14:06:35+00:00',
530  'expectedDate' => null,
531  null,
532  ],
533  'tracking6' => [
534  'tracking6',
535  'shipTimestamp' => '2016-08-05',
536  'expectedDate' => null,
537  null,
538  ],
539  'tracking7' => [
540  'tracking7',
541  'shipTimestamp' => '2016/08/05',
542  'expectedDate' => null,
543  null
544  ],
545  ];
546  }
547 
556  public function testGetTrackingWithEvents($tracking, $shipTimeStamp, $expectedDate, $expectedTime, $callNum = 1)
557  {
558  $tracking = $tracking . 'WithEvent';
559 
560  // @codingStandardsIgnoreStart
561  $response = new \stdClass();
562  $response->HighestSeverity = 'SUCCESS';
563  $response->CompletedTrackDetails = new \stdClass();
564 
565  $event = new \stdClass();
566  $event->EventDescription = 'Test';
567  $event->Timestamp = $shipTimeStamp;
568  $event->Address = new \stdClass();
569 
570  $event->Address->City = 'Culver City';
571  $event->Address->StateOrProvinceCode = 'CA';
572  $event->Address->CountryCode = 'US';
573 
574  $trackDetails = new \stdClass();
575  $trackDetails->Events = $event;
576 
577  $response->CompletedTrackDetails->TrackDetails = $trackDetails;
578  // @codingStandardsIgnoreEnd
579 
580  $this->soapClient->expects($this->exactly($callNum))
581  ->method('track')
582  ->willReturn($response);
583 
584  $this->serializer->method('serialize')
585  ->willReturn('TrackingWithEventsString' . $tracking);
586 
587  $status = $this->helper->getObject(Status::class);
588  $this->statusFactory->method('create')
589  ->willReturn($status);
590 
591  $this->carrier->getTracking($tracking);
592  $tracks = $this->carrier->getResult()->getAllTrackings();
593  $this->assertEquals(1, count($tracks));
594 
595  $current = $tracks[0];
596  $this->assertNotEmpty($current['progressdetail']);
597  $this->assertEquals(1, count($current['progressdetail']));
598 
599  $event = $current['progressdetail'][0];
600  $fields = ['activity', 'deliverylocation'];
601  array_walk($fields, function ($field) use ($event) {
602  $this->assertNotEmpty($event[$field]);
603  });
604  $this->assertEquals($expectedDate, $event['deliverydate']);
605  $this->assertEquals($expectedTime, $event['deliverytime']);
606  }
607 
612  private function initRateErrorFactory()
613  {
614  $this->error = $this->getMockBuilder(RateResultError::class)
615  ->disableOriginalConstructor()
616  ->setMethods(['setCarrier', 'setCarrierTitle', 'setErrorMessage'])
617  ->getMock();
618  $this->errorFactory = $this->getMockBuilder(RateErrorFactory::class)
619  ->disableOriginalConstructor()
620  ->setMethods(['create'])
621  ->getMock();
622  $this->errorFactory->expects($this->any())
623  ->method('create')
624  ->willReturn($this->error);
625  }
626 
631  private function getRateFactory()
632  {
633  $rate = $this->getMockBuilder(RateResult::class)
634  ->disableOriginalConstructor()
635  ->setMethods(['getError'])
636  ->getMock();
637  $rateFactory = $this->getMockBuilder(RateResultFactory::class)
638  ->disableOriginalConstructor()
639  ->setMethods(['create'])
640  ->getMock();
641  $rateFactory->expects($this->any())
642  ->method('create')
643  ->willReturn($rate);
644 
645  return $rateFactory;
646  }
647 
652  private function getCountryFactory()
653  {
654  $country = $this->getMockBuilder(Country::class)
655  ->disableOriginalConstructor()
656  ->setMethods(['load', 'getData'])
657  ->getMock();
658  $country->expects($this->any())
659  ->method('load')
660  ->willReturnSelf();
661 
662  $countryFactory = $this->getMockBuilder(CountryFactory::class)
663  ->disableOriginalConstructor()
664  ->setMethods(['create'])
665  ->getMock();
666  $countryFactory->expects($this->any())
667  ->method('create')
668  ->willReturn($country);
669 
670  return $countryFactory;
671  }
672 
677  private function getResultFactory()
678  {
679  $resultFactory = $this->getMockBuilder(ResultFactory::class)
680  ->disableOriginalConstructor()
681  ->setMethods(['create'])
682  ->getMock();
683  $this->result = $this->helper->getObject(Result::class);
684  $resultFactory->expects($this->any())
685  ->method('create')
686  ->willReturn($this->result);
687 
688  return $resultFactory;
689  }
690 
695  private function getStoreManager()
696  {
697  $store = $this->getMockBuilder(Store::class)
698  ->disableOriginalConstructor()
699  ->setMethods(['getBaseCurrencyCode'])
700  ->getMock();
701  $storeManager = $this->createMock(StoreManagerInterface::class);
702  $storeManager->expects($this->any())
703  ->method('getStore')
704  ->willReturn($store);
705 
706  return $storeManager;
707  }
708 
713  private function getRateMethodFactory()
714  {
715  $priceCurrency = $this->createMock(PriceCurrencyInterface::class);
716  $rateMethod = $this->getMockBuilder(Method::class)
717  ->setConstructorArgs(['priceCurrency' => $priceCurrency])
718  ->setMethods(null)
719  ->getMock();
720  $rateMethodFactory = $this->getMockBuilder(MethodFactory::class)
721  ->disableOriginalConstructor()
722  ->setMethods(['create'])
723  ->getMock();
724  $rateMethodFactory->expects($this->any())
725  ->method('create')
726  ->willReturn($rateMethod);
727 
728  return $rateMethodFactory;
729  }
730 }
$response
Definition: 404.php:11
testGetTracking($tracking, $shipTimeStamp, $expectedDate, $expectedTime, $callNum=1)
$fields
Definition: details.phtml:14
$storeManager
__()
Definition: __.php:13
$amount
Definition: order.php:14
testGetTrackingWithEvents($tracking, $shipTimeStamp, $expectedDate, $expectedTime, $callNum=1)
$status
Definition: order_status.php:8
testCollectRatesRateAmountOriginBased($amount, $rateType, $expected, $callNum=1)
testFilterDebugData($data, array $maskFields, $expected)