From a9166d0b0cf2b7284bf084666e670b60c8a761bc Mon Sep 17 00:00:00 2001 From: carmenmaymo Date: Mon, 7 Jul 2025 15:36:15 +0200 Subject: [PATCH 1/2] Add OXXO transaction success and failing tests --- .../Transaction_tests/OxxoTransactionTest.php | 199 ++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 tests/integration/PHPUnit/Transaction_tests/OxxoTransactionTest.php diff --git a/tests/integration/PHPUnit/Transaction_tests/OxxoTransactionTest.php b/tests/integration/PHPUnit/Transaction_tests/OxxoTransactionTest.php new file mode 100644 index 000000000..13ae98aee --- /dev/null +++ b/tests/integration/PHPUnit/Transaction_tests/OxxoTransactionTest.php @@ -0,0 +1,199 @@ + function () use ($orderEndpoint) { + return $orderEndpoint; + }, + ]; + + return $this->bootstrapModule(array_merge($services, $additionalServices)); + } + + /** + * Data provider for different product combinations + * + * @return array + */ + public function paymentProcessingDataProvider(): array + { + // A webhook will put the pending payments to on-hold status, + // but we are not testing webhooks here. + // look at PaymentCapturePending::handle_request + return [ + 'simple product only' => [ + 'products' => ['simple'], + 'expected_status' => 'pending' + ], + 'expensive product' => [ + 'products' => ['simple_expensive'], + 'expected_status' => 'pending' + ], + 'multiple products' => [ + 'products' => [ + ['preset' => 'simple', 'quantity' => 2], + 'simple_expensive' + ], + 'expected_status' => 'pending' + ], + ]; + } + + /** + * Tests OXXO payment processing with different product combinations. + * + * @scenario Process OXXO payment for order + * @given a WooCommerce order with various product combinations + * @and valid billing information for Mexico + * @when the OXXO payment is processed + * @then the PayPal API should be called to create and confirm payment + * @and a payer action link should be stored in order meta + * @and the order status should change to on-hold + * @and the cart should be emptied + * + * @dataProvider paymentProcessingDataProvider + * + * @param array $products Product configuration + * @param string $expected_status Expected order status after payment + * + * @return void + */ + public function testProcessPayment(array $products, string $expected_status): void + { + $mockOrderEndpoint = $this->mockOrderEndpointForOXXO(); + $container = $this->setupTestContainer($mockOrderEndpoint); + + $order = $this->getConfiguredOrder( + $this->customer_id, + OXXOGateway::ID, + $products, + [], // No discounts for OXXO tests + false + ); + + $order->set_billing_country('MX'); + $order->set_billing_first_name('Juan'); + $order->set_billing_last_name('Pérez'); + $order->set_billing_email('juan.perez@example.com'); + $order->save(); + + $gateway = $container->get('wcgateway.oxxo-gateway'); + $result = $gateway->process_payment($order->get_id()); + + $this->assertEquals('success', $result['result']); + $this->assertArrayHasKey('redirect', $result); + + $order = wc_get_order($order->get_id()); + $this->assertEquals($expected_status, $order->get_status()); + + $payer_action_link = $order->get_meta('ppcp_oxxo_payer_action'); + $this->assertNotEmpty($payer_action_link); + $this->assertStringContainsString('paypal.com/payment/oxxo', $payer_action_link); + } + + /** + * Tests OXXO payment processing failure scenarios. + * + * @scenario Process OXXO payment with API failure + * @given a WooCommerce order with valid billing information + * @when the PayPal API fails during order creation + * @then the payment should fail gracefully + * @and the order status should be updated to failed + * @and an error notice should be displayed + * + * @return void + */ + public function testProcessPaymentFailure(): void + { + $mockOrderEndpoint = $this->mockOrderEndpointWithFailure(); + $container = $this->setupTestContainer($mockOrderEndpoint); + + $order = $this->getConfiguredOrder( + $this->customer_id, + OXXOGateway::ID, + ['simple'], + [], + false + ); + $order->set_billing_country('MX'); + $order->set_billing_first_name('Juan'); + $order->set_billing_last_name('Pérez'); + $order->set_billing_email('juan.perez@example.com'); + $order->save(); + + $gateway = $container->get('wcgateway.oxxo-gateway'); + $result = $gateway->process_payment($order->get_id()); + + $this->assertEquals('failure', $result['result']); + } + + /** + * Mock OrderEndpoint for successful OXXO payment processing + * + * @return OrderEndpoint + */ + private function mockOrderEndpointForOXXO(): OrderEndpoint + { + $mockEndpoint = $this->mockOrderEndpoint('CAPTURE', true, true); + + // Add OXXO-specific confirm_payment_source method + $confirmResponse = (object)[ + 'links' => [ + (object)[ + 'rel' => 'payer-action', + 'href' => 'https://sandbox.paypal.com/payment/oxxo?token=TEST_TOKEN_123', + ], + ] + ]; + + $mockEndpoint->shouldReceive('confirm_payment_source') + ->andReturn($confirmResponse); + + return $mockEndpoint; + } + + /** + * Mock OrderEndpoint for failed payment processing + * + * @return OrderEndpoint + */ + private function mockOrderEndpointWithFailure(): OrderEndpoint + { + $mockEndpoint = $this->mockOrderEndpoint('CAPTURE', false, false); + + // Override the create method to throw exception (OXXO fails at order creation) + $mockEndpoint->shouldReceive('confirm_payment_source') + ->andThrow(RuntimeException::class, 'API Error'); + + return $mockEndpoint; + } +} From 4426fc6e13868ec5d35eb0ab8f8a28b1b45e4883 Mon Sep 17 00:00:00 2001 From: carmenmaymo Date: Wed, 9 Jul 2025 10:55:13 +0200 Subject: [PATCH 2/2] Add vaulting transaction test --- .../CreditcardTransactionTest.php | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/integration/PHPUnit/Transaction_tests/CreditcardTransactionTest.php b/tests/integration/PHPUnit/Transaction_tests/CreditcardTransactionTest.php index 76a3fdd55..6be9de4d5 100644 --- a/tests/integration/PHPUnit/Transaction_tests/CreditcardTransactionTest.php +++ b/tests/integration/PHPUnit/Transaction_tests/CreditcardTransactionTest.php @@ -181,4 +181,67 @@ class CreditcardTransactionTest extends IntegrationMockedTestCase unset($_POST['ppcp-credit-card-gateway-card-expiry']); unset($_POST['ppcp-credit-card-gateway-card-cvc']); } + + /** + * Tests payment processing with a saved/vaulted credit card. + * + * GIVEN a WooCommerce order + * AND a saved credit card token for the customer + * AND the saved card ID in POST data + * WHEN the payment is processed through the credit card gateway + * THEN the payment should be successfully captured using the vaulted card + * AND the order status should change to processing + * AND a transaction ID should be set on the order + */ + public function testProcessPaymentVaultedCard() + { + $mockOrderEndpoint = $this->mockOrderEndpoint('CAPTURE', false, true); + $order = $this->getConfiguredOrder( + $this->customer_id, + 'ppcp-credit-card-gateway', + ['simple'], + [], + false + ); + $paypal_order_id = 'TEST-PAYPAL-ORDER-' . uniqid(); + + $_POST['paypal_order_id'] = $paypal_order_id; + $order->update_meta_data('_paypal_order_id', $paypal_order_id); + $order->save(); + + $paymentToken = $this->setupPaymentToken($this->customer_id, 'ppcp-credit-card-gateway'); + + // Set the saved card in POST data (simulating frontend selection) + $_POST['saved_credit_card'] = $paymentToken->get_token(); + + $sessionHandler = \Mockery::mock(\WooCommerce\PayPalCommerce\Session\SessionHandler::class); + $sessionHandler->shouldReceive('order')->andReturn(null); + $sessionHandler->shouldReceive('destroy_session_data')->once(); + + $additionalServices = [ + 'session.handler' => function() use ($sessionHandler) { + return $sessionHandler; + }, + 'api.endpoint.payment-tokens' => function() { + return $this->mockPaymentTokensEndpoint; + } + ]; + + $c = $this->setupTestContainer($mockOrderEndpoint, $additionalServices); + $gateway = $c->get('wcgateway.credit-card-gateway'); + + $result = $gateway->process_payment($order->get_id()); + + // Assertions + $this->assertEquals('success', $result['result']); + $this->assertArrayHasKey('redirect', $result); + + // Verify order status changed + $order = wc_get_order($order->get_id()); // Refresh order + $this->assertEquals('processing', $order->get_status()); + $this->assertNotEmpty($order->get_transaction_id()); + + // Clean up POST data + unset($_POST['saved_credit_card']); + } }