CheckoutTest.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Paypal\Model\Express;
  7. use Magento\Checkout\Model\Type\Onepage;
  8. use Magento\Framework\ObjectManagerInterface;
  9. use Magento\Paypal\Model\Api\Nvp;
  10. use Magento\Paypal\Model\Api\Type\Factory;
  11. use Magento\Paypal\Model\Config;
  12. use Magento\Paypal\Model\Info;
  13. use Magento\Quote\Model\Quote;
  14. use Magento\Quote\Model\Quote\Address;
  15. use Magento\Quote\Model\ResourceModel\Quote\Collection;
  16. use Magento\TestFramework\Helper\Bootstrap;
  17. /**
  18. * Class CheckoutTest
  19. *
  20. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  21. */
  22. class CheckoutTest extends \PHPUnit\Framework\TestCase
  23. {
  24. /**
  25. * @var ObjectManagerInterface
  26. */
  27. private $objectManager;
  28. /**
  29. * @var Info|\PHPUnit_Framework_MockObject_MockObject
  30. */
  31. private $paypalInfo;
  32. /**
  33. * @var Config|\PHPUnit_Framework_MockObject_MockObject
  34. */
  35. private $paypalConfig;
  36. /**
  37. * @var Factory|\PHPUnit_Framework_MockObject_MockObject
  38. */
  39. private $apiTypeFactory;
  40. /**
  41. * @var Nvp|\PHPUnit_Framework_MockObject_MockObject
  42. */
  43. private $api;
  44. /**
  45. * @var Checkout
  46. */
  47. private $checkoutModel;
  48. /**
  49. * Set up
  50. *
  51. * @return void
  52. */
  53. protected function setUp()
  54. {
  55. $this->objectManager = Bootstrap::getObjectManager();
  56. $this->paypalInfo = $this->getMockBuilder(Info::class)
  57. ->disableOriginalConstructor()
  58. ->getMock();
  59. $this->paypalConfig = $this->getMockBuilder(Config::class)
  60. ->disableOriginalConstructor()
  61. ->getMock();
  62. $this->api = $this->getMockBuilder(Nvp::class)
  63. ->disableOriginalConstructor()
  64. ->setMethods(['call', 'getExportedShippingAddress', 'getExportedBillingAddress'])
  65. ->getMock();
  66. $this->api->expects($this->any())
  67. ->method('call')
  68. ->will($this->returnValue([]));
  69. $this->apiTypeFactory = $this->getMockBuilder(Factory::class)
  70. ->disableOriginalConstructor()
  71. ->getMock();
  72. $this->apiTypeFactory->expects($this->any())
  73. ->method('create')
  74. ->will($this->returnValue($this->api));
  75. }
  76. /**
  77. * Verify that api has set customer email.
  78. *
  79. * @magentoDataFixture Magento/Paypal/_files/quote_express.php
  80. * @magentoAppIsolation enabled
  81. * @magentoDbIsolation enabled
  82. */
  83. public function testCheckoutStartWithBillingAddress()
  84. {
  85. $quote = $this->getFixtureQuote();
  86. $paypalConfig = $this->getMockBuilder(Config::class)
  87. ->disableOriginalConstructor()
  88. ->getMock();
  89. $apiTypeFactory = $this->getMockBuilder(Factory::class)
  90. ->disableOriginalConstructor()
  91. ->setMethods(['create'])
  92. ->getMock();
  93. $paypalInfo = $this->getMockBuilder(Info::class)
  94. ->disableOriginalConstructor()
  95. ->getMock();
  96. $checkoutModel = $this->objectManager->create(
  97. Checkout::class,
  98. [
  99. 'params' => ['quote' => $quote, 'config' => $paypalConfig],
  100. 'apiTypeFactory' => $apiTypeFactory,
  101. 'paypalInfo' => $paypalInfo
  102. ]
  103. );
  104. $api = $this->getMockBuilder(Nvp::class)
  105. ->disableOriginalConstructor()
  106. ->setMethods(['callSetExpressCheckout'])
  107. ->getMock();
  108. $api->expects($this->any())
  109. ->method('callSetExpressCheckout')
  110. ->will($this->returnValue(null));
  111. $apiTypeFactory->expects($this->any())
  112. ->method('create')
  113. ->will($this->returnValue($api));
  114. $checkoutModel->start(
  115. 'return',
  116. 'cancel',
  117. false
  118. );
  119. $this->assertEquals('test@com.com', $api->getBillingAddress()->getEmail());
  120. }
  121. /**
  122. * Verify that an order placed with an existing customer can re-use the customer addresses.
  123. *
  124. * @magentoDataFixture Magento/Paypal/_files/quote_express_with_customer.php
  125. * @magentoAppIsolation enabled
  126. * @magentoDbIsolation enabled
  127. */
  128. public function testPrepareCustomerQuote()
  129. {
  130. /** @var Quote $quote */
  131. $quote = $this->getFixtureQuote();
  132. $quote->setCheckoutMethod(Onepage::METHOD_CUSTOMER); // to dive into _prepareCustomerQuote() on switch
  133. $quote->getShippingAddress()->setSameAsBilling(0);
  134. $quote->setReservedOrderId(null);
  135. $customer = $this->objectManager->create(\Magento\Customer\Model\Customer::class)->load(1);
  136. $customer->setDefaultBilling(false)
  137. ->setDefaultShipping(false)
  138. ->save();
  139. /** @var \Magento\Customer\Model\Session $customerSession */
  140. $customerSession = $this->objectManager->get(\Magento\Customer\Model\Session::class);
  141. $customerSession->loginById(1);
  142. $checkout = $this->getCheckout($quote);
  143. $checkout->place('token');
  144. /** @var \Magento\Customer\Api\CustomerRepositoryInterface $customerService */
  145. $customerService = $this->objectManager->get(\Magento\Customer\Api\CustomerRepositoryInterface::class);
  146. $customer = $customerService->getById($quote->getCustomerId());
  147. $this->assertEquals(1, $quote->getCustomerId());
  148. $this->assertEquals(2, count($customer->getAddresses()));
  149. $this->assertEquals(1, $quote->getBillingAddress()->getCustomerAddressId());
  150. $this->assertEquals(2, $quote->getShippingAddress()->getCustomerAddressId());
  151. $order = $checkout->getOrder();
  152. $this->assertEquals(1, $order->getBillingAddress()->getCustomerAddressId());
  153. $this->assertEquals(2, $order->getShippingAddress()->getCustomerAddressId());
  154. }
  155. /**
  156. * Verify that after placing the order, addresses are associated with the order and the quote is a guest quote.
  157. *
  158. * @magentoDataFixture Magento/Paypal/_files/quote_express.php
  159. * @magentoAppIsolation enabled
  160. * @magentoDbIsolation enabled
  161. */
  162. public function testPlaceGuestQuote()
  163. {
  164. /** @var Quote $quote */
  165. $quote = $this->getFixtureQuote();
  166. $quote->setCheckoutMethod(Onepage::METHOD_GUEST); // to dive into _prepareGuestQuote() on switch
  167. $quote->getShippingAddress()->setSameAsBilling(0);
  168. $quote->setReservedOrderId(null);
  169. $checkout = $this->getCheckout($quote);
  170. $checkout->place('token');
  171. $this->assertNull($quote->getCustomerId());
  172. $this->assertTrue($quote->getCustomerIsGuest());
  173. $this->assertEquals(
  174. \Magento\Customer\Model\GroupManagement::NOT_LOGGED_IN_ID,
  175. $quote->getCustomerGroupId()
  176. );
  177. $this->assertNotEmpty($quote->getBillingAddress());
  178. $this->assertNotEmpty($quote->getShippingAddress());
  179. $order = $checkout->getOrder();
  180. $this->assertNotEmpty($order->getBillingAddress());
  181. $this->assertNotEmpty($order->getShippingAddress());
  182. }
  183. /**
  184. * @param Quote $quote
  185. * @return Checkout
  186. */
  187. protected function getCheckout(Quote $quote)
  188. {
  189. return $this->objectManager->create(
  190. Checkout::class,
  191. [
  192. 'params' => [
  193. 'config' => $this->getMockBuilder(Config::class)
  194. ->disableOriginalConstructor()
  195. ->getMock(),
  196. 'quote' => $quote,
  197. ]
  198. ]
  199. );
  200. }
  201. /**
  202. * Verify that an order placed with an existing customer can re-use the customer addresses.
  203. *
  204. * @magentoDataFixture Magento/Paypal/_files/quote_payment_express_with_customer.php
  205. * @magentoAppIsolation enabled
  206. * @magentoDbIsolation enabled
  207. */
  208. public function testReturnFromPaypal()
  209. {
  210. $quote = $this->getFixtureQuote();
  211. $this->checkoutModel = $this->objectManager->create(
  212. Checkout::class,
  213. [
  214. 'params' => ['quote' => $quote, 'config' => $this->paypalConfig],
  215. 'apiTypeFactory' => $this->apiTypeFactory,
  216. 'paypalInfo' => $this->paypalInfo
  217. ]
  218. );
  219. $prefix = 'exported';
  220. $exportedBillingAddress = $this->getExportedAddressFixture($quote->getBillingAddress()->getData(), $prefix);
  221. $this->api->expects($this->any())
  222. ->method('getExportedBillingAddress')
  223. ->will($this->returnValue($exportedBillingAddress));
  224. $exportedShippingAddress = $this->getExportedAddressFixture($quote->getShippingAddress()->getData(), $prefix);
  225. $this->api->expects($this->any())
  226. ->method('getExportedShippingAddress')
  227. ->will($this->returnValue($exportedShippingAddress));
  228. $this->paypalInfo->expects($this->once())->method('importToPayment')->with($this->api, $quote->getPayment());
  229. $quote->getPayment()->setAdditionalInformation(Checkout::PAYMENT_INFO_BUTTON, 1);
  230. $this->checkoutModel->returnFromPaypal('token');
  231. $billingAddress = $quote->getBillingAddress();
  232. $this->assertContains($prefix, $billingAddress->getFirstname());
  233. $this->assertEquals('note', $billingAddress->getCustomerNote());
  234. $shippingAddress = $quote->getShippingAddress();
  235. $this->assertTrue((bool)$shippingAddress->getSameAsBilling());
  236. $this->assertNull($shippingAddress->getPrefix());
  237. $this->assertNull($shippingAddress->getMiddlename());
  238. $this->assertNull($shippingAddress->getLastname());
  239. $this->assertNull($shippingAddress->getSuffix());
  240. $this->assertTrue($shippingAddress->getShouldIgnoreValidation());
  241. $this->assertContains('exported', $shippingAddress->getFirstname());
  242. $paymentAdditionalInformation = $quote->getPayment()->getAdditionalInformation();
  243. $this->assertArrayHasKey(Checkout::PAYMENT_INFO_TRANSPORT_SHIPPING_METHOD, $paymentAdditionalInformation);
  244. $this->assertArrayHasKey(Checkout::PAYMENT_INFO_TRANSPORT_PAYER_ID, $paymentAdditionalInformation);
  245. $this->assertArrayHasKey(Checkout::PAYMENT_INFO_TRANSPORT_TOKEN, $paymentAdditionalInformation);
  246. $this->assertTrue($quote->getPayment()->hasMethod());
  247. $this->assertTrue($quote->getTotalsCollectedFlag());
  248. }
  249. /**
  250. * The case when handling address data from Paypal button.
  251. * System's address fields are replacing from export Paypal data.
  252. * Billing and Shipping address are the same
  253. *
  254. * @magentoDataFixture Magento/Paypal/_files/quote_payment_express_with_customer.php
  255. * @magentoAppIsolation enabled
  256. * @magentoDbIsolation enabled
  257. */
  258. public function testReturnFromPaypalButton()
  259. {
  260. $quote = $this->getFixtureQuote();
  261. $this->prepareCheckoutModel($quote);
  262. $quote->getPayment()->setAdditionalInformation(Checkout::PAYMENT_INFO_BUTTON, 1);
  263. $this->checkoutModel->returnFromPaypal('token');
  264. $shippingAddress = $quote->getShippingAddress();
  265. $billingAddress = $quote->getBillingAddress();
  266. $exportedShippingData = $this->getExportedData()['shipping'];
  267. $this->assertEquals([$exportedShippingData['street']], $shippingAddress->getStreet());
  268. $this->assertEquals($exportedShippingData['firstname'], $shippingAddress->getFirstname());
  269. $this->assertEquals($exportedShippingData['city'], $shippingAddress->getCity());
  270. $this->assertEquals($exportedShippingData['telephone'], $shippingAddress->getTelephone());
  271. $this->assertEquals($exportedShippingData['email'], $shippingAddress->getEmail());
  272. $this->assertEquals([$exportedShippingData['street']], $billingAddress->getStreet());
  273. $this->assertEquals($exportedShippingData['firstname'], $billingAddress->getFirstname());
  274. $this->assertEquals($exportedShippingData['city'], $billingAddress->getCity());
  275. $this->assertEquals($exportedShippingData['telephone'], $billingAddress->getTelephone());
  276. $this->assertEquals($exportedShippingData['email'], $billingAddress->getEmail());
  277. }
  278. /**
  279. * The case when handling address data from Paypal button.
  280. * System's address fields are replacing from export Paypal data.
  281. * Billing and Shipping address are different
  282. *
  283. * @magentoDataFixture Magento/Paypal/_files/quote_payment_express_with_customer.php
  284. * @magentoAppIsolation enabled
  285. * @magentoDbIsolation enabled
  286. */
  287. public function testReturnFromPaypalButtonWithReturnBillingAddress()
  288. {
  289. $quote = $this->getFixtureQuote();
  290. $this->paypalConfig->expects($this->exactly(2))
  291. ->method('getValue')
  292. ->with('requireBillingAddress')
  293. ->willReturn(1);
  294. $this->prepareCheckoutModel($quote);
  295. $quote->getPayment()->setAdditionalInformation(Checkout::PAYMENT_INFO_BUTTON, 1);
  296. $this->checkoutModel->returnFromPaypal('token');
  297. $shippingAddress = $quote->getShippingAddress();
  298. $billingAddress = $quote->getBillingAddress();
  299. $exportedBillingData = $this->getExportedData()['billing'];
  300. $exportedShippingData = $this->getExportedData()['shipping'];
  301. $this->assertEquals([$exportedShippingData['street']], $shippingAddress->getStreet());
  302. $this->assertEquals($exportedShippingData['firstname'], $shippingAddress->getFirstname());
  303. $this->assertEquals($exportedShippingData['city'], $shippingAddress->getCity());
  304. $this->assertEquals($exportedShippingData['telephone'], $shippingAddress->getTelephone());
  305. $this->assertEquals($exportedShippingData['email'], $shippingAddress->getEmail());
  306. $this->assertEquals([$exportedBillingData['street']], $billingAddress->getStreet());
  307. $this->assertEquals($exportedBillingData['firstname'], $billingAddress->getFirstname());
  308. $this->assertEquals($exportedBillingData['city'], $billingAddress->getCity());
  309. $this->assertEquals($exportedBillingData['telephone'], $billingAddress->getTelephone());
  310. $this->assertEquals($exportedBillingData['email'], $billingAddress->getEmail());
  311. }
  312. /**
  313. * The case when handling address data from the checkout.
  314. * System's address fields are not replacing from export PayPal data.
  315. * Billing and Shipping address are the same
  316. *
  317. * @magentoDataFixture Magento/Paypal/_files/quote_payment_express_with_customer.php
  318. * @magentoAppIsolation enabled
  319. * @magentoDbIsolation enabled
  320. */
  321. public function testReturnFromPaypalIfCheckout()
  322. {
  323. $prefix = 'exported';
  324. $quote = $this->getFixtureQuote();
  325. $this->prepareCheckoutModel($quote, $prefix);
  326. $quote->getPayment()->setAdditionalInformation(Checkout::PAYMENT_INFO_BUTTON, 0);
  327. $originalShippingAddress = $quote->getShippingAddress();
  328. $originalBillingAddress = $quote->getBillingAddress();
  329. $this->checkoutModel->returnFromPaypal('token');
  330. $shippingAddress = $quote->getShippingAddress();
  331. $billingAddress = $quote->getBillingAddress();
  332. $this->assertEquals($originalShippingAddress->getStreet(), $shippingAddress->getStreet());
  333. $this->assertEquals($originalShippingAddress->getFirstname(), $shippingAddress->getFirstname());
  334. $this->assertEquals($originalShippingAddress->getCity(), $shippingAddress->getCity());
  335. $this->assertEquals($originalShippingAddress->getTelephone(), $shippingAddress->getTelephone());
  336. $this->assertEquals($originalBillingAddress->getStreet(), $billingAddress->getStreet());
  337. $this->assertEquals($originalBillingAddress->getFirstname(), $billingAddress->getFirstname());
  338. $this->assertEquals($originalBillingAddress->getCity(), $billingAddress->getCity());
  339. $this->assertEquals($originalBillingAddress->getTelephone(), $billingAddress->getTelephone());
  340. }
  341. /**
  342. * The case when handling address data from the checkout.
  343. * System's address fields are replacing billing address from export PayPal data.
  344. * Billing and Shipping address are different
  345. *
  346. * @magentoDataFixture Magento/Paypal/_files/quote_payment_express_with_customer.php
  347. * @magentoAppIsolation enabled
  348. * @magentoDbIsolation enabled
  349. */
  350. public function testReturnFromPaypalIfCheckoutWithReturnBillingAddress()
  351. {
  352. $prefix = 'exported';
  353. $quote = $this->getFixtureQuote();
  354. $this->paypalConfig->expects($this->exactly(2))
  355. ->method('getValue')
  356. ->with('requireBillingAddress')
  357. ->willReturn(1);
  358. $this->prepareCheckoutModel($quote, $prefix);
  359. $quote->getPayment()->setAdditionalInformation(Checkout::PAYMENT_INFO_BUTTON, 0);
  360. $originalShippingAddress = $quote->getShippingAddress();
  361. $this->checkoutModel->returnFromPaypal('token');
  362. $shippingAddress = $quote->getShippingAddress();
  363. $billingAddress = $quote->getBillingAddress();
  364. $exportedBillingData = $this->getExportedData()['billing'];
  365. $this->assertEquals($originalShippingAddress->getStreet(), $shippingAddress->getStreet());
  366. $this->assertEquals($originalShippingAddress->getFirstname(), $shippingAddress->getFirstname());
  367. $this->assertEquals($originalShippingAddress->getCity(), $shippingAddress->getCity());
  368. $this->assertEquals($originalShippingAddress->getTelephone(), $shippingAddress->getTelephone());
  369. $this->assertEquals([$prefix . $exportedBillingData['street']], $billingAddress->getStreet());
  370. $this->assertEquals($prefix . $exportedBillingData['firstname'], $billingAddress->getFirstname());
  371. $this->assertEquals($prefix . $exportedBillingData['city'], $billingAddress->getCity());
  372. $this->assertEquals($prefix . $exportedBillingData['telephone'], $billingAddress->getTelephone());
  373. }
  374. /**
  375. * Test case when customer doesn't have either billing or shipping addresses.
  376. * Customer add virtual product to quote and place order using PayPal Express method.
  377. * After return from PayPal quote billing address have to be updated by PayPal Express address.
  378. *
  379. * @magentoDataFixture Magento/Paypal/_files/virtual_quote_with_empty_billing_address.php
  380. * @magentoConfigFixture current_store payment/paypal_express/active 1
  381. * @magentoDbIsolation enabled
  382. *
  383. * @return void
  384. */
  385. public function testReturnFromPayPalForCustomerWithEmptyAddresses(): void
  386. {
  387. $quote = $this->getFixtureQuote();
  388. $this->prepareCheckoutModel($quote);
  389. $quote->getPayment()->setAdditionalInformation(Checkout::PAYMENT_INFO_BUTTON, 0);
  390. $this->checkoutModel->returnFromPaypal('token');
  391. $billingAddress = $quote->getBillingAddress();
  392. $this->performQuoteAddressAssertions($billingAddress, $this->getExportedData()['billing']);
  393. }
  394. /**
  395. * Test case when customer doesn't have either billing or shipping addresses.
  396. * Customer add virtual product to quote and place order using PayPal Express method.
  397. * Default store country is in PayPal Express allowed specific country list.
  398. *
  399. * @magentoDataFixture Magento/Paypal/_files/virtual_quote_with_empty_billing_address.php
  400. * @magentoConfigFixture current_store payment/paypal_express/active 1
  401. * @magentoConfigFixture current_store payment/paypal_express/allowspecific 1
  402. * @magentoConfigFixture current_store payment/paypal_express/specificcountry US,GB
  403. * @magentoConfigFixture current_store general/country/default US
  404. *
  405. * @magentoDbIsolation enabled
  406. *
  407. * @return void
  408. */
  409. public function testPaymentValidationWithAllowedSpecificCountry(): void
  410. {
  411. $quote = $this->getFixtureQuote();
  412. $this->prepareCheckoutModel($quote);
  413. $quote->getPayment()->getMethodInstance()->validate();
  414. }
  415. /**
  416. * Test case when customer doesn't have either billing or shipping addresses.
  417. * Customer add virtual product to quote and place order using PayPal Express method.
  418. * PayPal Express allowed specific country list doesn't contain default store country.
  419. *
  420. * @magentoDataFixture Magento/Paypal/_files/virtual_quote_with_empty_billing_address.php
  421. * @magentoConfigFixture current_store payment/paypal_express/active 1
  422. * @magentoConfigFixture current_store payment/paypal_express/allowspecific 1
  423. * @magentoConfigFixture current_store payment/paypal_express/specificcountry US,GB
  424. * @magentoConfigFixture current_store general/country/default CA
  425. *
  426. * @magentoDbIsolation enabled
  427. * @expectedException \Magento\Framework\Exception\LocalizedException
  428. * @expectedExceptionMessage You can't use the payment type you selected to make payments to the billing country.
  429. *
  430. * @return void
  431. */
  432. public function testPaymentValidationWithAllowedSpecificCountryNegative(): void
  433. {
  434. $quote = $this->getFixtureQuote();
  435. $this->prepareCheckoutModel($quote);
  436. $quote->getPayment()->getMethodInstance()->validate();
  437. }
  438. /**
  439. * Performs quote address assertions.
  440. *
  441. * @param Address $address
  442. * @param array $expected
  443. * @return void
  444. */
  445. private function performQuoteAddressAssertions(Address $address, array $expected): void
  446. {
  447. foreach ($expected as $key => $item) {
  448. $methodName = 'get' . ucfirst($key);
  449. if ($key === 'street') {
  450. $item = [$item];
  451. }
  452. $this->assertEquals($item, $address->$methodName(), 'The "'. $key . '" does not match.');
  453. }
  454. }
  455. /**
  456. * Initialize a checkout model mock.
  457. *
  458. * @param Quote $quote
  459. */
  460. private function prepareCheckoutModel(Quote $quote, $prefix = '')
  461. {
  462. $this->checkoutModel = $this->objectManager->create(
  463. Checkout::class,
  464. [
  465. 'params' => ['quote' => $quote, 'config' => $this->paypalConfig],
  466. 'apiTypeFactory' => $this->apiTypeFactory,
  467. 'paypalInfo' => $this->paypalInfo
  468. ]
  469. );
  470. $exportedBillingAddress = $this->getExportedAddressFixture($this->getExportedData()['billing'], $prefix);
  471. $this->api->method('getExportedBillingAddress')
  472. ->willReturn($exportedBillingAddress);
  473. $exportedShippingAddress = $this->getExportedAddressFixture($this->getExportedData()['shipping'], $prefix);
  474. $this->api->method('getExportedShippingAddress')
  475. ->willReturn($exportedShippingAddress);
  476. $this->paypalInfo->method('importToPayment')
  477. ->with($this->api, $quote->getPayment());
  478. }
  479. /**
  480. * A Paypal response stub.
  481. *
  482. * @return array
  483. */
  484. private function getExportedData(): array
  485. {
  486. return [
  487. 'shipping' => [
  488. 'email' => 'customer@example.com',
  489. 'firstname' => 'John',
  490. 'lastname' => 'Doe',
  491. 'country' => 'US',
  492. 'region' => 'Colorado',
  493. 'region_id' => '13',
  494. 'city' => 'Denver',
  495. 'street' => '66 Pearl St',
  496. 'postcode' => '80203',
  497. 'telephone' => '555-555-555'
  498. ],
  499. 'billing' => [
  500. 'email' => 'customer@example.com',
  501. 'firstname' => 'Jane',
  502. 'lastname' => 'Doe',
  503. 'country' => 'US',
  504. 'region' => 'Texas',
  505. 'region_id' => '13',
  506. 'city' => 'Austin',
  507. 'street' => '1100 Congress Ave',
  508. 'postcode' => '78701',
  509. 'telephone' => '555-555-555'
  510. ]
  511. ];
  512. }
  513. /**
  514. * Verify that guest customer quota has set type of checkout.
  515. *
  516. * @magentoDataFixture Magento/Paypal/_files/quote_payment_express.php
  517. * @magentoAppIsolation enabled
  518. * @magentoDbIsolation enabled
  519. */
  520. public function testGuestReturnFromPaypal()
  521. {
  522. $quote = $this->getFixtureQuote();
  523. $paypalConfig = $this->getMockBuilder(Config::class)
  524. ->disableOriginalConstructor()
  525. ->getMock();
  526. $apiTypeFactory = $this->getMockBuilder(Factory::class)
  527. ->disableOriginalConstructor()
  528. ->setMethods(['create'])
  529. ->getMock();
  530. $paypalInfo = $this->getMockBuilder(Info::class)
  531. ->disableOriginalConstructor()
  532. ->setMethods(['importToPayment'])
  533. ->getMock();
  534. $checkoutModel = $this->objectManager->create(
  535. Checkout::class,
  536. [
  537. 'params' => ['quote' => $quote, 'config' => $paypalConfig],
  538. 'apiTypeFactory' => $apiTypeFactory,
  539. 'paypalInfo' => $paypalInfo
  540. ]
  541. );
  542. $api = $this->getMockBuilder(Nvp::class)
  543. ->disableOriginalConstructor()
  544. ->setMethods(['call', 'getExportedShippingAddress', 'getExportedBillingAddress'])
  545. ->getMock();
  546. $api->expects($this->any())
  547. ->method('call')
  548. ->will($this->returnValue([]));
  549. $apiTypeFactory->expects($this->any())
  550. ->method('create')
  551. ->will($this->returnValue($api));
  552. $exportedBillingAddress = $this->getExportedAddressFixture($quote->getBillingAddress()->getData());
  553. $api->expects($this->any())
  554. ->method('getExportedBillingAddress')
  555. ->will($this->returnValue($exportedBillingAddress));
  556. $exportedShippingAddress = $this->getExportedAddressFixture($quote->getShippingAddress()->getData());
  557. $api->expects($this->any())
  558. ->method('getExportedShippingAddress')
  559. ->will($this->returnValue($exportedShippingAddress));
  560. $paypalInfo->expects($this->once())
  561. ->method('importToPayment')
  562. ->with($api, $quote->getPayment());
  563. $quote->getPayment()->setAdditionalInformation(Checkout::PAYMENT_INFO_BUTTON, 1);
  564. $checkoutModel->returnFromPaypal('token');
  565. $this->assertEquals(Onepage::METHOD_GUEST, $quote->getCheckoutMethod());
  566. }
  567. /**
  568. * Prepare fixture for exported address.
  569. *
  570. * @param array $addressData
  571. * @param string $prefix
  572. * @return \Magento\Framework\DataObject
  573. */
  574. private function getExportedAddressFixture(array $addressData, string $prefix = ''): \Magento\Framework\DataObject
  575. {
  576. $addressDataKeys = [
  577. 'country',
  578. 'firstname',
  579. 'lastname',
  580. 'street',
  581. 'city',
  582. 'telephone',
  583. 'postcode',
  584. 'region',
  585. 'region_id',
  586. 'email',
  587. ];
  588. $result = [];
  589. foreach ($addressDataKeys as $key) {
  590. if (isset($addressData[$key])) {
  591. $result[$key] = $prefix . $addressData[$key];
  592. }
  593. }
  594. $fixture = new \Magento\Framework\DataObject($result);
  595. $fixture->setExportedKeys($addressDataKeys);
  596. $fixture->setData('note', 'note');
  597. return $fixture;
  598. }
  599. /**
  600. * Gets quote.
  601. *
  602. * @return Quote
  603. */
  604. private function getFixtureQuote(): Quote
  605. {
  606. /** @var Collection $quoteCollection */
  607. $quoteCollection = $this->objectManager->create(Collection::class);
  608. return $quoteCollection->getLastItem();
  609. }
  610. }