woocommerce-paypal-payments/tests/integration/PHPUnit/StoreSync/GetCartEndpointTest.php

127 lines
5 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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' );
}
}