CreateTest.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Sales\Model\AdminOrder;
  7. use Magento\Backend\Model\Session\Quote as SessionQuote;
  8. use Magento\Customer\Api\AddressRepositoryInterface;
  9. use Magento\Customer\Api\CustomerRepositoryInterface;
  10. use Magento\Customer\Model\Customer;
  11. use Magento\Customer\Model\CustomerRegistry;
  12. use Magento\Framework\Message\ManagerInterface;
  13. use Magento\Framework\Registry;
  14. use Magento\Quote\Model\Quote;
  15. use Magento\Sales\Api\Data\OrderAddressExtensionInterface;
  16. use Magento\Sales\Api\Data\OrderAddressExtensionInterfaceFactory;
  17. use Magento\Sales\Api\OrderManagementInterface;
  18. use Magento\Sales\Model\Order;
  19. use Magento\TestFramework\Helper\Bootstrap;
  20. use Magento\TestFramework\ObjectManager;
  21. /**
  22. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  23. * @magentoAppArea adminhtml
  24. * @magentoAppIsolation enabled
  25. */
  26. class CreateTest extends \PHPUnit\Framework\TestCase
  27. {
  28. /**
  29. * @var Create
  30. */
  31. private $model;
  32. /**
  33. * @var ManagerInterface
  34. */
  35. private $messageManager;
  36. /**
  37. * @var ObjectManager
  38. */
  39. private $objectManager;
  40. protected function setUp()
  41. {
  42. $this->objectManager = Bootstrap::getObjectManager();
  43. $this->messageManager = $this->objectManager->get(ManagerInterface::class);
  44. $this->model =$this->objectManager->create(Create::class, ['messageManager' => $this->messageManager]);
  45. }
  46. /**
  47. * @magentoDataFixture Magento/Downloadable/_files/product_downloadable.php
  48. * @magentoDataFixture Magento/Downloadable/_files/order_with_downloadable_product.php
  49. * @magentoDbIsolation disabled
  50. */
  51. public function testInitFromOrderShippingAddressSameAsBillingWhenEmpty()
  52. {
  53. /** @var $order Order */
  54. $order = $this->objectManager->create(Order::class);
  55. $order->loadByIncrementId('100000001');
  56. self::assertNull($order->getShippingAddress());
  57. $this->objectManager->get(Registry::class)->unregister('rule_data');
  58. $this->model->initFromOrder($order);
  59. self::assertNull($order->getShippingAddress());
  60. }
  61. /**
  62. * @magentoDataFixture Magento/Customer/_files/customer.php
  63. * @magentoDataFixture Magento/Downloadable/_files/product_downloadable.php
  64. * @magentoDataFixture Magento/Downloadable/_files/order_with_downloadable_product_with_additional_options.php
  65. * @magentoDbIsolation disabled
  66. * @magentoAppIsolation enabled
  67. */
  68. public function testInitFromOrderAndCreateOrderFromQuoteWithAdditionalOptions()
  69. {
  70. /** @var $serializer \Magento\Framework\Serialize\Serializer\Json */
  71. $serializer = $this->objectManager->create(\Magento\Framework\Serialize\Serializer\Json::class);
  72. /** @var $order Order */
  73. $order = $this->objectManager->create(Order::class);
  74. $order->loadByIncrementId('100000001');
  75. /** @var $orderCreate \Magento\Sales\Model\AdminOrder\Create */
  76. $orderCreate = $this->model->initFromOrder($order);
  77. $quoteItems = $orderCreate->getQuote()->getItemsCollection();
  78. self::assertEquals(1, $quoteItems->count());
  79. $quoteItem = $quoteItems->getFirstItem();
  80. $quoteItemOptions = $quoteItem->getOptionsByCode();
  81. self::assertEquals(
  82. $serializer->serialize(['additional_option_key' => 'additional_option_value']),
  83. $quoteItemOptions['additional_options']->getValue()
  84. );
  85. $session = $this->objectManager->get(SessionQuote::class);
  86. $session->setCustomerId(1);
  87. $customer = $this->objectManager->create(Customer::class);
  88. $customer->load(1)->setDefaultBilling(null)->setDefaultShipping(null)->save();
  89. $rate = $this->objectManager->create(Quote\Address\Rate::class);
  90. $rate->setCode('freeshipping_freeshipping');
  91. $this->model->getQuote()->getShippingAddress()->addShippingRate($rate);
  92. $this->model->getQuote()->getShippingAddress()->setCountryId('EE');
  93. $this->model->setShippingAsBilling(0);
  94. $this->model->setPaymentData(['method' => 'checkmo']);
  95. $newOrder = $this->model->createOrder();
  96. $newOrderItems = $newOrder->getItemsCollection();
  97. self::assertEquals(1, $newOrderItems->count());
  98. $order->loadByIncrementId('100000001');
  99. $this->assertEquals($newOrder->getRealOrderId(), $order->getRelationChildRealId());
  100. $this->assertEquals($newOrder->getId(), $order->getRelationChildId());
  101. $newOrderItem = $newOrderItems->getFirstItem();
  102. self::assertEquals(
  103. ['additional_option_key' => 'additional_option_value'],
  104. $newOrderItem->getProductOptionByCode('additional_options')
  105. );
  106. }
  107. /**
  108. * @magentoDataFixture Magento/Downloadable/_files/product_downloadable.php
  109. * @magentoDataFixture Magento/Downloadable/_files/order_with_downloadable_product.php
  110. * @magentoDataFixture Magento/Sales/_files/order_shipping_address_same_as_billing.php
  111. * @magentoDbIsolation disabled
  112. */
  113. public function testInitFromOrderShippingAddressSameAsBillingWhenSame()
  114. {
  115. /** @var $order Order */
  116. $order = $this->objectManager->create(Order::class);
  117. $order->loadByIncrementId('100000001');
  118. self::assertNull($order->getShippingAddress()->getSameAsBilling());
  119. /** @var OrderAddressExtensionInterface $shippingExtAttributes */
  120. $shippingExtAttributes = $this->objectManager->get(OrderAddressExtensionInterfaceFactory::class)
  121. ->create();
  122. $billingExtAttributes = clone $shippingExtAttributes;
  123. $shippingExtAttributes->setData('tmp', false);
  124. $billingExtAttributes->setData('tmp', true);
  125. $order->getShippingAddress()->setExtensionAttributes($shippingExtAttributes);
  126. $order->getBillingAddress()->setExtensionAttributes($billingExtAttributes);
  127. $this->objectManager->get(Registry::class)->unregister('rule_data');
  128. $this->model->initFromOrder($order);
  129. self::assertTrue($order->getShippingAddress()->getSameAsBilling());
  130. }
  131. /**
  132. * @magentoDataFixture Magento/Downloadable/_files/product_downloadable.php
  133. * @magentoDataFixture Magento/Downloadable/_files/order_with_downloadable_product.php
  134. * @magentoDataFixture Magento/Sales/_files/order_shipping_address_different_to_billing.php
  135. * @magentoDbIsolation disabled
  136. */
  137. public function testInitFromOrderShippingAddressSameAsBillingWhenDifferent()
  138. {
  139. /** @var $order Order */
  140. $order = $this->objectManager->create(Order::class);
  141. $order->loadByIncrementId('100000002');
  142. self::assertNull($order->getShippingAddress()->getSameAsBilling());
  143. $this->objectManager->get(Registry::class)->unregister('rule_data');
  144. $this->model->initFromOrder($order);
  145. self::assertFalse($order->getShippingAddress()->getSameAsBilling());
  146. }
  147. /**
  148. * @magentoDataFixture Magento/Sales/_files/order_paid_with_payflowpro.php
  149. * @magentoDbIsolation disabled
  150. */
  151. public function testInitFromOrderCcInformationDeleted()
  152. {
  153. /** @var $order Order */
  154. $order = $this->objectManager->create(Order::class);
  155. $order->loadByIncrementId('100000001');
  156. $payment = $order->getPayment();
  157. self::assertEquals('5', $payment->getCcExpMonth());
  158. self::assertEquals('2016', $payment->getCcExpYear());
  159. self::assertEquals('AE', $payment->getCcType());
  160. self::assertEquals('0005', $payment->getCcLast4());
  161. $this->objectManager->get(Registry::class)->unregister('rule_data');
  162. $payment = $this->model->initFromOrder($order)->getQuote()->getPayment();
  163. self::assertNull($payment->getCcExpMonth());
  164. self::assertNull($payment->getCcExpYear());
  165. self::assertNull($payment->getCcType());
  166. self::assertNull($payment->getCcLast4());
  167. }
  168. /**
  169. * @magentoDataFixture Magento/Sales/_files/order.php
  170. * @magentoDbIsolation disabled
  171. */
  172. public function testInitFromOrderWithEmptyPaymentDetails()
  173. {
  174. /** @var $order Order */
  175. $order = $this->objectManager->create(Order::class);
  176. $order->loadByIncrementId('100000001');
  177. $this->objectManager->get(Registry::class)
  178. ->unregister('rule_data');
  179. $initOrder = $this->model->initFromOrder($order);
  180. $payment = $initOrder->getQuote()->getPayment();
  181. self::assertEquals($initOrder->getQuote()->getId(), $payment->getData('quote_id'));
  182. $payment->unsetData('quote_id');
  183. self::assertEmpty($payment->getMethod());
  184. self::assertEmpty($payment->getAdditionalInformation());
  185. self::assertEmpty($payment->getAdditionalData());
  186. self::assertEmpty($payment->getData());
  187. }
  188. /**
  189. * @magentoAppIsolation enabled
  190. */
  191. public function testGetCustomerWishlistNoCustomerId()
  192. {
  193. /** @var SessionQuote $session */
  194. $session = $this->objectManager->create(SessionQuote::class);
  195. $session->setCustomerId(null);
  196. self::assertFalse(
  197. $this->model->getCustomerWishlist(true),
  198. 'If customer ID is not set to session, false is expected to be returned.'
  199. );
  200. }
  201. /**
  202. * @magentoDataFixture Magento/Customer/_files/customer.php
  203. * @magentoDataFixture Magento/Catalog/_files/product_simple.php
  204. * @magentoAppIsolation enabled
  205. */
  206. public function testGetCustomerWishlist()
  207. {
  208. $customerIdFromFixture = 1;
  209. $productIdFromFixture = 1;
  210. /** @var SessionQuote $session */
  211. $session = $this->objectManager->create(SessionQuote::class);
  212. $session->setCustomerId($customerIdFromFixture);
  213. /** Test new wishlist creation for the customer specified above */
  214. /** @var \Magento\Wishlist\Model\Wishlist $wishlist */
  215. $wishlist = $this->model->getCustomerWishlist(true);
  216. self::assertInstanceOf(
  217. \Magento\Wishlist\Model\Wishlist::class,
  218. $wishlist,
  219. 'New Wish List is expected to be created if existing Customer does not have one yet.'
  220. );
  221. self::assertEquals(0, $wishlist->getItemsCount(), 'New Wish List must be empty just after creation.');
  222. /** Add new item to wishlist and try to get it using getCustomerWishlist once again */
  223. $wishlist->addNewItem($productIdFromFixture)->save();
  224. $updatedWishlist = $this->model->getCustomerWishlist(true);
  225. self::assertEquals(
  226. 1,
  227. $updatedWishlist->getItemsCount(),
  228. 'Wish List must contain a Product which was added to it earlier.'
  229. );
  230. /** Try to load wishlist from cache in the class after it is deleted from DB */
  231. $wishlist->delete();
  232. self::assertSame(
  233. $updatedWishlist,
  234. $this->model->getCustomerWishlist(false),
  235. 'Wish List cached in class variable is expected to be returned.'
  236. );
  237. self::assertNotSame(
  238. $updatedWishlist,
  239. $this->model->getCustomerWishlist(true),
  240. 'New Wish List is expected to be created when cache is forced to be refreshed.'
  241. );
  242. }
  243. /**
  244. * @magentoDbIsolation enabled
  245. */
  246. public function testSetBillingAddress()
  247. {
  248. $addressData = $this->getValidAddressData();
  249. /** Validate data before creating address object */
  250. $this->model->setIsValidate(true)->setBillingAddress($addressData);
  251. self::assertInstanceOf(
  252. Quote\Address::class,
  253. $this->model->getBillingAddress(),
  254. 'Billing address object was not created.'
  255. );
  256. $expectedAddressData = array_merge(
  257. $addressData,
  258. [
  259. 'address_type' => 'billing',
  260. 'quote_id' => $this->model->getQuote()->getId(),
  261. 'street' => "Line1\nLine2",
  262. 'save_in_address_book' => 0,
  263. 'region' => '',
  264. 'region_id' => 1,
  265. ]
  266. );
  267. $result = $this->model->getBillingAddress()->getData();
  268. foreach ($expectedAddressData as $key => $value) {
  269. self::assertArrayHasKey($key, $result);
  270. self::assertEquals($value, $result[$key]);
  271. }
  272. }
  273. /**
  274. * @magentoDataFixture Magento/Customer/_files/customer.php
  275. * @magentoDbIsolation disabled
  276. */
  277. public function testSetBillingAddressValidationErrors()
  278. {
  279. $customerIdFromFixture = 1;
  280. /** @var SessionQuote $session */
  281. $session = $this->objectManager->create(SessionQuote::class);
  282. $session->setCustomerId($customerIdFromFixture);
  283. $invalidAddressData = array_merge($this->getValidAddressData(), ['firstname' => '', 'lastname' => '']);
  284. /**
  285. * Note that validation errors are collected during setBillingAddress() call in the internal class variable,
  286. * but they are not set to message manager at this step.
  287. * They are set to message manager only during createOrder() call.
  288. */
  289. $this->model->setIsValidate(true)->setBillingAddress($invalidAddressData);
  290. try {
  291. $this->model->createOrder();
  292. $this->fail('Validation errors are expected to lead to exception during createOrder() call.');
  293. } catch (\Magento\Framework\Exception\LocalizedException $e) {
  294. /** createOrder is expected to throw exception with empty message when validation error occurs */
  295. }
  296. $errorMessages = [];
  297. /** @var $validationError \Magento\Framework\Message\Error */
  298. foreach ($this->messageManager->getMessages()->getItems() as $validationError) {
  299. $errorMessages[] = $validationError->getText();
  300. }
  301. self::assertTrue(
  302. in_array('Billing Address: "First Name" is a required value.', $errorMessages),
  303. 'Expected validation message is absent.'
  304. );
  305. self::assertTrue(
  306. in_array('Billing Address: "Last Name" is a required value.', $errorMessages),
  307. 'Expected validation message is absent.'
  308. );
  309. }
  310. /**
  311. * @magentoDataFixture Magento/Catalog/_files/product_simple.php
  312. * @magentoAppIsolation enabled
  313. */
  314. public function testCreateOrderNewCustomerDifferentAddresses()
  315. {
  316. $productIdFromFixture = 1;
  317. $shippingMethod = 'freeshipping_freeshipping';
  318. $paymentMethod = 'checkmo';
  319. $shippingAddressAsBilling = 0;
  320. $customerEmail = 'new_customer@example.com';
  321. $firstNameForShippingAddress = 'FirstNameForShipping';
  322. $orderData = [
  323. 'currency' => 'USD',
  324. 'account' => ['group_id' => '1', 'email' => $customerEmail],
  325. 'billing_address' => array_merge($this->getValidAddressData(), ['save_in_address_book' => '1']),
  326. 'shipping_address' => array_merge(
  327. $this->getValidAddressData(),
  328. ['save_in_address_book' => '1', 'firstname' => $firstNameForShippingAddress]
  329. ),
  330. 'shipping_method' => $shippingMethod,
  331. 'comment' => ['customer_note' => ''],
  332. 'send_confirmation' => true,
  333. ];
  334. $paymentData = ['method' => $paymentMethod];
  335. $this->preparePreconditionsForCreateOrder(
  336. $productIdFromFixture,
  337. $customerEmail,
  338. $shippingMethod,
  339. $shippingAddressAsBilling,
  340. $paymentData,
  341. $orderData,
  342. $paymentMethod
  343. );
  344. $order = $this->model->createOrder();
  345. $this->verifyCreatedOrder($order, $shippingMethod);
  346. /** @var Customer $customer */
  347. $customer = $this->objectManager->create(Customer::class);
  348. $customer->load($order->getCustomerId());
  349. self::assertEquals(
  350. $firstNameForShippingAddress,
  351. $customer->getPrimaryShippingAddress()->getFirstname(),
  352. 'Shipping address is saved incorrectly.'
  353. );
  354. }
  355. /**
  356. * @magentoDataFixture Magento/Catalog/_files/product_simple_with_decimal_qty.php
  357. * @magentoDbIsolation disabled
  358. * @magentoAppIsolation enabled
  359. */
  360. public function testCreateOrderNewCustomer()
  361. {
  362. $productIdFromFixture = 1;
  363. $shippingMethod = 'freeshipping_freeshipping';
  364. $paymentMethod = 'checkmo';
  365. $shippingAddressAsBilling = 1;
  366. $customerEmail = 'new_customer@example.com';
  367. $orderData = [
  368. 'currency' => 'USD',
  369. 'account' => ['group_id' => '1', 'email' => $customerEmail],
  370. 'billing_address' => array_merge($this->getValidAddressData(), ['save_in_address_book' => '1']),
  371. 'shipping_method' => $shippingMethod,
  372. 'comment' => ['customer_note' => ''],
  373. 'send_confirmation' => false,
  374. ];
  375. $paymentData = ['method' => $paymentMethod];
  376. $this->preparePreconditionsForCreateOrder(
  377. $productIdFromFixture,
  378. $customerEmail,
  379. $shippingMethod,
  380. $shippingAddressAsBilling,
  381. $paymentData,
  382. $orderData,
  383. $paymentMethod
  384. );
  385. $order = $this->model->createOrder();
  386. //Check, order considering decimal qty in product.
  387. foreach ($order->getItems() as $orderItem) {
  388. self::assertTrue($orderItem->getIsQtyDecimal());
  389. }
  390. $this->verifyCreatedOrder($order, $shippingMethod);
  391. }
  392. /**
  393. * Tests order creation with new customer after failed first place order action.
  394. *
  395. * @magentoDataFixture Magento/Catalog/_files/product_simple.php
  396. * @magentoDbIsolation disabled
  397. * @magentoAppIsolation enabled
  398. * @dataProvider createOrderNewCustomerWithFailedFirstPlaceOrderActionDataProvider
  399. * @param string $customerEmailFirstAttempt
  400. * @param string $customerEmailSecondAttempt
  401. */
  402. public function testCreateOrderNewCustomerWithFailedFirstPlaceOrderAction(
  403. $customerEmailFirstAttempt,
  404. $customerEmailSecondAttempt
  405. ) {
  406. $productIdFromFixture = 1;
  407. $shippingMethod = 'freeshipping_freeshipping';
  408. $paymentMethod = 'checkmo';
  409. $shippingAddressAsBilling = 1;
  410. $customerEmail = $customerEmailFirstAttempt;
  411. $orderData = [
  412. 'currency' => 'USD',
  413. 'account' => ['group_id' => '1', 'email' => $customerEmail],
  414. 'billing_address' => array_merge($this->getValidAddressData(), ['save_in_address_book' => '1']),
  415. 'shipping_method' => $shippingMethod,
  416. 'comment' => ['customer_note' => ''],
  417. 'send_confirmation' => false,
  418. ];
  419. $paymentData = ['method' => $paymentMethod];
  420. $this->preparePreconditionsForCreateOrder(
  421. $productIdFromFixture,
  422. $customerEmail,
  423. $shippingMethod,
  424. $shippingAddressAsBilling,
  425. $paymentData,
  426. $orderData,
  427. $paymentMethod
  428. );
  429. // Emulates failing place order action
  430. $orderManagement = $this->getMockForAbstractClass(OrderManagementInterface::class);
  431. $orderManagement->method('place')
  432. ->willThrowException(new \Exception('Can\'t place order'));
  433. $this->objectManager->addSharedInstance($orderManagement, OrderManagementInterface::class);
  434. try {
  435. $this->model->createOrder();
  436. } catch (\Exception $e) {
  437. $this->objectManager->removeSharedInstance(OrderManagementInterface::class);
  438. }
  439. $customerEmail = $customerEmailSecondAttempt ? :$this->model->getQuote()->getCustomer()->getEmail();
  440. $orderData['account']['email'] = $customerEmailSecondAttempt;
  441. $this->preparePreconditionsForCreateOrder(
  442. $productIdFromFixture,
  443. $customerEmail,
  444. $shippingMethod,
  445. $shippingAddressAsBilling,
  446. $paymentData,
  447. $orderData,
  448. $paymentMethod
  449. );
  450. $order = $this->model->createOrder();
  451. $this->verifyCreatedOrder($order, $shippingMethod);
  452. }
  453. /**
  454. * Email before and after failed first place order action.
  455. *
  456. * @case #1 Is the same.
  457. * @case #2 Changed after failed first place order action.
  458. * @return array
  459. */
  460. public function createOrderNewCustomerWithFailedFirstPlaceOrderActionDataProvider()
  461. {
  462. return [
  463. 1 => ['customer@email.com', 'customer@email.com'],
  464. 2 => ['customer@email.com', 'changed_customer@email.com'],
  465. ];
  466. }
  467. /**
  468. * @magentoDataFixture Magento/Catalog/_files/product_simple.php
  469. * @magentoDataFixture Magento/Customer/_files/customer.php
  470. * @magentoDbIsolation disabled
  471. * @magentoAppIsolation enabled
  472. */
  473. public function testCreateOrderExistingCustomerDifferentAddresses()
  474. {
  475. $productIdFromFixture = 1;
  476. $customerIdFromFixture = 1;
  477. $customerEmailFromFixture = 'customer@example.com';
  478. $shippingMethod = 'freeshipping_freeshipping';
  479. $paymentMethod = 'checkmo';
  480. $shippingAddressAsBilling = 0;
  481. $firstNameForShippingAddress = 'FirstNameForShipping';
  482. $orderData = [
  483. 'currency' => 'USD',
  484. 'billing_address' => array_merge($this->getValidAddressData(), ['save_in_address_book' => '1']),
  485. 'shipping_address' => array_merge(
  486. $this->getValidAddressData(),
  487. ['save_in_address_book' => '1', 'firstname' => $firstNameForShippingAddress]
  488. ),
  489. 'shipping_method' => $shippingMethod,
  490. 'comment' => ['customer_note' => ''],
  491. 'send_confirmation' => false,
  492. ];
  493. $paymentData = ['method' => $paymentMethod];
  494. $this->preparePreconditionsForCreateOrder(
  495. $productIdFromFixture,
  496. $customerEmailFromFixture,
  497. $shippingMethod,
  498. $shippingAddressAsBilling,
  499. $paymentData,
  500. $orderData,
  501. $paymentMethod,
  502. $customerIdFromFixture
  503. );
  504. $order = $this->model->createOrder();
  505. $this->verifyCreatedOrder($order, $shippingMethod);
  506. $this->objectManager->get(CustomerRegistry::class)
  507. ->remove($order->getCustomerId());
  508. $customer = $this->objectManager->get(CustomerRepositoryInterface::class)
  509. ->getById($order->getCustomerId());
  510. $address = $this->objectManager->get(AddressRepositoryInterface::class)
  511. ->getById($customer->getDefaultShipping());
  512. self::assertEquals(
  513. $firstNameForShippingAddress,
  514. $address->getFirstname(),
  515. 'Shipping address is saved incorrectly.'
  516. );
  517. }
  518. /**
  519. * @magentoDataFixture Magento/Catalog/_files/product_simple.php
  520. * @magentoDataFixture Magento/Customer/_files/customer.php
  521. * @magentoDbIsolation disabled
  522. * @magentoAppIsolation enabled
  523. */
  524. public function testCreateOrderExistingCustomer()
  525. {
  526. $productIdFromFixture = 1;
  527. $customerIdFromFixture = 1;
  528. $customerEmailFromFixture = 'customer@example.com';
  529. $shippingMethod = 'freeshipping_freeshipping';
  530. $paymentMethod = 'checkmo';
  531. $shippingAddressAsBilling = 1;
  532. $orderData = [
  533. 'currency' => 'USD',
  534. 'billing_address' => array_merge($this->getValidAddressData(), ['save_in_address_book' => '1']),
  535. 'shipping_method' => $shippingMethod,
  536. 'comment' => ['customer_note' => ''],
  537. 'send_confirmation' => false,
  538. ];
  539. $paymentData = ['method' => $paymentMethod];
  540. $this->preparePreconditionsForCreateOrder(
  541. $productIdFromFixture,
  542. $customerEmailFromFixture,
  543. $shippingMethod,
  544. $shippingAddressAsBilling,
  545. $paymentData,
  546. $orderData,
  547. $paymentMethod,
  548. $customerIdFromFixture
  549. );
  550. $order = $this->model->createOrder();
  551. $this->verifyCreatedOrder($order, $shippingMethod);
  552. }
  553. /**
  554. * @magentoDataFixture Magento/Sales/_files/quote.php
  555. * @magentoDataFixture Magento/Customer/_files/customer.php
  556. * @magentoAppIsolation enabled
  557. * @magentoDbIsolation disabled
  558. */
  559. public function testGetCustomerCartExistingCart()
  560. {
  561. $fixtureCustomerId = 1;
  562. /** Preconditions */
  563. /** @var SessionQuote $session */
  564. $session = $this->objectManager->create(SessionQuote::class);
  565. $session->setCustomerId($fixtureCustomerId);
  566. /** @var $quoteFixture Quote */
  567. $quoteFixture = $this->objectManager->create(Quote::class);
  568. $quoteFixture->load('test01', 'reserved_order_id');
  569. $quoteFixture->setCustomerIsGuest(false)->setCustomerId($fixtureCustomerId)->save();
  570. /** SUT execution */
  571. $customerQuote = $this->model->getCustomerCart();
  572. self::assertEquals($quoteFixture->getId(), $customerQuote->getId(), 'Quote ID is invalid.');
  573. /** Try to load quote once again to ensure that caching works correctly */
  574. $customerQuoteFromCache = $this->model->getCustomerCart();
  575. self::assertSame($customerQuote, $customerQuoteFromCache, 'Customer quote caching does not work correctly.');
  576. }
  577. /**
  578. * @magentoDataFixture Magento/Sales/_files/quote.php
  579. * @magentoDataFixture Magento/Customer/_files/customer.php
  580. * @magentoAppIsolation enabled
  581. * @magentoDbIsolation disabled
  582. */
  583. public function testMoveQuoteItemToCart()
  584. {
  585. $fixtureCustomerId = 1;
  586. /** Preconditions */
  587. /** @var SessionQuote $session */
  588. $session = $this->objectManager->create(SessionQuote::class);
  589. $session->setCustomerId($fixtureCustomerId);
  590. /** @var $quoteFixture Quote */
  591. $quoteFixture = $this->objectManager->create(Quote::class);
  592. $quoteFixture->load('test01', 'reserved_order_id');
  593. $quoteFixture->setCustomerIsGuest(false)->setCustomerId($fixtureCustomerId)->save();
  594. $customerQuote = $this->model->getCustomerCart();
  595. $item = $customerQuote->getAllVisibleItems()[0];
  596. $this->model->moveQuoteItem($item, 'cart', 3);
  597. self::assertEquals(4, $item->getQty(), 'Number of Qty isn\'t correct for Quote item.');
  598. self::assertEquals(3, $item->getQtyToAdd(), 'Number of added qty isn\'t correct for Quote item.');
  599. }
  600. /**
  601. * @magentoAppIsolation enabled
  602. * @magentoDbIsolation disabled
  603. * @magentoDataFixture Magento/Customer/_files/customer.php
  604. */
  605. public function testGetCustomerCartNewCart()
  606. {
  607. $customerIdFromFixture = 1;
  608. $customerEmailFromFixture = 'customer@example.com';
  609. /** Preconditions */
  610. /** @var SessionQuote $session */
  611. $session = $this->objectManager->create(SessionQuote::class);
  612. $session->setCustomerId($customerIdFromFixture);
  613. /** SUT execution */
  614. $customerQuote = $this->model->getCustomerCart();
  615. self::assertNotEmpty($customerQuote->getId(), 'Quote ID is invalid.');
  616. self::assertEquals(
  617. $customerEmailFromFixture,
  618. $customerQuote->getCustomerEmail(),
  619. 'Customer data is preserved incorrectly in a newly quote.'
  620. );
  621. }
  622. /**
  623. * Prepare preconditions for createOrder method invocation.
  624. *
  625. * @param int $productIdFromFixture
  626. * @param string $customerEmail
  627. * @param string $shippingMethod
  628. * @param int $shippingAddressAsBilling
  629. * @param array $paymentData
  630. * @param array $orderData
  631. * @param string $paymentMethod
  632. * @param int|null $customerIdFromFixture
  633. */
  634. private function preparePreconditionsForCreateOrder(
  635. $productIdFromFixture,
  636. $customerEmail,
  637. $shippingMethod,
  638. $shippingAddressAsBilling,
  639. $paymentData,
  640. $orderData,
  641. $paymentMethod,
  642. $customerIdFromFixture = null
  643. ) {
  644. /** Disable product options */
  645. /** @var \Magento\Catalog\Model\Product $product */
  646. $product = $this->objectManager->create(\Magento\Catalog\Model\Product::class);
  647. $product->load($productIdFromFixture)->setHasOptions(false)->save();
  648. /** Set current customer */
  649. /** @var SessionQuote $session */
  650. $session = $this->objectManager->get(SessionQuote::class);
  651. if ($customerIdFromFixture !== null) {
  652. $session->setCustomerId($customerIdFromFixture);
  653. /** Unset fake IDs for default billing and shipping customer addresses */
  654. /** @var Customer $customer */
  655. $customer = $this->objectManager->create(Customer::class);
  656. $customer->load($customerIdFromFixture)->setDefaultBilling(null)->setDefaultShipping(null)->save();
  657. } else {
  658. /**
  659. * Customer ID must be set to session to pass \Magento\Sales\Model\AdminOrder\Create::_validate()
  660. * This code emulates order placement via admin panel.
  661. */
  662. $session->setCustomerId(0);
  663. }
  664. /** Emulate availability of shipping method (all are disabled by default) */
  665. /** @var $rate Quote\Address\Rate */
  666. $rate = $this->objectManager->create(Quote\Address\Rate::class);
  667. $rate->setCode($shippingMethod);
  668. $this->model->getQuote()->getShippingAddress()->addShippingRate($rate);
  669. $this->model->setShippingAsBilling($shippingAddressAsBilling);
  670. $this->model->addProduct($productIdFromFixture, ['qty' => 1]);
  671. $this->model->setPaymentData($paymentData);
  672. $this->model->setIsValidate(true)->importPostData($orderData);
  673. /** Check preconditions */
  674. self::assertEquals(
  675. 0,
  676. $this->messageManager->getMessages()->getCount(),
  677. "Precondition failed: Errors occurred before SUT execution."
  678. );
  679. /** Selectively check quote data */
  680. $createOrderData = $this->model->getData();
  681. self::assertEquals(
  682. $shippingMethod,
  683. $createOrderData['shipping_method'],
  684. 'Precondition failed: Shipping method specified in create order model is invalid'
  685. );
  686. self::assertEquals(
  687. 'FirstName',
  688. $createOrderData['billing_address']['firstname'],
  689. 'Precondition failed: Address data is invalid in create order model'
  690. );
  691. self::assertEquals(
  692. 'Simple Product',
  693. $this->model->getQuote()->getItemByProduct($product)->getData('name'),
  694. 'Precondition failed: Quote items data is invalid in create order model'
  695. );
  696. self::assertEquals(
  697. $customerEmail,
  698. $this->model->getQuote()->getCustomer()->getEmail(),
  699. 'Precondition failed: Customer data is invalid in create order model'
  700. );
  701. self::assertEquals(
  702. $paymentMethod,
  703. $this->model->getQuote()->getPayment()->getData('method'),
  704. 'Precondition failed: Payment method data is invalid in create order model'
  705. );
  706. }
  707. /**
  708. * Ensure that order is created correctly via createOrder().
  709. *
  710. * @param Order $order
  711. * @param string $shippingMethod
  712. */
  713. private function verifyCreatedOrder($order, $shippingMethod)
  714. {
  715. /** Selectively check order data */
  716. $orderData = $order->getData();
  717. self::assertNotEmpty($orderData['increment_id'], 'Order increment ID is empty.');
  718. self::assertEquals($this->model->getQuote()->getId(), $orderData['quote_id'], 'Quote ID is invalid.');
  719. self::assertEquals(
  720. $this->model->getQuote()->getCustomer()->getEmail(),
  721. $orderData['customer_email'],
  722. 'Customer email is invalid.'
  723. );
  724. self::assertEquals(
  725. $this->model->getQuote()->getCustomer()->getFirstname(),
  726. $orderData['customer_firstname'],
  727. 'Customer first name is invalid.'
  728. );
  729. self::assertEquals($shippingMethod, $orderData['shipping_method'], 'Shipping method is invalid.');
  730. }
  731. /**
  732. * Get valid address data for address creation.
  733. *
  734. * @return array
  735. */
  736. private function getValidAddressData()
  737. {
  738. return [
  739. 'prefix' => 'prefix',
  740. 'firstname' => 'FirstName',
  741. 'middlename' => 'MiddleName',
  742. 'lastname' => 'LastName',
  743. 'suffix' => 'suffix',
  744. 'company' => 'Company Name',
  745. 'street' => [0 => 'Line1', 1 => 'Line2'],
  746. 'city' => 'City',
  747. 'country_id' => 'US',
  748. 'region' => [
  749. 'region' => '',
  750. 'region_id' => '1',
  751. ],
  752. 'postcode' => '76868',
  753. 'telephone' => '+8709273498729384',
  754. 'fax' => '',
  755. 'vat_id' => ''
  756. ];
  757. }
  758. }