FreeShippingTest.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. declare(strict_types=1);
  7. namespace Magento\OfflineShipping\Test\Unit\Model\Quote\Address;
  8. use Magento\OfflineShipping\Model\Quote\Address\FreeShipping;
  9. use Magento\OfflineShipping\Model\SalesRule\Calculator;
  10. use Magento\Quote\Model\Quote;
  11. use Magento\Quote\Model\Quote\Address;
  12. use Magento\Quote\Model\Quote\Item;
  13. use Magento\Store\Api\Data\StoreInterface;
  14. use Magento\Store\Model\StoreManagerInterface;
  15. use PHPUnit_Framework_MockObject_MockObject as MockObject;
  16. class FreeShippingTest extends \PHPUnit\Framework\TestCase
  17. {
  18. private static $websiteId = 1;
  19. private static $customerGroupId = 2;
  20. private static $couponCode = 3;
  21. private static $storeId = 1;
  22. /**
  23. * @var FreeShipping
  24. */
  25. private $model;
  26. /**
  27. * @var MockObject|StoreManagerInterface
  28. */
  29. private $storeManager;
  30. /**
  31. * @var MockObject|Calculator
  32. */
  33. private $calculator;
  34. protected function setUp()
  35. {
  36. $this->storeManager = $this->createMock(StoreManagerInterface::class);
  37. $this->calculator = $this->createMock(Calculator::class);
  38. $this->model = new FreeShipping(
  39. $this->storeManager,
  40. $this->calculator
  41. );
  42. }
  43. /**
  44. * Checks free shipping availability based on quote items and cart rule calculations.
  45. *
  46. * @param int $addressFree
  47. * @param int $fItemFree
  48. * @param int $sItemFree
  49. * @param bool $expected
  50. * @dataProvider itemsDataProvider
  51. */
  52. public function testIsFreeShipping(int $addressFree, int $fItemFree, int $sItemFree, bool $expected)
  53. {
  54. $address = $this->getShippingAddress();
  55. $this->withStore();
  56. $quote = $this->getQuote($address);
  57. $fItem = $this->getItem($quote);
  58. $sItem = $this->getItem($quote);
  59. $items = [$fItem, $sItem];
  60. $this->calculator->method('init')
  61. ->with(self::$websiteId, self::$customerGroupId, self::$couponCode);
  62. $this->calculator->method('processFreeShipping')
  63. ->withConsecutive(
  64. [$fItem],
  65. [$sItem]
  66. )
  67. ->willReturnCallback(function () use ($fItem, $sItem, $addressFree, $fItemFree, $sItemFree) {
  68. // emulate behavior of cart rule calculator
  69. $fItem->getAddress()->setFreeShipping($addressFree);
  70. $fItem->setFreeShipping($fItemFree);
  71. $sItem->setFreeShipping($sItemFree);
  72. });
  73. $actual = $this->model->isFreeShipping($quote, $items);
  74. self::assertEquals($expected, $actual);
  75. self::assertEquals($expected, $address->getFreeShipping());
  76. }
  77. /**
  78. * Gets list of variations with free shipping availability.
  79. *
  80. * @return array
  81. */
  82. public function itemsDataProvider(): array
  83. {
  84. return [
  85. ['addressFree' => 1, 'fItemFree' => 0, 'sItemFree' => 0, 'expected' => true],
  86. ['addressFree' => 0, 'fItemFree' => 1, 'sItemFree' => 0, 'expected' => false],
  87. ['addressFree' => 0, 'fItemFree' => 0, 'sItemFree' => 1, 'expected' => false],
  88. ['addressFree' => 0, 'fItemFree' => 1, 'sItemFree' => 1, 'expected' => true],
  89. ];
  90. }
  91. /**
  92. * Creates mock object for store entity.
  93. */
  94. private function withStore()
  95. {
  96. $store = $this->getMockBuilder(StoreInterface::class)
  97. ->disableOriginalConstructor()
  98. ->getMock();
  99. $this->storeManager->method('getStore')
  100. ->with(self::$storeId)
  101. ->willReturn($store);
  102. $store->method('getWebsiteId')
  103. ->willReturn(self::$websiteId);
  104. }
  105. /**
  106. * Get mock object for quote entity.
  107. *
  108. * @param Address $address
  109. * @return Quote
  110. */
  111. private function getQuote(Address $address): Quote
  112. {
  113. /** @var Quote|MockObject $quote */
  114. $quote = $this->getMockBuilder(Quote::class)
  115. ->disableOriginalConstructor()
  116. ->setMethods(
  117. [
  118. 'getCouponCode', 'getCustomerGroupId', 'getShippingAddress', 'getStoreId', 'getItemsQty',
  119. 'getVirtualItemsQty'
  120. ]
  121. )
  122. ->getMock();
  123. $quote->method('getStoreId')
  124. ->willReturn(self::$storeId);
  125. $quote->method('getCustomerGroupId')
  126. ->willReturn(self::$customerGroupId);
  127. $quote->method('getCouponCode')
  128. ->willReturn(self::$couponCode);
  129. $quote->method('getShippingAddress')
  130. ->willReturn($address);
  131. $quote->method('getItemsQty')
  132. ->willReturn(2);
  133. $quote->method('getVirtualItemsQty')
  134. ->willReturn(0);
  135. return $quote;
  136. }
  137. /**
  138. * Gets stub object for shipping address.
  139. *
  140. * @return Address|MockObject
  141. */
  142. private function getShippingAddress(): Address
  143. {
  144. /** @var Address|MockObject $address */
  145. $address = $this->getMockBuilder(Address::class)
  146. ->disableOriginalConstructor()
  147. ->setMethods(['beforeSave'])
  148. ->getMock();
  149. return $address;
  150. }
  151. /**
  152. * Gets stub object for quote item.
  153. *
  154. * @param Quote $quote
  155. * @return Item
  156. */
  157. private function getItem(Quote $quote): Item
  158. {
  159. /** @var Item|MockObject $item */
  160. $item = $this->getMockBuilder(Item::class)
  161. ->disableOriginalConstructor()
  162. ->setMethods(['getHasChildren'])
  163. ->getMock();
  164. $item->setQuote($quote);
  165. $item->setNoDiscount(0);
  166. $item->setParentItemId(0);
  167. $item->method('getHasChildren')
  168. ->willReturn(0);
  169. return $item;
  170. }
  171. }