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 
9 use Magento\Directory\Model\CountryFactory;
18 use Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory;
20 use Magento\Shipping\Model\Rate\ResultFactory;
22 use Magento\Shipping\Model\Simplexml\ElementFactory;
24 use PHPUnit_Framework_MockObject_MockObject as MockObject;
25 use Psr\Log\LoggerInterface;
26 
30 class CarrierTest extends \PHPUnit\Framework\TestCase
31 {
32  const FREE_METHOD_NAME = 'free_method';
33 
34  const PAID_METHOD_NAME = 'paid_method';
35 
41  private $error;
42 
46  private $helper;
47 
53  private $model;
54 
58  private $errorFactory;
59 
63  private $scope;
64 
68  private $countryFactory;
69 
73  private $country;
74 
78  private $abstractModel;
79 
83  private $rate;
84 
88  private $httpClient;
89 
93  private $logger;
94 
95  protected function setUp()
96  {
97  $this->helper = new ObjectManager($this);
98 
99  $this->scope = $this->getMockBuilder(ScopeConfigInterface::class)
100  ->disableOriginalConstructor()
101  ->getMock();
102 
103  $this->scope->method('getValue')
104  ->willReturnCallback([$this, 'scopeConfigGetValue']);
105 
106  $this->error = $this->getMockBuilder(Error::class)
107  ->setMethods(['setCarrier', 'setCarrierTitle', 'setErrorMessage'])
108  ->getMock();
109 
110  $this->errorFactory = $this->getMockBuilder(ErrorFactory::class)
111  ->disableOriginalConstructor()
112  ->setMethods(['create'])
113  ->getMock();
114 
115  $this->errorFactory->method('create')
116  ->willReturn($this->error);
117 
118  $rateFactory = $this->getRateFactory();
119 
120  $this->country = $this->getMockBuilder(Country::class)
121  ->disableOriginalConstructor()
122  ->setMethods(['load', 'getData'])
123  ->getMock();
124 
125  $this->abstractModel = $this->getMockBuilder(AbstractModel::class)
126  ->disableOriginalConstructor()
127  ->setMethods(['getData'])
128  ->getMock();
129 
130  $this->country->method('load')
131  ->willReturn($this->abstractModel);
132 
133  $this->countryFactory = $this->getMockBuilder(CountryFactory::class)
134  ->disableOriginalConstructor()
135  ->setMethods(['create'])
136  ->getMock();
137 
138  $this->countryFactory->method('create')
139  ->willReturn($this->country);
140 
141  $xmlFactory = $this->getXmlFactory();
142  $httpClientFactory = $this->getHttpClientFactory();
143 
144  $this->logger = $this->getMockForAbstractClass(LoggerInterface::class);
145 
146  $this->model = $this->helper->getObject(
147  Carrier::class,
148  [
149  'scopeConfig' => $this->scope,
150  'rateErrorFactory' => $this->errorFactory,
151  'countryFactory' => $this->countryFactory,
152  'rateFactory' => $rateFactory,
153  'xmlElFactory' => $xmlFactory,
154  'logger' => $this->logger,
155  'httpClientFactory' => $httpClientFactory,
156  ]
157  );
158  }
159 
166  public function scopeConfigGetValue(string $path)
167  {
168  $pathMap = [
169  'carriers/ups/free_method' => 'free_method',
170  'carriers/ups/free_shipping_subtotal' => 5,
171  'carriers/ups/showmethod' => 1,
172  'carriers/ups/title' => 'ups Title',
173  'carriers/ups/specificerrmsg' => 'ups error message',
174  'carriers/ups/min_package_weight' => 2,
175  'carriers/ups/type' => 'UPS',
176  'carriers/ups/debug' => 1,
177  'carriers/ups/username' => 'user',
178  'carriers/ups/password' => 'pass',
179  'carriers/ups/access_license_number' => 'acn',
180  ];
181 
182  return isset($pathMap[$path]) ? $pathMap[$path] : null;
183  }
184 
193  public function testGetMethodPrice(
194  $cost,
196  $freeShippingEnabled,
197  $requestSubtotal,
198  $expectedPrice
199  ) {
200  $path = 'carriers/' . $this->model->getCarrierCode() . '/';
201  $this->scope->method('isSetFlag')
202  ->with($path . 'free_shipping_enable')
203  ->willReturn($freeShippingEnabled);
204 
205  $request = new RateRequest();
206  $request->setBaseSubtotalInclTax($requestSubtotal);
207  $this->model->setRawRequest($request);
208  $price = $this->model->getMethodPrice($cost, $shippingMethod);
209  $this->assertEquals($expectedPrice, $price);
210  }
211 
217  public function getMethodPriceProvider()
218  {
219  return [
220  [3, self::FREE_METHOD_NAME, true, 6, 0],
221  [3, self::FREE_METHOD_NAME, true, 4, 3],
222  [3, self::FREE_METHOD_NAME, false, 6, 3],
223  [3, self::FREE_METHOD_NAME, false, 4, 3],
224  [3, self::PAID_METHOD_NAME, true, 6, 3],
225  [3, self::PAID_METHOD_NAME, true, 4, 3],
226  [3, self::PAID_METHOD_NAME, false, 6, 3],
227  [3, self::PAID_METHOD_NAME, false, 4, 3],
228  [7, self::FREE_METHOD_NAME, true, 6, 0],
229  [7, self::FREE_METHOD_NAME, true, 4, 7],
230  [7, self::FREE_METHOD_NAME, false, 6, 7],
231  [7, self::FREE_METHOD_NAME, false, 4, 7],
232  [7, self::PAID_METHOD_NAME, true, 6, 7],
233  [7, self::PAID_METHOD_NAME, true, 4, 7],
234  [7, self::PAID_METHOD_NAME, false, 6, 7],
235  [7, self::PAID_METHOD_NAME, false, 4, 7],
236  [3, self::FREE_METHOD_NAME, true, 0, 3],
237  [3, self::FREE_METHOD_NAME, true, 0, 3],
238  [3, self::FREE_METHOD_NAME, false, 0, 3],
239  [3, self::FREE_METHOD_NAME, false, 0, 3],
240  [3, self::PAID_METHOD_NAME, true, 0, 3],
241  [3, self::PAID_METHOD_NAME, true, 0, 3],
242  [3, self::PAID_METHOD_NAME, false, 0, 3],
243  [3, self::PAID_METHOD_NAME, false, 0, 3]
244  ];
245  }
246 
248  {
249  $this->scope->method('isSetFlag')
250  ->willReturn(false);
251 
252  $this->error->method('setCarrier')
253  ->with('ups');
254  $this->error->method('setCarrierTitle');
255  $this->error->method('setErrorMessage');
256 
257  $request = new RateRequest();
258  $request->setPackageWeight(1);
259 
260  $this->assertSame($this->error, $this->model->collectRates($request));
261  }
262 
263  public function testCollectRatesFail()
264  {
265  $this->scope->method('isSetFlag')
266  ->willReturn(true);
267 
268  $request = new RateRequest();
269  $request->setPackageWeight(1);
270 
271  $this->assertSame($this->rate, $this->model->collectRates($request));
272  }
273 
280  public function testFilterDebugData($data, array $maskFields, $expected)
281  {
282  $refClass = new \ReflectionClass(Carrier::class);
283  $property = $refClass->getProperty('_debugReplacePrivateDataKeys');
284  $property->setAccessible(true);
285  $property->setValue($this->model, $maskFields);
286 
287  $refMethod = $refClass->getMethod('filterDebugData');
288  $refMethod->setAccessible(true);
289  $result = $refMethod->invoke($this->model, $data);
290  $expectedXml = new \SimpleXMLElement($expected);
291  $resultXml = new \SimpleXMLElement($result);
292  $this->assertEquals($expectedXml->asXML(), $resultXml->asXML());
293  }
294 
298  public function logDataProvider()
299  {
300  return [
301  [
302  '<?xml version="1.0" encoding="UTF-8"?>
303  <RateRequest>
304  <UserId>42121</UserId>
305  <Password>TestPassword</Password>
306  <Package ID="0">
307  <Service>ALL</Service>
308  </Package>
309  </RateRequest>',
310  ['UserId', 'Password'],
311  '<?xml version="1.0" encoding="UTF-8"?>
312  <RateRequest>
313  <UserId>****</UserId>
314  <Password>****</Password>
315  <Package ID="0">
316  <Service>ALL</Service>
317  </Package>
318  </RateRequest>',
319  ],
320  [
321  '<?xml version="1.0" encoding="UTF-8"?>
322  <RateRequest>
323  <Auth>
324  <UserId>1231</UserId>
325  </Auth>
326  <Package ID="0">
327  <Service>ALL</Service>
328  </Package>
329  </RateRequest>',
330  ['UserId'],
331  '<?xml version="1.0" encoding="UTF-8"?>
332  <RateRequest>
333  <Auth>
334  <UserId>****</UserId>
335  </Auth>
336  <Package ID="0">
337  <Service>ALL</Service>
338  </Package>
339  </RateRequest>',
340  ]
341  ];
342  }
343 
349  public function testSetRequest($countryCode, $foundCountryCode)
350  {
352  $request = $this->helper->getObject(RateRequest::class);
353  $request->setData([
354  'orig_country' => 'USA',
355  'orig_region_code' => 'CA',
356  'orig_post_code' => 90230,
357  'orig_city' => 'Culver City',
358  'dest_country_id' => $countryCode,
359  ]);
360 
361  $this->country->expects($this->at(1))
362  ->method('load')
363  ->with($countryCode)
364  ->willReturnSelf();
365 
366  $this->country->method('getData')
367  ->with('iso2_code')
368  ->willReturn($foundCountryCode);
369 
370  $this->model->setRequest($request);
371  }
372 
377  public function countryDataProvider()
378  {
379  return [
380  ['countryCode' => 'PR', 'foundCountryCode' => null],
381  ['countryCode' => 'US', 'foundCountryCode' => 'US'],
382  ];
383  }
384 
390  public function testRequestToShipment()
391  {
392  // the same tracking number is specified in the fixtures XML file.
393  $trackingNumber = '1Z207W886698856557';
394  $packages = $this->getPackages();
395  $request = new DataObject(['packages' => $packages]);
396  $shipmentResponse = simplexml_load_file(__DIR__ . '/../Fixtures/ShipmentConfirmResponse.xml');
397  $acceptResponse = simplexml_load_file(__DIR__ . '/../Fixtures/ShipmentAcceptResponse.xml');
398 
399  $this->httpClient->method('getBody')
400  ->willReturnOnConsecutiveCalls($shipmentResponse->asXML(), $acceptResponse->asXML());
401 
402  $this->logger->expects($this->atLeastOnce())
403  ->method('debug')
404  ->with($this->stringContains('<UserId>****</UserId>'));
405 
406  $result = $this->model->requestToShipment($request);
407  $this->assertEmpty($result->getErrors());
408 
409  $info = $result->getInfo()[0];
410  $this->assertEquals($trackingNumber, $info['tracking_number'], 'Tracking Number must match.');
411  }
412 
418  private function getXmlFactory(): MockObject
419  {
420  $xmlElFactory = $this->getMockBuilder(ElementFactory::class)
421  ->disableOriginalConstructor()
422  ->setMethods(['create'])
423  ->getMock();
424  $xmlElFactory->method('create')
425  ->willReturnCallback(
426  function ($data) {
427  $helper = new ObjectManager($this);
428 
429  return $helper->getObject(
430  Element::class,
431  ['data' => $data['data']]
432  );
433  }
434  );
435 
436  return $xmlElFactory;
437  }
438 
442  private function getPackages(): array
443  {
444  $packages = [
445  'package' => [
446  'params' => [
447  'width' => '3',
448  'length' => '3',
449  'height' => '3',
450  'dimension_units' => 'INCH',
451  'weight_units' => 'POUND',
452  'weight' => '0.454000000001',
453  'customs_value' => '10.00',
454  'container' => 'Small Express Box',
455  ],
456  'items' => [
457  'item1' => [
458  'name' => 'item_name',
459  ],
460  ],
461  ],
462  ];
463 
464  return $packages;
465  }
466 
472  private function getHttpClientFactory(): MockObject
473  {
474  $httpClientFactory = $this->getMockBuilder(ClientFactory::class)
475  ->disableOriginalConstructor()
476  ->setMethods(['create'])
477  ->getMock();
478  $this->httpClient = $this->getMockForAbstractClass(ClientInterface::class);
479  $httpClientFactory->method('create')
480  ->willReturn($this->httpClient);
481 
482  return $httpClientFactory;
483  }
484 
488  private function getRateFactory(): MockObject
489  {
490  $this->rate = $this->createPartialMock(Result::class, ['getError']);
491  $rateFactory = $this->createPartialMock(ResultFactory::class, ['create']);
492 
493  $rateFactory->method('create')
494  ->willReturn($this->rate);
495 
496  return $rateFactory;
497  }
498 }
testGetMethodPrice( $cost, $shippingMethod, $freeShippingEnabled, $requestSubtotal, $expectedPrice)
defined('TESTS_BP')||define('TESTS_BP' __DIR__
Definition: _bootstrap.php:60
$price
testFilterDebugData($data, array $maskFields, $expected)
$shippingMethod
Definition: popup.phtml:12
foreach( $_productCollection as $_product)() ?>" class $info
Definition: listing.phtml:52