mirror of
https://github.com/wp-graphql/wp-graphql-woocommerce.git
synced 2026-08-14 12:53:44 +02:00
* fix: resolve REQUEST_URI fatal error and JWT key length issues in CI QLSessionHandlerTest::tearDown() was calling unset($_SERVER) which destroyed the entire superglobal. WordPress cron.php then fataled on shutdown when accessing $_SERVER['REQUEST_URI']. Changed to only unset the specific HTTP_WOOCOMMERCE_SESSION key. Also updated JWT secret keys to meet firebase/php-jwt v7's minimum 32-byte requirement for HS256 in both test config and Docker entrypoint. * fix: the rest of the files added * devops: php7.4 removed from matrix * chore: Linter compliances met * devops: More broken test updated * devops: Tests updated for CI * fix: QLSessionHandlerCest fixed * fix: QLSessionHandlerCest fixed * devops: CI fixed
527 lines
11 KiB
PHP
527 lines
11 KiB
PHP
<?php
|
|
|
|
use Tests\WPGraphQL\Logger\CodeceptLogger as Signal;
|
|
|
|
class CartTransactionQueueCest {
|
|
private $product_catalog;
|
|
|
|
public function _before( FunctionalTester $I ) {
|
|
// Create Products
|
|
$this->product_catalog = $I->getCatalog();
|
|
}
|
|
|
|
public function _addTshirtToCart( FunctionalTester $I, $headers = [] ) {
|
|
/**
|
|
* Add t-shirt to the cart
|
|
*/
|
|
$add_to_cart_query = 'mutation ( $input: AddToCartInput! ) {
|
|
addToCart( input: $input ) {
|
|
clientMutationId
|
|
cartItem {
|
|
key
|
|
product {
|
|
node {
|
|
id
|
|
}
|
|
}
|
|
variation {
|
|
node {
|
|
id
|
|
}
|
|
}
|
|
quantity
|
|
subtotal
|
|
subtotalTax
|
|
total
|
|
tax
|
|
}
|
|
}
|
|
}';
|
|
$success = $I->postRawRequest(
|
|
$add_to_cart_query,
|
|
[
|
|
'input' => [
|
|
'clientMutationId' => 'someId',
|
|
'productId' => $this->product_catalog['t-shirt'],
|
|
'quantity' => 5,
|
|
]
|
|
],
|
|
[ 'headers' => $headers ]
|
|
);
|
|
|
|
|
|
$response_body = json_decode( $success->getBody(), true );
|
|
$I->assertQuerySuccessful(
|
|
$response_body,
|
|
[
|
|
$I->expectField( 'addToCart.cartItem.key', Signal::NOT_NULL ),
|
|
]
|
|
);
|
|
|
|
$key = $I->lodashGet( $response_body, 'data.addToCart.cartItem.key' );
|
|
|
|
/**
|
|
* Assert existence and validity of "woocommerce-session" HTTP header.
|
|
*/
|
|
$session_header = $success->getHeader('woocommerce-session');
|
|
$I->assertNotEmpty( $session_header );
|
|
$session_token = $session_header[0];
|
|
|
|
return compact( 'key', 'session_token' );
|
|
}
|
|
|
|
public function _startAuthenticatedSession( $I ) {
|
|
$I->setupStoreAndUsers();
|
|
|
|
// Begin Tests.
|
|
$I->wantTo( 'login' );
|
|
$login_input = [
|
|
'clientMutationId' => 'someId',
|
|
'username' => 'jimbo1234@example.com',
|
|
'password' => 'password',
|
|
];
|
|
|
|
$success = $I->login( $login_input );
|
|
|
|
// Validate response.
|
|
$I->assertQuerySuccessful(
|
|
$success,
|
|
[
|
|
$I->expectField( 'login.customer.databaseId', Signal::NOT_NULL ),
|
|
$I->expectField( 'login.authToken', Signal::NOT_NULL ),
|
|
$I->expectField( 'login.refreshToken', Signal::NOT_NULL ),
|
|
$I->expectField( 'login.sessionToken', Signal::NOT_NULL ),
|
|
]
|
|
);
|
|
|
|
// Retrieve JWT Authorization Token for later use.
|
|
$auth_token = $I->lodashGet( $success, 'data.login.authToken' );
|
|
|
|
// Retrieve session token. Add as "Session %s" in the woocommerce-session HTTP header to future requests
|
|
// so WooCommerce can identify the user session associated with actions made in the GraphQL requests.
|
|
// You can also retrieve the token from the "woocommerce-session" HTTP response header.
|
|
$initial_session_token = $I->lodashGet( $success, 'data.login.sessionToken' );
|
|
|
|
$headers = [
|
|
'Authorization' => "Bearer {$auth_token}",
|
|
'woocommerce-session' => "Session {$initial_session_token}",
|
|
];
|
|
|
|
$tokens = $this->_addTshirtToCart( $I, $headers );
|
|
|
|
return array_merge(
|
|
$tokens,
|
|
[ 'auth_token' => $auth_token ]
|
|
);
|
|
}
|
|
|
|
// tests
|
|
public function testCartTransactionQueueWithConcurrentRequests( FunctionalTester $I, $scenario ) {
|
|
//$scenario->skip( 'The test is unstable, and will be skipped until success is guaranteed on each run.' );
|
|
$tokens = $this->_startAuthenticatedSession( $I );
|
|
|
|
$key = $tokens['key'];
|
|
$auth_token = $tokens['auth_token'];
|
|
$session_token = $tokens['session_token'];
|
|
|
|
$I->wantTo( 'Running a bunch of cart mutations one after the another wait for all the response at once' );
|
|
$update_item_quantities_mutation = '
|
|
mutation( $input: UpdateItemQuantitiesInput! ) {
|
|
updateItemQuantities( input: $input ) {
|
|
clientMutationId
|
|
updated {
|
|
key
|
|
quantity
|
|
}
|
|
removed {
|
|
key
|
|
quantity
|
|
}
|
|
items {
|
|
key
|
|
quantity
|
|
}
|
|
}
|
|
}
|
|
';
|
|
$remove_item_mutation = '
|
|
mutation ( $input: RemoveItemsFromCartInput! ) {
|
|
removeItemsFromCart( input: $input ) {
|
|
clientMutationId
|
|
cart {
|
|
contents {
|
|
nodes {
|
|
key
|
|
quantity
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
';
|
|
$restore_item_mutation = '
|
|
mutation ( $input: RestoreCartItemsInput! ) {
|
|
restoreCartItems( input: $input ) {
|
|
clientMutationId
|
|
cart {
|
|
contents {
|
|
nodes {
|
|
key
|
|
quantity
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
';
|
|
$operations = [
|
|
[
|
|
'query' => $update_item_quantities_mutation,
|
|
'variables' => [
|
|
'input' => [
|
|
'clientMutationId' => 'some_id',
|
|
'items' => [
|
|
[
|
|
'key' => $key,
|
|
'quantity' => 3,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
[
|
|
'query' => $update_item_quantities_mutation,
|
|
'variables' => [
|
|
'input' => [
|
|
'clientMutationId' => 'some_id',
|
|
'items' => [
|
|
[
|
|
'key' => $key,
|
|
'quantity' => 4,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
[
|
|
'query' => $remove_item_mutation,
|
|
'variables' => [
|
|
'input' => [
|
|
'clientMutationId' => 'some_id',
|
|
'keys' => [ $key ],
|
|
],
|
|
],
|
|
],
|
|
[
|
|
'query' => $restore_item_mutation,
|
|
'variables' => [
|
|
'input' => [
|
|
'clientMutationId' => 'some_id',
|
|
'keys' => [ $key ],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$selected_options = [
|
|
'headers' => [
|
|
'Content-Type' => 'application/json',
|
|
'Authorization' => "Bearer {$auth_token}",
|
|
'woocommerce-session' => "Session {$session_token}",
|
|
],
|
|
];
|
|
$responses = $I->concurrentRequests( $operations, $selected_options, 200 );
|
|
|
|
$I->assertQuerySuccessful(
|
|
$responses[0],
|
|
[
|
|
$I->expectObject(
|
|
'updateItemQuantities',
|
|
[
|
|
$I->expectObject(
|
|
'updated.0',
|
|
[
|
|
$I->expectField( 'key', $key ),
|
|
$I->expectField( 'quantity', 3 )
|
|
]
|
|
),
|
|
$I->expectField( 'removed', Signal::IS_FALSY ),
|
|
$I->expectObject(
|
|
'items.0',
|
|
[
|
|
$I->expectField( 'key', $key ),
|
|
$I->expectField( 'quantity', 3 )
|
|
]
|
|
)
|
|
]
|
|
)
|
|
]
|
|
);
|
|
|
|
$I->assertQuerySuccessful(
|
|
$responses[1],
|
|
[
|
|
$I->expectObject(
|
|
'updateItemQuantities',
|
|
[
|
|
$I->expectObject(
|
|
'updated.0',
|
|
[
|
|
$I->expectField( 'key', $key ),
|
|
$I->expectField( 'quantity', 4 )
|
|
]
|
|
),
|
|
$I->expectField( 'removed', Signal::IS_FALSY ),
|
|
$I->expectObject(
|
|
'items.0',
|
|
[
|
|
$I->expectField( 'key', $key ),
|
|
$I->expectField( 'quantity', 4 )
|
|
]
|
|
)
|
|
]
|
|
)
|
|
]
|
|
);
|
|
|
|
$I->assertQuerySuccessful(
|
|
$responses[2],
|
|
[
|
|
$I->expectObject(
|
|
'removeItemsFromCart',
|
|
[
|
|
$I->expectField(
|
|
'cart.contents.nodes',
|
|
Signal::IS_FALSY
|
|
)
|
|
]
|
|
)
|
|
]
|
|
);
|
|
|
|
$I->assertQuerySuccessful(
|
|
$responses[3],
|
|
[
|
|
$I->expectObject(
|
|
'restoreCartItems',
|
|
[
|
|
$I->expectObject(
|
|
'cart.contents.nodes.0',
|
|
[
|
|
$I->expectField( 'key', $key ),
|
|
$I->expectField( 'quantity', 4 )
|
|
]
|
|
)
|
|
]
|
|
)
|
|
]
|
|
);
|
|
}
|
|
|
|
public function testCartTransactionQueueWithConcurrentBatchRequests( FunctionalTester $I, $scenario ) {
|
|
$tokens = $this->_startAuthenticatedSession( $I );
|
|
|
|
$key = $tokens['key'];
|
|
$auth_token = $tokens['auth_token'];
|
|
$session_token = $tokens['session_token'];
|
|
|
|
$I->wantTo( 'Running a bunch of cart mutations one after the another wait for all the response at once' );
|
|
$update_item_quantities_mutation = '
|
|
mutation( $input: UpdateItemQuantitiesInput! ) {
|
|
updateItemQuantities( input: $input ) {
|
|
clientMutationId
|
|
updated {
|
|
key
|
|
quantity
|
|
}
|
|
removed {
|
|
key
|
|
quantity
|
|
}
|
|
items {
|
|
key
|
|
quantity
|
|
}
|
|
}
|
|
}
|
|
';
|
|
$remove_item_mutation = '
|
|
mutation ( $input: RemoveItemsFromCartInput! ) {
|
|
removeItemsFromCart( input: $input ) {
|
|
clientMutationId
|
|
cart {
|
|
contents {
|
|
nodes {
|
|
key
|
|
quantity
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
';
|
|
$restore_item_mutation = '
|
|
mutation ( $input: RestoreCartItemsInput! ) {
|
|
restoreCartItems( input: $input ) {
|
|
clientMutationId
|
|
cart {
|
|
contents {
|
|
nodes {
|
|
key
|
|
quantity
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
';
|
|
|
|
$operations = [
|
|
[
|
|
[
|
|
'query' => $update_item_quantities_mutation,
|
|
'variables' => [
|
|
'input' => [
|
|
'clientMutationId' => 'some_id',
|
|
'items' => [
|
|
[
|
|
'key' => $key,
|
|
'quantity' => 3,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
[
|
|
'query' => $update_item_quantities_mutation,
|
|
'variables' => [
|
|
'input' => [
|
|
'clientMutationId' => 'some_id',
|
|
'items' => [
|
|
[
|
|
'key' => $key,
|
|
'quantity' => 4,
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
[
|
|
[
|
|
'query' => $remove_item_mutation,
|
|
'variables' => [
|
|
'input' => [
|
|
'clientMutationId' => 'some_id',
|
|
'keys' => [ $key ],
|
|
],
|
|
],
|
|
],
|
|
[
|
|
'query' => $restore_item_mutation,
|
|
'variables' => [
|
|
'input' => [
|
|
'clientMutationId' => 'some_id',
|
|
'keys' => [ $key ],
|
|
],
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$selected_options = [
|
|
'headers' => [
|
|
'Content-Type' => 'application/json',
|
|
'Authorization' => "Bearer {$auth_token}",
|
|
'woocommerce-session' => "Session {$session_token}",
|
|
],
|
|
];
|
|
$responses = $I->concurrentRequests( $operations, $selected_options, 150 );
|
|
|
|
$I->assertQuerySuccessful(
|
|
$responses[0][0],
|
|
[
|
|
$I->expectObject(
|
|
'updateItemQuantities',
|
|
[
|
|
$I->expectObject(
|
|
'updated.0',
|
|
[
|
|
$I->expectField( 'key', $key ),
|
|
$I->expectField( 'quantity', 3 )
|
|
]
|
|
),
|
|
$I->expectField( 'removed', Signal::IS_FALSY ),
|
|
$I->expectObject(
|
|
'items.0',
|
|
[
|
|
$I->expectField( 'key', $key ),
|
|
$I->expectField( 'quantity', 3 )
|
|
]
|
|
)
|
|
]
|
|
)
|
|
]
|
|
);
|
|
|
|
$I->assertQuerySuccessful(
|
|
$responses[0][1],
|
|
[
|
|
$I->expectObject(
|
|
'updateItemQuantities',
|
|
[
|
|
$I->expectObject(
|
|
'updated.0',
|
|
[
|
|
$I->expectField( 'key', $key ),
|
|
$I->expectField( 'quantity', 4 )
|
|
]
|
|
),
|
|
$I->expectField( 'removed', Signal::IS_FALSY ),
|
|
$I->expectObject(
|
|
'items.0',
|
|
[
|
|
$I->expectField( 'key', $key ),
|
|
$I->expectField( 'quantity', 4 )
|
|
]
|
|
)
|
|
]
|
|
)
|
|
]
|
|
);
|
|
|
|
$I->assertQuerySuccessful(
|
|
$responses[1][0],
|
|
[
|
|
$I->expectObject(
|
|
'removeItemsFromCart',
|
|
[
|
|
$I->expectField(
|
|
'cart.contents.nodes',
|
|
Signal::IS_FALSY
|
|
)
|
|
]
|
|
)
|
|
]
|
|
);
|
|
|
|
$I->assertQuerySuccessful(
|
|
$responses[1][1],
|
|
[
|
|
$I->expectObject(
|
|
'restoreCartItems',
|
|
[
|
|
$I->expectObject(
|
|
'cart.contents.nodes.0',
|
|
[
|
|
$I->expectField( 'key', $key ),
|
|
$I->expectField( 'quantity', 4 )
|
|
]
|
|
)
|
|
]
|
|
)
|
|
]
|
|
);
|
|
}
|
|
}
|