CartTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Payment\Test\Unit\Model;
  7. use \Magento\Payment\Model\Cart;
  8. class CartTest extends \PHPUnit\Framework\TestCase
  9. {
  10. /** @var \Magento\Payment\Model\Cart */
  11. protected $_model;
  12. /** @var \PHPUnit_Framework_MockObject_MockObject */
  13. protected $_eventManagerMock;
  14. /** @var \PHPUnit_Framework_MockObject_MockObject */
  15. protected $_salesModelMock;
  16. protected function setUp()
  17. {
  18. $this->_eventManagerMock = $this->createMock(\Magento\Framework\Event\ManagerInterface::class);
  19. $this->_salesModelMock = $this->createMock(\Magento\Payment\Model\Cart\SalesModel\SalesModelInterface::class);
  20. $factoryMock = $this->createMock(\Magento\Payment\Model\Cart\SalesModel\Factory::class);
  21. $factoryMock->expects($this->once())->method('create')->will($this->returnValue($this->_salesModelMock));
  22. $this->_model = new \Magento\Payment\Model\Cart($factoryMock, $this->_eventManagerMock, null);
  23. }
  24. /**
  25. * Test sales model getter
  26. */
  27. public function testGetSalesModel()
  28. {
  29. $this->assertTrue($this->_salesModelMock === $this->_model->getSalesModel());
  30. }
  31. /**
  32. * Test addCustomItem()
  33. */
  34. public function testAddCustomItem()
  35. {
  36. $this->_salesModelMock->expects(
  37. $this->once()
  38. )->method(
  39. 'getAllItems'
  40. )->will(
  41. $this->returnValue($this->_getSalesModelItems())
  42. );
  43. $this->_model->getAllItems();
  44. $this->_model->addCustomItem('test', 10, 10.5, 'some_id');
  45. $items = $this->_model->getAllItems();
  46. $customItem = array_pop($items);
  47. $this->assertTrue(
  48. $customItem->getName() == 'test' &&
  49. $customItem->getQty() == 10 &&
  50. $customItem->getAmount() == 10.5 &&
  51. $customItem->getId() == 'some_id'
  52. );
  53. }
  54. /**
  55. * @param array $transferFlags
  56. * @param array $salesModelItems
  57. * @param array $salesModelAmounts
  58. * @param array $expected
  59. * @dataProvider cartDataProvider
  60. */
  61. public function testGetAmounts($transferFlags, $salesModelItems, $salesModelAmounts, $expected)
  62. {
  63. $amounts = $this->_collectItemsAndAmounts($transferFlags, $salesModelItems, $salesModelAmounts);
  64. $this->assertEquals($expected, $amounts);
  65. // check that method just return calculated result for further calls
  66. $this->_eventManagerMock->expects($this->never())->method('dispatch');
  67. $amounts = $this->_model->getAmounts();
  68. $this->assertEquals($expected, $amounts);
  69. }
  70. /**
  71. * @param array $transferFlags
  72. * @param array $salesModelItems
  73. * @param array $salesModelAmounts
  74. * @dataProvider cartDataProvider
  75. */
  76. public function testGetAllItems($transferFlags, $salesModelItems, $salesModelAmounts)
  77. {
  78. $this->_collectItemsAndAmounts($transferFlags, $salesModelItems, $salesModelAmounts);
  79. $customItems = [];
  80. if ($transferFlags['transfer_shipping']) {
  81. $customItems[] = new \Magento\Framework\DataObject(
  82. ['name' => 'Shipping', 'qty' => 1, 'amount' => $salesModelAmounts['BaseShippingAmount']]
  83. );
  84. }
  85. if ($transferFlags['transfer_discount']) {
  86. $customItems[] = new \Magento\Framework\DataObject(
  87. ['name' => 'Discount', 'qty' => 1, 'amount' => -1.00 * $salesModelAmounts['BaseDiscountAmount']]
  88. );
  89. }
  90. $cartItems = $this->_convertToCartItems($salesModelItems);
  91. $expected = array_merge($cartItems, $customItems);
  92. $areEqual = $this->_compareSalesItems($expected, $this->_model->getAllItems());
  93. $this->assertTrue($areEqual);
  94. }
  95. /**
  96. * Test all amount specific methods i.e. add...(), set...(), get...()
  97. */
  98. public function testAmountSettersAndGetters()
  99. {
  100. foreach (['Discount', 'Shipping', 'Tax'] as $amountType) {
  101. $setMethod = 'set' . $amountType;
  102. $getMethod = 'get' . $amountType;
  103. $addMethod = 'add' . $amountType;
  104. $this->_model->{$setMethod}(10);
  105. $this->assertEquals(10, $this->_model->{$getMethod}());
  106. $this->_model->{$addMethod}(5);
  107. $this->assertEquals(15, $this->_model->{$getMethod}());
  108. $this->_model->{$addMethod}(-20);
  109. $this->assertEquals(-5, $this->_model->{$getMethod}());
  110. $this->_model->{$setMethod}(10);
  111. $this->assertEquals(10, $this->_model->{$getMethod}());
  112. }
  113. // there is no method setSubtotal(), so test the following separately
  114. $this->_model->addSubtotal(10);
  115. $this->assertEquals(10, $this->_model->getSubtotal());
  116. $this->_model->addSubtotal(2);
  117. $this->assertEquals(12, $this->_model->getSubtotal());
  118. $this->_model->addSubtotal(-20);
  119. $this->assertEquals(-8, $this->_model->getSubtotal());
  120. }
  121. /**
  122. * Data provider
  123. *
  124. * @return array
  125. */
  126. public function cartDataProvider()
  127. {
  128. return [
  129. // 1. All transfer flags set to true
  130. [
  131. ['transfer_shipping' => true, 'transfer_discount' => true],
  132. $this->_getSalesModelItems(),
  133. [
  134. 'BaseDiscountAmount' => 15.0,
  135. 'BaseShippingAmount' => 20.0,
  136. 'BaseSubtotal' => 100.0,
  137. 'BaseTaxAmount' => 8.0
  138. ],
  139. [
  140. Cart::AMOUNT_DISCOUNT => 0.0,
  141. Cart::AMOUNT_SHIPPING => 0.0,
  142. Cart::AMOUNT_SUBTOTAL => 105.0, // = 100.5 + shipping - discount
  143. Cart::AMOUNT_TAX => 8.0
  144. ]
  145. ],
  146. // 2. All transfer flags set to false
  147. [
  148. ['transfer_shipping' => false, 'transfer_discount' => false],
  149. $this->_getSalesModelItems(),
  150. [
  151. 'BaseDiscountAmount' => 15.0,
  152. 'BaseShippingAmount' => 20.0,
  153. 'BaseSubtotal' => 100.0,
  154. 'BaseTaxAmount' => 8.0
  155. ],
  156. [
  157. Cart::AMOUNT_DISCOUNT => 15.0,
  158. Cart::AMOUNT_SHIPPING => 20.0,
  159. Cart::AMOUNT_SUBTOTAL => 100.0,
  160. Cart::AMOUNT_TAX => 8.0
  161. ]
  162. ],
  163. // 3. Shipping transfer flag set to true, discount to false, sales items are empty (don't affect result)
  164. [
  165. ['transfer_shipping' => true, 'transfer_discount' => false],
  166. [],
  167. [
  168. 'BaseDiscountAmount' => 15.0,
  169. 'BaseShippingAmount' => 20.0,
  170. 'BaseSubtotal' => 100.0,
  171. 'BaseTaxAmount' => 8.0
  172. ],
  173. [
  174. Cart::AMOUNT_DISCOUNT => 15.0,
  175. Cart::AMOUNT_SHIPPING => 0.0,
  176. Cart::AMOUNT_SUBTOTAL => 120.0,
  177. Cart::AMOUNT_TAX => 8.0
  178. ]
  179. ]
  180. ];
  181. }
  182. /**
  183. * Return true if arrays of cart sales items are equal, false otherwise. Elements order not considered
  184. *
  185. * @param array $salesItemsA
  186. * @param array $salesItemsB
  187. * @return bool
  188. */
  189. protected function _compareSalesItems(array $salesItemsA, array $salesItemsB)
  190. {
  191. if (count($salesItemsA) != count($salesItemsB)) {
  192. return false;
  193. }
  194. $toStringCallback = function (&$item) {
  195. $item = $item->toString();
  196. };
  197. array_walk($salesItemsA, $toStringCallback);
  198. array_walk($salesItemsB, $toStringCallback);
  199. sort($salesItemsA);
  200. sort($salesItemsB);
  201. return implode('', $salesItemsA) == implode('', $salesItemsB);
  202. }
  203. /**
  204. * Collect sales model items and calculate amounts of sales model
  205. *
  206. * @param array $transferFlags
  207. * @param array $salesModelItems
  208. * @param array $salesModelAmounts
  209. * @return array Cart amounts
  210. */
  211. protected function _collectItemsAndAmounts($transferFlags, $salesModelItems, $salesModelAmounts)
  212. {
  213. if ($transferFlags['transfer_shipping']) {
  214. $this->_model->setTransferShippingAsItem();
  215. }
  216. if ($transferFlags['transfer_discount']) {
  217. $this->_model->setTransferDiscountAsItem();
  218. }
  219. $this->_eventManagerMock->expects(
  220. $this->once()
  221. )->method(
  222. 'dispatch'
  223. )->with(
  224. $this->equalTo('payment_cart_collect_items_and_amounts'),
  225. $this->equalTo(['cart' => $this->_model])
  226. );
  227. $this->_salesModelMock->expects(
  228. $this->once()
  229. )->method(
  230. 'getAllItems'
  231. )->will(
  232. $this->returnValue($salesModelItems)
  233. );
  234. foreach ($salesModelAmounts as $key => $value) {
  235. $this->_salesModelMock->expects($this->once())->method('get' . $key)->will($this->returnValue($value));
  236. }
  237. return $this->_model->getAmounts();
  238. }
  239. /**
  240. * Return sales model items
  241. *
  242. * @return array
  243. */
  244. protected function _getSalesModelItems()
  245. {
  246. $product = new \Magento\Framework\DataObject(['id' => '1']);
  247. return [
  248. new \Magento\Framework\DataObject(
  249. ['name' => 'name 1', 'qty' => 1, 'price' => 0.1, 'original_item' => $product]
  250. ),
  251. new \Magento\Framework\DataObject(
  252. ['name' => 'name 2', 'qty' => 2, 'price' => 1.2, 'original_item' => $product]
  253. ),
  254. new \Magento\Framework\DataObject(
  255. [
  256. 'parent_item' => 'parent item 3',
  257. 'name' => 'name 3',
  258. 'qty' => 3,
  259. 'price' => 2.3,
  260. 'original_item' => $product,
  261. ]
  262. )
  263. ];
  264. }
  265. /**
  266. * Convert sales model items to cart items
  267. *
  268. * @param array $salesModelItems
  269. * @return array
  270. */
  271. protected function _convertToCartItems(array $salesModelItems)
  272. {
  273. $result = [];
  274. foreach ($salesModelItems as $item) {
  275. if ($item->getParentItem()) {
  276. continue;
  277. }
  278. $result[] = new \Magento\Framework\DataObject(
  279. [
  280. 'name' => $item->getName(),
  281. 'qty' => $item->getQty(),
  282. 'amount' => $item->getPrice(),
  283. 'id' => $item->getOriginalItem()->getId(),
  284. ]
  285. );
  286. }
  287. return $result;
  288. }
  289. }