mirror of
https://gh.wpcy.net/https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2026-04-28 03:09:16 +08:00
This commit adds unit tests for the Agentic Commerce ingestion functionality: - Add tests for ProductsPayload class covering simple products, variable products, and edge cases - Add tests for IngestionBatchProvider with various batch scenarios and priority handling - Add tests for SyncJob including successful syncs, error handling, and metadata updates - Add ProductsPayloadFactory to enable dependency injection in SyncJob - Add ProductStatus stub for WooCommerce enum compatibility - Update patchwork.json to support mocking of date functions in tests
358 lines
No EOL
10 KiB
PHP
358 lines
No EOL
10 KiB
PHP
<?php
|
|
declare( strict_types = 1 );
|
|
|
|
namespace WooCommerce\PayPalCommerce\AgenticCommerce\Ingestion;
|
|
|
|
use WooCommerce\PayPalCommerce\TestCase;
|
|
use Automattic\WooCommerce\Enums\ProductStatus;
|
|
use function Brain\Monkey\Functions\when;
|
|
|
|
/**
|
|
* @covers IngestionBatchProvider
|
|
*/
|
|
class IngestionBatchProviderTest extends TestCase {
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
private $stale_timeout_days = 7;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
private $product_types = array( 'simple', 'variable' );
|
|
|
|
/**
|
|
* @var IngestionBatchProvider
|
|
*/
|
|
private $provider;
|
|
|
|
public function setUp(): void {
|
|
parent::setUp();
|
|
|
|
$this->provider = new IngestionBatchProvider(
|
|
$this->stale_timeout_days,
|
|
$this->product_types
|
|
);
|
|
|
|
// Mock WordPress date functions
|
|
when( 'gmdate' )->alias( function( $format, $timestamp = null ) {
|
|
if ( $timestamp === null ) {
|
|
$timestamp = time();
|
|
}
|
|
return gmdate( $format, $timestamp );
|
|
} );
|
|
|
|
when( 'strtotime' )->alias( 'strtotime' );
|
|
}
|
|
|
|
public function test_get_batch_returns_never_synced_products_first(): void {
|
|
// Arrange
|
|
$never_synced_ids = array( 1, 2, 3, 4, 5 );
|
|
$limit = 10;
|
|
|
|
// Mock wc_get_products calls
|
|
when( 'wc_get_products' )->alias( function( $args ) use ( $never_synced_ids ) {
|
|
// First call - products never synced
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_last_sync' &&
|
|
$args['meta_query'][0]['compare'] === 'NOT EXISTS' ) {
|
|
$this->assertEquals( ProductStatus::PUBLISH, $args['status'] );
|
|
$this->assertEquals( $this->product_types, $args['type'] );
|
|
$this->assertFalse( $args['downloadable'] );
|
|
$this->assertEquals( 10, $args['limit'] );
|
|
$this->assertEquals( 'ids', $args['return'] );
|
|
return $never_synced_ids;
|
|
}
|
|
|
|
// Second call - products needing sync
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_needs_sync' ) {
|
|
$this->assertEquals( 5, $args['limit'] ); // 10 - 5 already found
|
|
return array( 6, 7 );
|
|
}
|
|
|
|
// Third call - stale products
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_last_sync' &&
|
|
$args['meta_query'][0]['compare'] === '<' ) {
|
|
$this->assertEquals( 3, $args['limit'] ); // 10 - 7 already found
|
|
$this->assertEquals( 'DATETIME', $args['meta_query'][0]['type'] );
|
|
$this->assertEquals( 'meta_value', $args['orderby'] );
|
|
$this->assertEquals( 'ASC', $args['order'] );
|
|
$this->assertEquals( '_ppcp_agentic_last_sync', $args['meta_key'] );
|
|
return array( 8, 9, 10 );
|
|
}
|
|
|
|
return array();
|
|
} );
|
|
|
|
// Act
|
|
$result = $this->provider->get_batch( $limit );
|
|
|
|
// Assert
|
|
$this->assertEquals( array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ), $result );
|
|
}
|
|
|
|
public function test_get_batch_respects_limit_with_never_synced_products(): void {
|
|
// Arrange
|
|
$never_synced_ids = array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
|
|
$limit = 5;
|
|
|
|
when( 'wc_get_products' )->alias( function( $args ) use ( $never_synced_ids ) {
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_last_sync' &&
|
|
$args['meta_query'][0]['compare'] === 'NOT EXISTS' ) {
|
|
$this->assertEquals( 5, $args['limit'] );
|
|
return array_slice( $never_synced_ids, 0, 5 );
|
|
}
|
|
return array();
|
|
} );
|
|
|
|
// Act
|
|
$result = $this->provider->get_batch( $limit );
|
|
|
|
// Assert
|
|
$this->assertEquals( array( 1, 2, 3, 4, 5 ), $result );
|
|
$this->assertCount( 5, $result );
|
|
}
|
|
|
|
public function test_get_batch_returns_dirty_products_when_no_never_synced(): void {
|
|
// Arrange
|
|
$dirty_product_ids = array( 11, 12, 13 );
|
|
$limit = 5;
|
|
|
|
when( 'wc_get_products' )->alias( function( $args ) use ( $dirty_product_ids ) {
|
|
// First call - no never synced products
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_last_sync' &&
|
|
$args['meta_query'][0]['compare'] === 'NOT EXISTS' ) {
|
|
return array();
|
|
}
|
|
|
|
// Second call - products needing sync
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_needs_sync' ) {
|
|
$this->assertEquals( 5, $args['limit'] );
|
|
return $dirty_product_ids;
|
|
}
|
|
|
|
// Third call - stale products
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_last_sync' &&
|
|
$args['meta_query'][0]['compare'] === '<' ) {
|
|
$this->assertEquals( 2, $args['limit'] ); // 5 - 3 already found
|
|
return array( 14, 15 );
|
|
}
|
|
|
|
return array();
|
|
} );
|
|
|
|
// Act
|
|
$result = $this->provider->get_batch( $limit );
|
|
|
|
// Assert
|
|
$this->assertEquals( array( 11, 12, 13, 14, 15 ), $result );
|
|
}
|
|
|
|
public function test_get_batch_returns_stale_products_when_no_other_products(): void {
|
|
// Arrange
|
|
$stale_product_ids = array( 21, 22, 23, 24 );
|
|
$limit = 5;
|
|
|
|
when( 'wc_get_products' )->alias( function( $args ) use ( $stale_product_ids ) {
|
|
// First call - no never synced products
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_last_sync' &&
|
|
$args['meta_query'][0]['compare'] === 'NOT EXISTS' ) {
|
|
return array();
|
|
}
|
|
|
|
// Second call - no dirty products
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_needs_sync' ) {
|
|
return array();
|
|
}
|
|
|
|
// Third call - stale products
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_last_sync' &&
|
|
$args['meta_query'][0]['compare'] === '<' ) {
|
|
$this->assertEquals( 5, $args['limit'] );
|
|
|
|
// Verify stale date calculation
|
|
$expected_stale_date = gmdate( 'Y-m-d H:i:s', strtotime( '-7 days' ) );
|
|
$this->assertEquals( $expected_stale_date, $args['meta_query'][0]['value'] );
|
|
|
|
return $stale_product_ids;
|
|
}
|
|
|
|
return array();
|
|
} );
|
|
|
|
// Act
|
|
$result = $this->provider->get_batch( $limit );
|
|
|
|
// Assert
|
|
$this->assertEquals( $stale_product_ids, $result );
|
|
}
|
|
|
|
public function test_get_batch_returns_empty_array_when_no_products(): void {
|
|
// Arrange
|
|
when( 'wc_get_products' )->justReturn( array() );
|
|
|
|
// Act
|
|
$result = $this->provider->get_batch( 50 );
|
|
|
|
// Assert
|
|
$this->assertEquals( array(), $result );
|
|
}
|
|
|
|
public function test_get_batch_uses_correct_product_query_parameters(): void {
|
|
// Arrange
|
|
$limit = 50;
|
|
$call_count = 0;
|
|
|
|
when( 'wc_get_products' )->alias( function( $args ) use ( &$call_count ) {
|
|
$call_count++;
|
|
|
|
// Common assertions for all calls
|
|
$this->assertEquals( 'publish', $args['status'] );
|
|
$this->assertEquals( $this->product_types, $args['type'] );
|
|
$this->assertFalse( $args['downloadable'] );
|
|
$this->assertEquals( 'ids', $args['return'] );
|
|
|
|
// Return different results to trigger all three queries
|
|
if ( $call_count === 1 ) {
|
|
return array( 1, 2 );
|
|
} elseif ( $call_count === 2 ) {
|
|
return array( 3, 4 );
|
|
} else {
|
|
return array( 5, 6 );
|
|
}
|
|
} );
|
|
|
|
// Act
|
|
$result = $this->provider->get_batch( $limit );
|
|
|
|
// Assert
|
|
$this->assertEquals( 3, $call_count );
|
|
$this->assertEquals( array( 1, 2, 3, 4, 5, 6 ), $result );
|
|
}
|
|
|
|
public function test_get_batch_with_custom_stale_timeout(): void {
|
|
// Arrange
|
|
$custom_timeout_days = 30;
|
|
$custom_provider = new IngestionBatchProvider(
|
|
$custom_timeout_days,
|
|
$this->product_types
|
|
);
|
|
|
|
when( 'wc_get_products' )->alias( function( $args ) use ( $custom_timeout_days ) {
|
|
// Skip to stale products check
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_last_sync' &&
|
|
$args['meta_query'][0]['compare'] === '<' ) {
|
|
|
|
$expected_stale_date = gmdate( 'Y-m-d H:i:s', strtotime( '-30 days' ) );
|
|
$this->assertEquals( $expected_stale_date, $args['meta_query'][0]['value'] );
|
|
|
|
return array( 100, 101, 102 );
|
|
}
|
|
|
|
return array();
|
|
} );
|
|
|
|
// Act
|
|
$result = $custom_provider->get_batch( 10 );
|
|
|
|
// Assert
|
|
$this->assertContains( 100, $result );
|
|
$this->assertContains( 101, $result );
|
|
$this->assertContains( 102, $result );
|
|
}
|
|
|
|
public function test_get_batch_with_custom_product_types(): void {
|
|
// Arrange
|
|
$custom_types = array( 'simple', 'variable', 'grouped' );
|
|
$custom_provider = new IngestionBatchProvider(
|
|
$this->stale_timeout_days,
|
|
$custom_types
|
|
);
|
|
|
|
when( 'wc_get_products' )->alias( function( $args ) use ( $custom_types ) {
|
|
$this->assertEquals( $custom_types, $args['type'] );
|
|
return array( 1, 2, 3 );
|
|
} );
|
|
|
|
// Act
|
|
$result = $custom_provider->get_batch( 10 );
|
|
|
|
// Assert
|
|
$this->assertNotEmpty( $result );
|
|
}
|
|
|
|
public function test_get_batch_handles_mixed_results(): void {
|
|
// Arrange
|
|
$limit = 15;
|
|
|
|
when( 'wc_get_products' )->alias( function( $args ) {
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_last_sync' &&
|
|
$args['meta_query'][0]['compare'] === 'NOT EXISTS' ) {
|
|
return array( 1, 2, 3, 4, 5 );
|
|
}
|
|
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_needs_sync' ) {
|
|
$this->assertEquals( 10, $args['limit'] ); // 15 - 5
|
|
return array( 6, 7, 8, 9, 10 );
|
|
}
|
|
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_last_sync' &&
|
|
$args['meta_query'][0]['compare'] === '<' ) {
|
|
$this->assertEquals( 5, $args['limit'] ); // 15 - 10
|
|
return array( 11, 12, 13, 14, 15 );
|
|
}
|
|
|
|
return array();
|
|
} );
|
|
|
|
// Act
|
|
$result = $this->provider->get_batch( $limit );
|
|
|
|
// Assert
|
|
$this->assertCount( 15, $result );
|
|
$this->assertEquals( range( 1, 15 ), $result );
|
|
}
|
|
|
|
public function test_get_batch_stops_when_limit_reached_after_dirty_products(): void {
|
|
// Arrange
|
|
$limit = 7;
|
|
|
|
when( 'wc_get_products' )->alias( function( $args ) {
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_last_sync' &&
|
|
$args['meta_query'][0]['compare'] === 'NOT EXISTS' ) {
|
|
return array( 1, 2, 3 );
|
|
}
|
|
|
|
if ( isset( $args['meta_query'][0]['key'] ) &&
|
|
$args['meta_query'][0]['key'] === '_ppcp_agentic_needs_sync' ) {
|
|
return array( 4, 5, 6, 7 );
|
|
}
|
|
|
|
// This should not be called
|
|
$this->fail( 'Should not query for stale products when limit is reached' );
|
|
return array();
|
|
} );
|
|
|
|
// Act
|
|
$result = $this->provider->get_batch( $limit );
|
|
|
|
// Assert
|
|
$this->assertCount( 7, $result );
|
|
$this->assertEquals( array( 1, 2, 3, 4, 5, 6, 7 ), $result );
|
|
}
|
|
} |