PaymentInformationManagementTest.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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\Checkout\Api;
  8. use Braintree\Result\Error;
  9. use Magento\Braintree\Gateway\Http\Client\TransactionSale;
  10. use Magento\Braintree\Model\Ui\ConfigProvider;
  11. use Magento\Framework\Api\SearchCriteriaBuilder;
  12. use Magento\Framework\App\State;
  13. use Magento\Framework\App\Area;
  14. use Magento\Quote\Api\CartRepositoryInterface;
  15. use Magento\Quote\Api\Data\CartInterface;
  16. use Magento\Quote\Api\Data\PaymentInterface;
  17. use Magento\TestFramework\Helper\Bootstrap;
  18. use Magento\TestFramework\ObjectManager;
  19. use PHPUnit\Framework\TestCase;
  20. use PHPUnit_Framework_MockObject_MockObject as MockObject;
  21. /**
  22. * Class PaymentInformationManagementTest
  23. *
  24. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  25. */
  26. class PaymentInformationManagementTest extends TestCase
  27. {
  28. /**
  29. * @var ObjectManager
  30. */
  31. private $objectManager;
  32. /**
  33. * @var TransactionSale|MockObject
  34. */
  35. private $client;
  36. /**
  37. * @inheritdoc
  38. */
  39. protected function setUp()
  40. {
  41. $this->objectManager = Bootstrap::getObjectManager();
  42. $this->client = $this->getMockBuilder(TransactionSale::class)
  43. ->disableOriginalConstructor()
  44. ->getMock();
  45. $this->objectManager->addSharedInstance($this->client, TransactionSale::class);
  46. }
  47. /**
  48. * @inheritdoc
  49. */
  50. protected function tearDown()
  51. {
  52. $this->objectManager->removeSharedInstance(TransactionSale::class);
  53. parent::tearDown();
  54. }
  55. /**
  56. * Checks a case when payment method triggers an error during place order flow and
  57. * error messages from payment gateway should be mapped.
  58. * Error messages might be specific for different areas.
  59. *
  60. * @magentoAppIsolation enabled
  61. * @magentoDataFixture Magento/Checkout/_files/quote_with_shipping_method.php
  62. * @magentoConfigFixture current_store payment/braintree/active 1
  63. * @dataProvider getErrorPerAreaDataProvider
  64. * @expectedException \Magento\Framework\Exception\CouldNotSaveException
  65. * @param string $area
  66. * @param array $testErrorCodes
  67. * @param string $expectedOutput
  68. * @throws \Magento\Framework\Exception\LocalizedException
  69. */
  70. public function testSavePaymentInformationAndPlaceOrderWithErrors(
  71. string $area,
  72. array $testErrorCodes,
  73. string $expectedOutput
  74. ) {
  75. /** @var State $state */
  76. $state = $this->objectManager->get(State::class);
  77. $state->setAreaCode($area);
  78. $quote = $this->getQuote('test_order_1');
  79. /** @var PaymentInterface $payment */
  80. $payment = $this->objectManager->create(PaymentInterface::class);
  81. $payment->setMethod(ConfigProvider::CODE);
  82. $errors = ['errors' => []];
  83. foreach ($testErrorCodes as $testErrorCode) {
  84. array_push($errors['errors'], ['code' => $testErrorCode]);
  85. }
  86. $response = new Error(['errors' => $errors]);
  87. $this->client->method('placeRequest')
  88. ->willReturn(['object' => $response]);
  89. $this->expectExceptionMessage($expectedOutput);
  90. /** @var PaymentInformationManagementInterface $paymentInformationManagement */
  91. $paymentInformationManagement = $this->objectManager->get(PaymentInformationManagementInterface::class);
  92. $paymentInformationManagement->savePaymentInformationAndPlaceOrder(
  93. $quote->getId(),
  94. $payment
  95. );
  96. }
  97. /**
  98. * Gets list of areas with specific error messages.
  99. *
  100. * @return array
  101. */
  102. public function getErrorPerAreaDataProvider()
  103. {
  104. $testErrorGlobal = ['code' => 81802, 'message' => 'Company is too long.'];
  105. $testErrorAdmin = ['code' => 91511, 'message' => 'Customer does not have any credit cards.'];
  106. $testErrorFake = ['code' => 'fake_code', 'message' => 'Error message should not be mapped.'];
  107. return [
  108. [
  109. Area::AREA_FRONTEND,
  110. [$testErrorAdmin['code'], $testErrorFake['code']],
  111. 'Transaction has been declined. Please try again later.'
  112. ], [
  113. Area::AREA_FRONTEND,
  114. [$testErrorGlobal['code'], $testErrorAdmin['code'], $testErrorFake['code']],
  115. $testErrorGlobal['message']
  116. ], [
  117. Area::AREA_ADMINHTML,
  118. [$testErrorGlobal['code'], $testErrorAdmin['code'], $testErrorFake['code']],
  119. $testErrorGlobal['message'] . PHP_EOL . $testErrorAdmin['message']
  120. ],
  121. ];
  122. }
  123. /**
  124. * Retrieves quote by provided order ID.
  125. *
  126. * @param string $reservedOrderId
  127. * @return CartInterface
  128. */
  129. private function getQuote(string $reservedOrderId): CartInterface
  130. {
  131. /** @var SearchCriteriaBuilder $searchCriteriaBuilder */
  132. $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class);
  133. $searchCriteria = $searchCriteriaBuilder->addFilter('reserved_order_id', $reservedOrderId)
  134. ->create();
  135. /** @var CartRepositoryInterface $quoteRepository */
  136. $quoteRepository = $this->objectManager->get(CartRepositoryInterface::class);
  137. $items = $quoteRepository->getList($searchCriteria)
  138. ->getItems();
  139. return array_pop($items);
  140. }
  141. }