PaymentServiceCancelStrategyTest.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <?php
  2. namespace Webkul\BagistoApi\Tests\Unit\Services;
  3. use Illuminate\Support\Facades\Event;
  4. use Mockery;
  5. use Tests\TestCase;
  6. use Webkul\BagistoApi\Repositories\PaymentAttemptRepository;
  7. use Webkul\BagistoApi\Services\CartTokenService;
  8. use Webkul\BagistoApi\Services\PaymentService;
  9. use Webkul\Checkout\Repositories\CartRepository;
  10. use Webkul\Sales\Repositories\InvoiceRepository;
  11. use Webkul\Sales\Repositories\OrderRepository;
  12. use Webkul\Sales\Repositories\OrderTransactionRepository;
  13. /**
  14. * Coverage for the cancel-order strategy branches required by the
  15. * "支付流程" spec:
  16. *
  17. * - guest -> immediate cancel + reactivate old cart
  18. * - customer + addr -> keep order pending
  19. * - customer + !addr + config=cancel -> cancel
  20. * - customer + !addr + config=keep_pending -> keep pending
  21. * - !addr branch ALWAYS dispatches the no-address event
  22. */
  23. class PaymentServiceCancelStrategyTest extends TestCase
  24. {
  25. protected function tearDown(): void
  26. {
  27. Mockery::close();
  28. parent::tearDown();
  29. }
  30. private function makeService(): PaymentService
  31. {
  32. return new PaymentService(
  33. Mockery::mock(OrderRepository::class),
  34. Mockery::mock(CartRepository::class),
  35. Mockery::mock(CartTokenService::class),
  36. Mockery::mock(InvoiceRepository::class),
  37. Mockery::mock(OrderTransactionRepository::class),
  38. Mockery::mock(PaymentAttemptRepository::class),
  39. );
  40. }
  41. private function fakeOrder(?array $shippingFields, array $additional = []): object
  42. {
  43. $payment = (object) ['additional' => $additional];
  44. $shipping = $shippingFields ? (object) $shippingFields : null;
  45. return new class($payment, $shipping)
  46. {
  47. public function __construct(
  48. public object $payment,
  49. public ?object $shipping_address,
  50. ) {}
  51. };
  52. }
  53. public function test_guest_cancel_reactivates_old_cart(): void
  54. {
  55. Event::fake();
  56. $order = $this->fakeOrder([
  57. 'city' => 'NYC',
  58. 'postcode' => '10001',
  59. ], ['cart_id' => 42]);
  60. $result = $this->makeService()->decideCancelStrategy($order, isGuest: true);
  61. $this->assertSame('cancel', $result['action']);
  62. $this->assertSame('guest', $result['reason']);
  63. $this->assertSame(42, $result['reactivate_cart']);
  64. }
  65. public function test_customer_with_real_shipping_address_keeps_pending(): void
  66. {
  67. Event::fake();
  68. $order = $this->fakeOrder([
  69. 'city' => 'San Francisco',
  70. 'postcode' => '94016',
  71. ]);
  72. $result = $this->makeService()->decideCancelStrategy($order, isGuest: false);
  73. $this->assertSame('keep_pending', $result['action']);
  74. $this->assertSame('customer_has_shipping_address', $result['reason']);
  75. Event::assertNotDispatched('bagistoapi.express.cancel.no-address');
  76. }
  77. public function test_customer_without_shipping_address_default_cancel_strategy(): void
  78. {
  79. config(['bagistoapi.express_checkout.cancel_without_address' => 'cancel']);
  80. Event::fake();
  81. $order = $this->fakeOrder(null);
  82. $result = $this->makeService()->decideCancelStrategy($order, isGuest: false);
  83. $this->assertSame('cancel', $result['action']);
  84. $this->assertSame('customer_no_shipping_address', $result['reason']);
  85. Event::assertDispatched('bagistoapi.express.cancel.no-address');
  86. }
  87. public function test_customer_without_shipping_address_keep_pending_strategy(): void
  88. {
  89. config(['bagistoapi.express_checkout.cancel_without_address' => 'keep_pending']);
  90. Event::fake();
  91. $order = $this->fakeOrder(null);
  92. $result = $this->makeService()->decideCancelStrategy($order, isGuest: false);
  93. $this->assertSame('keep_pending', $result['action']);
  94. $this->assertSame('customer_no_shipping_address', $result['reason']);
  95. Event::assertDispatched('bagistoapi.express.cancel.no-address');
  96. }
  97. public function test_customer_with_placeholder_address_is_treated_as_no_address(): void
  98. {
  99. config([
  100. 'bagistoapi.express_checkout.cancel_without_address' => 'cancel',
  101. 'bagistoapi.express_checkout.placeholder_address' => [
  102. 'city' => 'Pending',
  103. 'postcode' => '00000',
  104. ],
  105. ]);
  106. Event::fake();
  107. $order = $this->fakeOrder([
  108. 'city' => 'Pending',
  109. 'postcode' => '00000',
  110. ]);
  111. $result = $this->makeService()->decideCancelStrategy($order, isGuest: false);
  112. $this->assertSame('cancel', $result['action']);
  113. $this->assertSame('customer_no_shipping_address', $result['reason']);
  114. }
  115. }