Files
wp-graphql-woocommerce/tests/functional/VariableProductPerformanceCest.php
Geoff TaylorandGitHub 858887fa78 devops: Variable product performance optimization (#1006)
* devops: Variable product performance optimization and tests

- Memoize get_variation_prices() in the Product model to avoid
  redundant lookups across multiple pricing fields (price, regularPrice,
  salePrice, and their RAW variants)
- Remove redundant post__in filter from variations connection resolver;
  post_parent already constrains the query, and the post__in triggered
  an extra get_children() call per product
- Add createVariableProductCatalog() helper to GraphQLE2E for creating
  variable products with many variations in tests
- Add VariableProductPerformanceTest (wpunit) measuring DB query count
  and duration for 15 variable products with 18 variations each
- Add VariableProductPerformanceCest (functional) verifying 6 rapid
  queries do not return 429 errors

Addresses #897

* fix: Skip timing assertion when xdebug is active and clean up debug code
2026-03-31 09:17:44 -04:00

60 lines
1.5 KiB
PHP

<?php
/**
* Tests that querying variable products with many variations does not
* trigger 429 errors from excessive response times or resource usage.
*
* @see https://github.com/wp-graphql/wp-graphql-woocommerce/issues/897
*/
class VariableProductPerformanceCest {
public function _before( FunctionalTester $I ) {
$I->createVariableProductCatalog( 10, 18 );
}
/**
* Test that sending multiple rapid product queries does not return 429 errors.
*/
public function testRapidVariableProductQueriesDoNotReturn429( FunctionalTester $I ) {
$query = '
query {
products(first: 10, where: { type: VARIABLE }) {
nodes {
... on VariableProduct {
databaseId
name
price
regularPrice
salePrice
variations(first: 5) {
nodes {
databaseId
price
regularPrice
}
}
}
}
}
}
';
// Fire 6 rapid queries — the reporter says 429 hits at ~6-7 executions.
$error_count = 0;
for ( $i = 0; $i < 6; $i++ ) {
$response = $I->sendGraphQLRequest( $query, null );
if ( empty( $response ) || ! isset( $response['data'] ) ) {
$error_count++;
codecept_debug( "Request {$i} failed or returned non-JSON response." );
continue;
}
$I->assertArrayHasKey( 'products', $response['data'] );
$nodes = $response['data']['products']['nodes'];
$I->assertNotEmpty( $nodes, "Request {$i} returned empty products." );
}
$I->assertEquals( 0, $error_count, "{$error_count} of 6 rapid queries returned errors (likely 429)." );
}
}