mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2026-07-29 02:07:27 +08:00
127 lines
5 KiB
PHP
127 lines
5 KiB
PHP
<?php
|
||
declare( strict_types = 1 );
|
||
|
||
namespace WooCommerce\PayPalCommerce\Tests\Integration\StoreSync;
|
||
|
||
use Mockery;
|
||
use Psr\Log\NullLogger;
|
||
use WP_REST_Request;
|
||
use WP_REST_Response;
|
||
use WooCommerce\PayPalCommerce\StoreSync\Endpoint\GetCartEndpoint;
|
||
use WooCommerce\PayPalCommerce\StoreSync\Helper\PayPalOrderManager;
|
||
use WooCommerce\PayPalCommerce\StoreSync\Schema\PayPalCart;
|
||
use WooCommerce\PayPalCommerce\StoreSync\Session\AgenticSessionHandler;
|
||
use WooCommerce\PayPalCommerce\StoreSync\Validation\StoreValidation;
|
||
use WooCommerce\PayPalCommerce\Tests\Integration\IntegrationMockedTestCase;
|
||
|
||
/**
|
||
* @covers \WooCommerce\PayPalCommerce\StoreSync\Endpoint\GetCartEndpoint
|
||
*/
|
||
class GetCartEndpointTest extends IntegrationMockedTestCase {
|
||
|
||
private GetCartEndpoint $endpoint;
|
||
|
||
private AgenticSessionHandler $session_handler;
|
||
|
||
public function setUp(): void {
|
||
parent::setUp();
|
||
|
||
$c = $this->getContainer();
|
||
|
||
$this->session_handler = $c->get( 'agentic.session.handler' );
|
||
|
||
$order_manager = Mockery::mock( PayPalOrderManager::class );
|
||
|
||
$this->endpoint = new GetCartEndpoint(
|
||
$c->get( 'agentic.auth.provider' ),
|
||
$this->session_handler,
|
||
$c->get( 'agentic.helper.session-manager' ),
|
||
$c->get( 'agentic.response.factory' ),
|
||
$c->get( 'agentic.validation.processor' ),
|
||
new NullLogger(),
|
||
$order_manager,
|
||
$c->get( 'agentic.store.data' )
|
||
);
|
||
}
|
||
|
||
/**
|
||
* GIVEN a cart session exists with a known ec_token and one product with a shipping address
|
||
* WHEN get_cart() is called with the corresponding cart_id
|
||
* THEN the response status is 200
|
||
* AND id matches the cart session id
|
||
* AND status and validation_status keys are present
|
||
* AND payment_method.token equals the ec_token stored in the session
|
||
* AND items array is not empty
|
||
* AND customer and shipping_address keys exist in the response
|
||
* AND available_shipping_options has at least one entry with exactly one selected option
|
||
* AND totals contains subtotal, shipping, tax and total each with a non-empty value
|
||
* AND the sum of item price × quantity equals the subtotal (in cents)
|
||
*/
|
||
public function test_get_cart_returns_expected_shape_for_existing_cart(): void {
|
||
$ec_token = 'test-ec-token-get';
|
||
|
||
$cart_data = array(
|
||
'items' => array(
|
||
array(
|
||
'variant_id' => 'DUMMY_SIMPLE_SKU_01',
|
||
'quantity' => 1,
|
||
),
|
||
),
|
||
'shipping_address' => array(
|
||
'address_line_1' => '456 Fictional St',
|
||
'admin_area_2' => 'San Jose',
|
||
'postal_code' => '90210',
|
||
'country_code' => 'US',
|
||
),
|
||
'payment_method' => array( 'type' => 'paypal' ),
|
||
);
|
||
|
||
$initial_cart = PayPalCart::from_array( $cart_data, new StoreValidation() );
|
||
$cart_id = $this->session_handler->create_cart_session( $initial_cart, $ec_token );
|
||
|
||
$request = new WP_REST_Request( 'GET' );
|
||
$request->set_param( 'cart_id', $cart_id );
|
||
|
||
$response = $this->endpoint->get_cart( $request );
|
||
|
||
$this->assertInstanceOf( WP_REST_Response::class, $response );
|
||
$this->assertSame( 200, $response->get_status() );
|
||
|
||
$data = $response->get_data();
|
||
|
||
$this->assertSame( $cart_id, $data['id'] ?? null, 'Response must echo the cart id' );
|
||
|
||
$this->assertArrayHasKey( 'status', $data, 'Response must include status' );
|
||
$this->assertArrayHasKey( 'validation_status', $data, 'Response must include validation_status' );
|
||
|
||
$this->assertArrayHasKey( 'payment_method', $data );
|
||
$this->assertSame( $ec_token, $data['payment_method']['token'] ?? null, 'Response must return the ec_token stored in the session' );
|
||
|
||
$this->assertArrayHasKey( 'items', $data, 'Response must include items' );
|
||
$this->assertNotEmpty( $data['items'] );
|
||
|
||
$this->assertArrayHasKey( 'customer', $data, 'Response must include customer' );
|
||
$this->assertArrayHasKey( 'shipping_address', $data, 'Response must include shipping_address' );
|
||
|
||
$shipping_options = $data['available_shipping_options'] ?? array();
|
||
$this->assertIsArray( $shipping_options );
|
||
$this->assertGreaterThanOrEqual( 1, count( $shipping_options ), 'At least one shipping option must be present' );
|
||
$selected = array_filter( $shipping_options, fn( $opt ) => ( $opt['is_selected'] ?? false ) === true );
|
||
$this->assertCount( 1, $selected, 'Exactly one shipping option must be selected' );
|
||
|
||
$this->assertArrayHasKey( 'totals', $data, 'Response must include calculated totals' );
|
||
foreach ( array( 'subtotal', 'shipping', 'tax', 'total' ) as $key ) {
|
||
$this->assertArrayHasKey( $key, $data['totals'], "totals must include $key" );
|
||
$this->assertNotEmpty( $data['totals'][ $key ]['value'] ?? '', "totals.$key.value must not be empty" );
|
||
}
|
||
|
||
$items_subtotal_cents = 0;
|
||
foreach ( $data['items'] as $item ) {
|
||
$price = (float) ( $item['price']['value'] ?? 0 );
|
||
$quantity = (int) ( $item['quantity'] ?? 0 );
|
||
$items_subtotal_cents += (int) round( $price * 100 ) * $quantity;
|
||
}
|
||
$subtotal_cents = (int) round( (float) ( $data['totals']['subtotal']['value'] ?? 0 ) * 100 );
|
||
$this->assertSame( $subtotal_cents, $items_subtotal_cents, 'Sum of item price × quantity must equal totals.subtotal' );
|
||
}
|
||
}
|