And deletion sync related tests for OrdersTableDataStore.
Also: - toggle_cot renamed to toggle_cot_feature_and_usage includes HPOSToggleTrais for clarity. - DataSynchronizerTests and OrdersTableDataStoreTests now inherit from a common HposTestCase class.
This commit is contained in:
parent
bafcd8752a
commit
48081b3351
|
@ -331,5 +331,4 @@ class OrderHelper {
|
||||||
|
|
||||||
return $order;
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,14 +28,14 @@ trait HPOSToggleTrait {
|
||||||
OrderHelper::delete_order_custom_tables();
|
OrderHelper::delete_order_custom_tables();
|
||||||
OrderHelper::create_order_custom_table_if_not_exist();
|
OrderHelper::create_order_custom_table_if_not_exist();
|
||||||
|
|
||||||
$this->toggle_cot( true );
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call in teardown to disable COT/HPOS.
|
* Call in teardown to disable COT/HPOS.
|
||||||
*/
|
*/
|
||||||
public function clean_up_cot_setup(): void {
|
public function clean_up_cot_setup(): void {
|
||||||
$this->toggle_cot( false );
|
$this->toggle_cot_feature_and_usage( false );
|
||||||
|
|
||||||
// Add back removed filter.
|
// Add back removed filter.
|
||||||
add_filter( 'query', array( $this, '_create_temporary_tables' ) );
|
add_filter( 'query', array( $this, '_create_temporary_tables' ) );
|
||||||
|
@ -43,12 +43,12 @@ trait HPOSToggleTrait {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables or disables the custom orders table across WP temporarily.
|
* Enables or disables the custom orders table feature, and sets the orders table as authoritative, across WP temporarily.
|
||||||
*
|
*
|
||||||
* @param boolean $enabled TRUE to enable COT or FALSE to disable.
|
* @param boolean $enabled TRUE to enable COT or FALSE to disable.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function toggle_cot( bool $enabled ): void {
|
private function toggle_cot_feature_and_usage( bool $enabled ): void {
|
||||||
$features_controller = wc_get_container()->get( Featurescontroller::class );
|
$features_controller = wc_get_container()->get( Featurescontroller::class );
|
||||||
$features_controller->change_feature_enable( 'custom_order_tables', $enabled );
|
$features_controller->change_feature_enable( 'custom_order_tables', $enabled );
|
||||||
|
|
||||||
|
@ -59,6 +59,14 @@ trait HPOSToggleTrait {
|
||||||
assert( is_a( $wc_data_store->get_current_class_name(), OrdersTableDataStore::class, true ) === $enabled );
|
assert( is_a( $wc_data_store->get_current_class_name(), OrdersTableDataStore::class, true ) === $enabled );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the orders table or the posts table as the authoritative table to store orders.
|
||||||
|
* @param bool $cot_authoritative True to set the orders table as authoritative, false to set the posts table as authoritative.
|
||||||
|
*/
|
||||||
|
protected function toggle_cot_authoritative( bool $cot_authoritative ) {
|
||||||
|
update_option( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION, wc_bool_to_string( $cot_authoritative ) );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to enable COT <> Posts sync.
|
* Helper function to enable COT <> Posts sync.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,7 +14,7 @@ class WC_User_Functions_Tests extends WC_Unit_Test_Case {
|
||||||
public function setUp(): void {
|
public function setUp(): void {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$this->setup_cot();
|
$this->setup_cot();
|
||||||
$this->toggle_cot( false );
|
$this->toggle_cot_feature_and_usage( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,7 +29,7 @@ class WC_User_Functions_Tests extends WC_Unit_Test_Case {
|
||||||
* Test wc_get_customer_order_count. Borrowed from `WC_Tests_Customer_Functions` class for COT.
|
* Test wc_get_customer_order_count. Borrowed from `WC_Tests_Customer_Functions` class for COT.
|
||||||
*/
|
*/
|
||||||
public function test_hpos_wc_customer_bought_product() {
|
public function test_hpos_wc_customer_bought_product() {
|
||||||
$this->toggle_cot( true );
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
$customer_id_1 = wc_create_new_customer( 'test@example.com', 'testuser', 'testpassword' );
|
$customer_id_1 = wc_create_new_customer( 'test@example.com', 'testuser', 'testpassword' );
|
||||||
$customer_id_2 = wc_create_new_customer( 'test2@example.com', 'testuser2', 'testpassword2' );
|
$customer_id_2 = wc_create_new_customer( 'test2@example.com', 'testuser2', 'testpassword2' );
|
||||||
$product_1 = new WC_Product_Simple();
|
$product_1 = new WC_Product_Simple();
|
||||||
|
|
|
@ -5,13 +5,17 @@ use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer;
|
||||||
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
|
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
|
||||||
use Automattic\WooCommerce\Internal\Features\FeaturesController;
|
use Automattic\WooCommerce\Internal\Features\FeaturesController;
|
||||||
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
|
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
|
||||||
|
use Automattic\WooCommerce\RestApi\UnitTests\HPOSToggleTrait;
|
||||||
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
|
use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../../../helpers/HPOSToggleTrait.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for DataSynchronizer class.
|
* Tests for DataSynchronizer class.
|
||||||
*/
|
*/
|
||||||
class DataSynchronizerTests extends WC_Unit_Test_Case {
|
class DataSynchronizerTests extends HposTestCase {
|
||||||
use ArraySubsetAsserts;
|
use ArraySubsetAsserts;
|
||||||
|
use HPOSToggleTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var DataSynchronizer
|
* @var DataSynchronizer
|
||||||
|
@ -231,23 +235,23 @@ class DataSynchronizerTests extends WC_Unit_Test_Case {
|
||||||
* @param bool $manual_sync True to trigger synchronization manually, false if automatic synchronization is enabled.
|
* @param bool $manual_sync True to trigger synchronization manually, false if automatic synchronization is enabled.
|
||||||
*/
|
*/
|
||||||
public function test_synced_order_deletion_with_sync_disabled_and_posts_authoritative_generates_proper_deletion_record_if_cot_record_exists( bool $manual_sync ) {
|
public function test_synced_order_deletion_with_sync_disabled_and_posts_authoritative_generates_proper_deletion_record_if_cot_record_exists( bool $manual_sync ) {
|
||||||
$this->set_posts_authoritative();
|
$this->toggle_cot_authoritative( false );
|
||||||
|
|
||||||
if ( $manual_sync ) {
|
if ( $manual_sync ) {
|
||||||
$this->disable_data_sync();
|
$this->disable_cot_sync();
|
||||||
$order = OrderHelper::create_order();
|
$order = OrderHelper::create_order();
|
||||||
$this->do_sync();
|
$this->do_cot_sync();
|
||||||
} else {
|
} else {
|
||||||
$this->enable_data_sync();
|
$this->enable_cot_sync();
|
||||||
$order = OrderHelper::create_order();
|
$order = OrderHelper::create_order();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->disable_data_sync();
|
$this->disable_cot_sync();
|
||||||
$order_id = $order->get_id();
|
$order_id = $order->get_id();
|
||||||
$order->delete( true );
|
$order->delete( true );
|
||||||
|
|
||||||
$this->assert_deletion_record_existence( $order_id, false );
|
$this->assert_deletion_record_existence( $order_id, false );
|
||||||
$this->assert_order_record_existence( $order_id, true );
|
$this->assert_order_record_existence( $order_id, true, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -256,8 +260,8 @@ class DataSynchronizerTests extends WC_Unit_Test_Case {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function test_synced_order_deletion_with_sync_disabled_and_posts_authoritative_not_generating_deletion_record_if_cot_record_not_exists() {
|
public function test_synced_order_deletion_with_sync_disabled_and_posts_authoritative_not_generating_deletion_record_if_cot_record_not_exists() {
|
||||||
$this->set_posts_authoritative();
|
$this->toggle_cot_authoritative( false );
|
||||||
$this->disable_data_sync();
|
$this->disable_cot_sync();
|
||||||
$order = OrderHelper::create_order();
|
$order = OrderHelper::create_order();
|
||||||
|
|
||||||
$order_id = $order->get_id();
|
$order_id = $order->get_id();
|
||||||
|
@ -282,19 +286,15 @@ class DataSynchronizerTests extends WC_Unit_Test_Case {
|
||||||
|
|
||||||
$meta_table_name = OrdersTableDataStore::get_meta_table_name();
|
$meta_table_name = OrdersTableDataStore::get_meta_table_name();
|
||||||
|
|
||||||
if ( $cot_is_authoritative ) {
|
$this->toggle_cot_authoritative( $cot_is_authoritative );
|
||||||
$this->set_cot_authoritative();
|
|
||||||
} else {
|
|
||||||
$this->set_posts_authoritative();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->enable_data_sync();
|
$this->enable_cot_sync();
|
||||||
$order_1 = OrderHelper::create_order();
|
$order_1 = OrderHelper::create_order();
|
||||||
$order_2 = OrderHelper::create_order();
|
$order_2 = OrderHelper::create_order();
|
||||||
$order_3 = OrderHelper::create_order();
|
$order_3 = OrderHelper::create_order();
|
||||||
$order_4 = OrderHelper::create_order();
|
$order_4 = OrderHelper::create_order();
|
||||||
|
|
||||||
$this->disable_data_sync();
|
$this->disable_cot_sync();
|
||||||
if ( $new_records_exist ) {
|
if ( $new_records_exist ) {
|
||||||
$order_5 = OrderHelper::create_order();
|
$order_5 = OrderHelper::create_order();
|
||||||
}
|
}
|
||||||
|
@ -323,19 +323,15 @@ class DataSynchronizerTests extends WC_Unit_Test_Case {
|
||||||
* @param bool $cot_is_authoritative True to test with the orders table as authoritative, false to test with the posts table as authoritative.
|
* @param bool $cot_is_authoritative True to test with the orders table as authoritative, false to test with the posts table as authoritative.
|
||||||
*/
|
*/
|
||||||
public function test_process_batch_processes_modified_and_deleted_orders( bool $cot_is_authoritative ) {
|
public function test_process_batch_processes_modified_and_deleted_orders( bool $cot_is_authoritative ) {
|
||||||
if ( $cot_is_authoritative ) {
|
$this->toggle_cot_authoritative( $cot_is_authoritative );
|
||||||
$this->set_cot_authoritative();
|
$this->enable_cot_sync();
|
||||||
} else {
|
|
||||||
$this->set_posts_authoritative();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->enable_data_sync();
|
|
||||||
$order_1 = OrderHelper::create_order();
|
$order_1 = OrderHelper::create_order();
|
||||||
$order_2 = OrderHelper::create_order();
|
$order_2 = OrderHelper::create_order();
|
||||||
$order_3 = OrderHelper::create_order();
|
$order_3 = OrderHelper::create_order();
|
||||||
$order_4 = OrderHelper::create_order();
|
$order_4 = OrderHelper::create_order();
|
||||||
|
|
||||||
$this->disable_data_sync();
|
$this->disable_cot_sync();
|
||||||
|
|
||||||
$order_1->set_date_modified( '2100-01-01 00:00:00' );
|
$order_1->set_date_modified( '2100-01-01 00:00:00' );
|
||||||
$order_1->save();
|
$order_1->save();
|
||||||
|
@ -387,22 +383,19 @@ class DataSynchronizerTests extends WC_Unit_Test_Case {
|
||||||
$this->register_legacy_proxy_function_mocks(
|
$this->register_legacy_proxy_function_mocks(
|
||||||
array(
|
array(
|
||||||
'wc_get_logger' => function() use ( $logger ) {
|
'wc_get_logger' => function() use ( $logger ) {
|
||||||
return $logger;},
|
return $logger;
|
||||||
|
},
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->sut = wc_get_container()->get( DataSynchronizer::class );
|
$this->sut = wc_get_container()->get( DataSynchronizer::class );
|
||||||
|
|
||||||
if ( $cot_is_authoritative ) {
|
$this->toggle_cot_authoritative( $cot_is_authoritative );
|
||||||
$this->set_cot_authoritative();
|
$this->enable_cot_sync();
|
||||||
} else {
|
|
||||||
$this->set_posts_authoritative();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->enable_data_sync();
|
|
||||||
$order_1 = OrderHelper::create_order();
|
$order_1 = OrderHelper::create_order();
|
||||||
$order_2 = OrderHelper::create_order();
|
$order_2 = OrderHelper::create_order();
|
||||||
|
|
||||||
$this->disable_data_sync();
|
$this->disable_cot_sync();
|
||||||
|
|
||||||
$order_1_id = $order_1->get_id();
|
$order_1_id = $order_1->get_id();
|
||||||
$order_1->delete( true );
|
$order_1->delete( true );
|
||||||
|
@ -419,104 +412,4 @@ class DataSynchronizerTests extends WC_Unit_Test_Case {
|
||||||
|
|
||||||
$this->assertEquals( array( "Order {$order_1_id} doesn't exist in the backup table, thus it can't be deleted" ), $logger->warnings );
|
$this->assertEquals( array( "Order {$order_1_id} doesn't exist in the backup table, thus it can't be deleted" ), $logger->warnings );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Assert that a given order record exists or doesn't exist.
|
|
||||||
*
|
|
||||||
* @param int $order_id The order id to check.
|
|
||||||
* @param bool $in_cot True to assert that the order exists or not in the orders table, false to check in the posts table.
|
|
||||||
* @param bool $exists True to assert that the order exists, false to check that the order doesn't exist.
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function assert_order_record_existence( $order_id, $in_cot, $exists = true ) {
|
|
||||||
global $wpdb;
|
|
||||||
|
|
||||||
$table_name = $in_cot ? OrdersTableDataStore::get_orders_table_name() : $wpdb->posts;
|
|
||||||
|
|
||||||
//phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
||||||
$exists = $wpdb->get_var(
|
|
||||||
$wpdb->prepare(
|
|
||||||
"SELECT EXISTS (SELECT id FROM {$table_name} WHERE id = %d)",
|
|
||||||
$order_id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
//phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
||||||
|
|
||||||
if ( $exists ) {
|
|
||||||
$this->assertTrue( (bool) $exists, "No order found with id $order_id in table $table_name" );
|
|
||||||
} else {
|
|
||||||
$this->assertFalse( (bool) $exists, "Unexpected order found with id $order_id in table $table_name" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assert that an order deletion record exists or doesn't exist in the orders meta table.
|
|
||||||
*
|
|
||||||
* @param int $order_id The order id to check.
|
|
||||||
* @param bool $deleted_from_cot True to assert that the record corresponds to an order deleted from the orders table, or from the posts table otherwise.
|
|
||||||
* @param bool $exists True to assert that the record exists, false to assert that the record doesn't exist.
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private function assert_deletion_record_existence( $order_id, $deleted_from_cot, $exists = true ) {
|
|
||||||
global $wpdb;
|
|
||||||
|
|
||||||
$meta_table_name = OrdersTableDataStore::get_meta_table_name();
|
|
||||||
//phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
||||||
$record = $wpdb->get_row(
|
|
||||||
$wpdb->prepare(
|
|
||||||
"SELECT meta_value FROM $meta_table_name WHERE order_id = %d AND meta_key = %s",
|
|
||||||
$order_id,
|
|
||||||
'deleted_from'
|
|
||||||
),
|
|
||||||
ARRAY_A
|
|
||||||
);
|
|
||||||
//phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
|
||||||
|
|
||||||
if ( $exists ) {
|
|
||||||
$this->assertNotNull( $record, "No deletion record found for order id {$order_id}, value: {$record['meta_value']}" );
|
|
||||||
} else {
|
|
||||||
$this->assertNull( $record, "Unexpected deletion record found for order id {$order_id}" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$deleted_from = $deleted_from_cot ? OrdersTableDataStore::get_orders_table_name() : $wpdb->posts;
|
|
||||||
|
|
||||||
$this->assertEquals( $deleted_from, $record['meta_value'], "Deletion record for order {$order_id} has a value of {$record['meta_value']}, expected {$deleted_from}" );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronize all the pending unsynchronized orders.
|
|
||||||
*/
|
|
||||||
private function do_sync() {
|
|
||||||
$batch = $this->sut->get_next_batch_to_process( 100 );
|
|
||||||
$this->sut->process_batch( $batch );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the orders table as authoritative.
|
|
||||||
*/
|
|
||||||
private function set_cot_authoritative() {
|
|
||||||
update_option( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION, 'yes' );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the posts table as authoritative.
|
|
||||||
*/
|
|
||||||
private function set_posts_authoritative() {
|
|
||||||
update_option( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION, 'no' );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable the orders synchronization.
|
|
||||||
*/
|
|
||||||
private function enable_data_sync() {
|
|
||||||
update_option( $this->sut::ORDERS_DATA_SYNC_ENABLED_OPTION, 'yes' );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disable the orders synchronization.
|
|
||||||
*/
|
|
||||||
private function disable_data_sync() {
|
|
||||||
update_option( $this->sut::ORDERS_DATA_SYNC_ENABLED_OPTION, 'no' );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer;
|
||||||
|
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for HPOS related unit test suites.
|
||||||
|
*/
|
||||||
|
class HposTestCase extends WC_Unit_Test_Case {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that a given order record exists or doesn't exist.
|
||||||
|
*
|
||||||
|
* @param int $order_id The order id to check.
|
||||||
|
* @param bool $in_cot True to assert that the order exists or not in the orders table, false to check in the posts table.
|
||||||
|
* @param bool $must_exist True to assert that the order exists, false to check that the order doesn't exist.
|
||||||
|
* @param string $order_type Expected order type, null to accept any type that starts with "shop_order".
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function assert_order_record_existence( $order_id, $in_cot, $must_exist, $order_type = null ) {
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
$table_name = $in_cot ? OrdersTableDataStore::get_orders_table_name() : $wpdb->posts;
|
||||||
|
$order_type = $order_type ?? 'shop_order%';
|
||||||
|
$sql = $in_cot ?
|
||||||
|
"SELECT EXISTS (SELECT id FROM $table_name WHERE id = %d)" :
|
||||||
|
"SELECT EXISTS (SELECT ID FROM $table_name WHERE ID = %d AND post_type LIKE %s)";
|
||||||
|
|
||||||
|
//phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||||
|
$exists = $wpdb->get_var(
|
||||||
|
$in_cot ?
|
||||||
|
$wpdb->prepare( $sql, $order_id ) :
|
||||||
|
$wpdb->prepare( $sql, $order_id, $order_type )
|
||||||
|
);
|
||||||
|
//phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
|
||||||
|
|
||||||
|
if ( $must_exist ) {
|
||||||
|
$this->assertTrue( (bool) $exists, "No order found with id $order_id in table $table_name" );
|
||||||
|
} else {
|
||||||
|
$this->assertFalse( (bool) $exists, "Unexpected order found with id $order_id in table $table_name" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert that an order deletion record exists or doesn't exist in the orders meta table.
|
||||||
|
*
|
||||||
|
* @param int $order_id The order id to check.
|
||||||
|
* @param bool $deleted_from_cot True to assert that the record corresponds to an order deleted from the orders table, or from the posts table otherwise.
|
||||||
|
* @param bool $must_exist True to assert that the record exists, false to assert that the record doesn't exist.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function assert_deletion_record_existence( $order_id, $deleted_from_cot, $must_exist = true ) {
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
$meta_table_name = OrdersTableDataStore::get_meta_table_name();
|
||||||
|
//phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||||
|
$record = $wpdb->get_row(
|
||||||
|
$wpdb->prepare(
|
||||||
|
"SELECT meta_value FROM $meta_table_name WHERE order_id = %d AND meta_key = %s",
|
||||||
|
$order_id,
|
||||||
|
'deleted_from'
|
||||||
|
),
|
||||||
|
ARRAY_A
|
||||||
|
);
|
||||||
|
//phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||||
|
|
||||||
|
if ( $must_exist ) {
|
||||||
|
$this->assertNotNull( $record, "No deletion record found for order id {$order_id}" );
|
||||||
|
} else {
|
||||||
|
$this->assertNull( $record, "Unexpected deletion record found for order id {$order_id}" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$deleted_from = $deleted_from_cot ? OrdersTableDataStore::get_orders_table_name() : $wpdb->posts;
|
||||||
|
|
||||||
|
$this->assertEquals( $deleted_from, $record['meta_value'], "Deletion record for order {$order_id} has a value of {$record['meta_value']}, expected {$deleted_from}" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize all the pending unsynchronized orders.
|
||||||
|
*/
|
||||||
|
protected function do_cot_sync() {
|
||||||
|
$sync = wc_get_container()->get( DataSynchronizer::class );
|
||||||
|
$batch = $sync->get_next_batch_to_process( 100 );
|
||||||
|
$sync->process_batch( $batch );
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,14 +29,14 @@ class OrdersTableDataStoreRestOrdersControllerTests extends \WC_REST_Orders_Cont
|
||||||
OrderHelper::delete_order_custom_tables();
|
OrderHelper::delete_order_custom_tables();
|
||||||
OrderHelper::create_order_custom_table_if_not_exist();
|
OrderHelper::create_order_custom_table_if_not_exist();
|
||||||
|
|
||||||
$this->toggle_cot( true );
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys system under test.
|
* Destroys system under test.
|
||||||
*/
|
*/
|
||||||
public function tearDown(): void {
|
public function tearDown(): void {
|
||||||
$this->toggle_cot( false );
|
$this->toggle_cot_feature_and_usage( false );
|
||||||
|
|
||||||
// Add back removed filter.
|
// Add back removed filter.
|
||||||
add_filter( 'query', array( $this, '_create_temporary_tables' ) );
|
add_filter( 'query', array( $this, '_create_temporary_tables' ) );
|
||||||
|
@ -51,7 +51,7 @@ class OrdersTableDataStoreRestOrdersControllerTests extends \WC_REST_Orders_Cont
|
||||||
public function test_orders_cpt() {
|
public function test_orders_cpt() {
|
||||||
wp_set_current_user( $this->user );
|
wp_set_current_user( $this->user );
|
||||||
|
|
||||||
$this->toggle_cot( false );
|
$this->toggle_cot_feature_and_usage( false );
|
||||||
$post_order_id = OrderHelper::create_complex_wp_post_order();
|
$post_order_id = OrderHelper::create_complex_wp_post_order();
|
||||||
( wc_get_container()->get( PostsToOrdersMigrationController::class ) )->migrate_orders( array( $post_order_id ) );
|
( wc_get_container()->get( PostsToOrdersMigrationController::class ) )->migrate_orders( array( $post_order_id ) );
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ class OrdersTableDataStoreRestOrdersControllerTests extends \WC_REST_Orders_Cont
|
||||||
$response_cpt_data = $response_cpt->get_data();
|
$response_cpt_data = $response_cpt->get_data();
|
||||||
|
|
||||||
// Re-enable COT.
|
// Re-enable COT.
|
||||||
$this->toggle_cot( true );
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
|
|
||||||
$response_cot = $this->server->dispatch( $request );
|
$response_cot = $this->server->dispatch( $request );
|
||||||
$this->assertEquals( 200, $response_cot->get_status() );
|
$this->assertEquals( 200, $response_cot->get_status() );
|
||||||
|
@ -91,7 +91,7 @@ class OrdersTableDataStoreRestOrdersControllerTests extends \WC_REST_Orders_Cont
|
||||||
* @param boolean $enabled TRUE to enable COT or FALSE to disable.
|
* @param boolean $enabled TRUE to enable COT or FALSE to disable.
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function toggle_cot( bool $enabled ): void {
|
private function toggle_cot_feature_and_usage( bool $enabled ): void {
|
||||||
$features_controller = wc_get_container()->get( Featurescontroller::class );
|
$features_controller = wc_get_container()->get( Featurescontroller::class );
|
||||||
$features_controller->change_feature_enable( 'custom_order_tables', true );
|
$features_controller->change_feature_enable( 'custom_order_tables', true );
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ require_once __DIR__ . '/../../../../helpers/HPOSToggleTrait.php';
|
||||||
*
|
*
|
||||||
* Test for OrdersTableDataStore class.
|
* Test for OrdersTableDataStore class.
|
||||||
*/
|
*/
|
||||||
class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
class OrdersTableDataStoreTests extends HposTestCase {
|
||||||
use HPOSToggleTrait;
|
use HPOSToggleTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,7 +50,7 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
// Remove the Test Suite’s use of temporary tables https://wordpress.stackexchange.com/a/220308.
|
// Remove the Test Suite’s use of temporary tables https://wordpress.stackexchange.com/a/220308.
|
||||||
$this->setup_cot();
|
$this->setup_cot();
|
||||||
$this->toggle_cot( false );
|
$this->toggle_cot_feature_and_usage( false );
|
||||||
$container = wc_get_container();
|
$container = wc_get_container();
|
||||||
$container->reset_all_resolved();
|
$container->reset_all_resolved();
|
||||||
$this->sut = $container->get( OrdersTableDataStore::class );
|
$this->sut = $container->get( OrdersTableDataStore::class );
|
||||||
|
@ -731,7 +731,7 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
||||||
* @testDox Tests queries involving 'orderby' and meta queries.
|
* @testDox Tests queries involving 'orderby' and meta queries.
|
||||||
*/
|
*/
|
||||||
public function test_cot_query_meta_orderby() {
|
public function test_cot_query_meta_orderby() {
|
||||||
$this->toggle_cot( true );
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
|
|
||||||
$order1 = new \WC_Order();
|
$order1 = new \WC_Order();
|
||||||
$order1->add_meta_data( 'color', 'red' );
|
$order1->add_meta_data( 'color', 'red' );
|
||||||
|
@ -1988,7 +1988,7 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
||||||
* @testDox Test that multiple calls to read don't try to sync again.
|
* @testDox Test that multiple calls to read don't try to sync again.
|
||||||
*/
|
*/
|
||||||
public function test_read_multiple_dont_sync_again_for_same_order() {
|
public function test_read_multiple_dont_sync_again_for_same_order() {
|
||||||
$this->toggle_cot( true );
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
$this->enable_cot_sync();
|
$this->enable_cot_sync();
|
||||||
$order = $this->create_complex_cot_order();
|
$order = $this->create_complex_cot_order();
|
||||||
|
|
||||||
|
@ -2018,7 +2018,7 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->toggle_cot( true );
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
$order = new WC_Order();
|
$order = new WC_Order();
|
||||||
$order->save();
|
$order->save();
|
||||||
|
|
||||||
|
@ -2045,7 +2045,7 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->toggle_cot( true );
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
$order = new WC_Order();
|
$order = new WC_Order();
|
||||||
$order->save();
|
$order->save();
|
||||||
|
|
||||||
|
@ -2064,7 +2064,7 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
||||||
* @testDox Make sure get_order return false when checking an order of different order types without warning.
|
* @testDox Make sure get_order return false when checking an order of different order types without warning.
|
||||||
*/
|
*/
|
||||||
public function test_get_order_with_id_for_different_type() {
|
public function test_get_order_with_id_for_different_type() {
|
||||||
$this->toggle_cot( true );
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
$this->disable_cot_sync();
|
$this->disable_cot_sync();
|
||||||
$product = new \WC_Product();
|
$product = new \WC_Product();
|
||||||
$product->save();
|
$product->save();
|
||||||
|
@ -2093,7 +2093,7 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
||||||
*/
|
*/
|
||||||
public function test_address_index_saved_on_update() {
|
public function test_address_index_saved_on_update() {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
$this->toggle_cot( true );
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
$this->disable_cot_sync();
|
$this->disable_cot_sync();
|
||||||
$order = new WC_Order();
|
$order = new WC_Order();
|
||||||
$order->set_billing_address_1( '123 Main St' );
|
$order->set_billing_address_1( '123 Main St' );
|
||||||
|
@ -2115,4 +2115,185 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
||||||
|
|
||||||
$this->assertEquals( 1, $result );
|
$this->assertEquals( 1, $result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @testdox When sync is enabled and an order is deleted, records in both the authoritative and the backup tables are deleted, and no deletion records are created.
|
||||||
|
*
|
||||||
|
* @testWith [true]
|
||||||
|
* [false]
|
||||||
|
*
|
||||||
|
* @param bool $cot_is_authoritative True to test with the orders table as authoritative, false to test with the posts table as authoritative.
|
||||||
|
*/
|
||||||
|
public function test_order_deletion_with_sync_enabled( bool $cot_is_authoritative ) {
|
||||||
|
$this->allow_current_user_to_delete_posts();
|
||||||
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
|
$this->toggle_cot_authoritative( $cot_is_authoritative );
|
||||||
|
$this->enable_cot_sync();
|
||||||
|
|
||||||
|
list($order, $refund) = $this->create_order_with_refund();
|
||||||
|
|
||||||
|
$order_id = $order->get_id();
|
||||||
|
$refund_id = $refund->get_id();
|
||||||
|
|
||||||
|
$order->delete( true );
|
||||||
|
|
||||||
|
$this->assert_no_order_records_or_deletion_records_exist( $order_id, $refund_id, $cot_is_authoritative );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @testdox Deletion records are created when an order is deleted with sync disabled, then when sync is enabled all order and deletion records are deleted.
|
||||||
|
*
|
||||||
|
* @testWith [true]
|
||||||
|
* [false]
|
||||||
|
*
|
||||||
|
* @param bool $cot_is_authoritative True to test with the orders table as authoritative, false to test with the posts table as authoritative.
|
||||||
|
*/
|
||||||
|
public function test_order_deletion_with_sync_disabled( bool $cot_is_authoritative ) {
|
||||||
|
$this->allow_current_user_to_delete_posts();
|
||||||
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
|
$this->toggle_cot_authoritative( $cot_is_authoritative );
|
||||||
|
$this->enable_cot_sync();
|
||||||
|
|
||||||
|
list($order, $refund) = $this->create_order_with_refund();
|
||||||
|
$order_id = $order->get_id();
|
||||||
|
$refund_id = $refund->get_id();
|
||||||
|
|
||||||
|
$this->disable_cot_sync();
|
||||||
|
$order->delete( true );
|
||||||
|
|
||||||
|
$this->assert_order_record_existence( $order_id, true, ! $cot_is_authoritative );
|
||||||
|
$this->assert_order_record_existence( $order_id, false, $cot_is_authoritative );
|
||||||
|
$this->assert_order_record_existence( $refund_id, true, ! $cot_is_authoritative );
|
||||||
|
$this->assert_order_record_existence( $refund_id, false, $cot_is_authoritative );
|
||||||
|
|
||||||
|
$this->assert_deletion_record_existence( $order_id, $cot_is_authoritative, true );
|
||||||
|
$this->assert_deletion_record_existence( $refund_id, $cot_is_authoritative, true );
|
||||||
|
|
||||||
|
$this->do_cot_sync();
|
||||||
|
|
||||||
|
$this->assert_no_order_records_or_deletion_records_exist( $order_id, $refund_id, $cot_is_authoritative );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @testdox When the orders table is authoritative, sync is disabled and an order is deleted, existing placeholder records are deleted from the posts table.
|
||||||
|
*/
|
||||||
|
public function test_order_deletion_with_sync_disabled_when_placeholders_are_created() {
|
||||||
|
$this->allow_current_user_to_delete_posts();
|
||||||
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
|
$this->toggle_cot_authoritative( true );
|
||||||
|
$this->disable_cot_sync();
|
||||||
|
|
||||||
|
list($order, $refund) = $this->create_order_with_refund();
|
||||||
|
$order_id = $order->get_id();
|
||||||
|
$refund_id = $refund->get_id();
|
||||||
|
|
||||||
|
$this->assert_order_record_existence( $order_id, true, true );
|
||||||
|
$this->assert_order_record_existence( $order_id, false, true, 'shop_order_placehold' );
|
||||||
|
$this->assert_order_record_existence( $refund_id, true, true );
|
||||||
|
$this->assert_order_record_existence( $refund_id, false, true, 'shop_order_placehold' );
|
||||||
|
|
||||||
|
$order->delete( true );
|
||||||
|
|
||||||
|
$this->assert_no_order_records_or_deletion_records_exist( $order_id, $refund_id, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @testdox When deleting an order whose associated post type is hierarchical, child orders aren't deleted and get the parent id of their parent order.
|
||||||
|
*/
|
||||||
|
public function test_order_deletion_when_post_type_is_hierarchical_results_in_child_order_upshifting() {
|
||||||
|
$this->reset_container_resolutions();
|
||||||
|
$this->reset_legacy_proxy_mocks();
|
||||||
|
$this->register_legacy_proxy_function_mocks(
|
||||||
|
array(
|
||||||
|
'is_post_type_hierarchical' => function( $post_type ) {
|
||||||
|
return 'shop_order' === $post_type ? true : is_post_type_hierarchical( $post_type );
|
||||||
|
},
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->sut = wc_get_container()->get( OrdersTableDataStore::class );
|
||||||
|
|
||||||
|
$this->allow_current_user_to_delete_posts();
|
||||||
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
|
$this->toggle_cot_authoritative( true );
|
||||||
|
$this->disable_cot_sync();
|
||||||
|
|
||||||
|
list($order, $refund) = $this->create_order_with_refund();
|
||||||
|
$order_id = $order->get_id();
|
||||||
|
$refund_id = $refund->get_id();
|
||||||
|
|
||||||
|
$this->switch_data_store( $order, $this->sut );
|
||||||
|
|
||||||
|
$order2 = OrderHelper::create_order();
|
||||||
|
$order2_id = $order2->get_id();
|
||||||
|
$order->set_parent_id( $order2_id );
|
||||||
|
$order->save();
|
||||||
|
|
||||||
|
$order->delete( true );
|
||||||
|
|
||||||
|
$this->assert_order_record_existence( $order_id, true, false );
|
||||||
|
$this->assert_order_record_existence( $refund_id, true, true );
|
||||||
|
|
||||||
|
$refund = wc_get_order( $refund_id );
|
||||||
|
$this->assertEquals( $order2_id, $refund->get_parent_id() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mock the current user capabilities so that it's allowed to delete posts.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function allow_current_user_to_delete_posts() {
|
||||||
|
$this->register_legacy_proxy_function_mocks(
|
||||||
|
array(
|
||||||
|
'current_user_can' => function( $capability ) {
|
||||||
|
return 'delete_posts' === $capability ? true : current_user_can( $capability );
|
||||||
|
},
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assert than no records exist whatsoever, and no deletion records either, for a given order and for its refund.
|
||||||
|
*
|
||||||
|
* @param int $order_id The order id to test.
|
||||||
|
* @param int $refund_id The refund id to test.
|
||||||
|
* @param bool $cot_is_authoritative True if the deletion record existence is to be checked for the orders table, false for the posts table.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function assert_no_order_records_or_deletion_records_exist( $order_id, $refund_id, $cot_is_authoritative ) {
|
||||||
|
$this->assert_order_record_existence( $order_id, true, false );
|
||||||
|
$this->assert_order_record_existence( $order_id, false, false );
|
||||||
|
$this->assert_order_record_existence( $refund_id, true, false );
|
||||||
|
$this->assert_order_record_existence( $refund_id, false, false );
|
||||||
|
|
||||||
|
$this->assert_deletion_record_existence( $order_id, $cot_is_authoritative, false );
|
||||||
|
$this->assert_deletion_record_existence( $refund_id, $cot_is_authoritative, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an order and a refund.
|
||||||
|
*
|
||||||
|
* @return array An array containing the order as the first element and the refund as the second element.
|
||||||
|
*/
|
||||||
|
private function create_order_with_refund() {
|
||||||
|
$order = OrderHelper::create_order();
|
||||||
|
|
||||||
|
$item = current( $order->get_items() )->get_data();
|
||||||
|
$refund = wc_create_refund(
|
||||||
|
array(
|
||||||
|
'order_id' => $order->get_id(),
|
||||||
|
'line_items' => array(
|
||||||
|
$item['id'] => array(
|
||||||
|
'id' => $item['id'],
|
||||||
|
'qty' => $item['quantity'],
|
||||||
|
'refund_total' => $item['total'],
|
||||||
|
'refund_tax' => $item['total_tax'],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$refund->save();
|
||||||
|
|
||||||
|
return array( $order, $refund );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ class OrdersTableRefundDataStoreTests extends WC_Unit_Test_Case {
|
||||||
*/
|
*/
|
||||||
public function test_refunds_backfill() {
|
public function test_refunds_backfill() {
|
||||||
$this->enable_cot_sync();
|
$this->enable_cot_sync();
|
||||||
$this->toggle_cot( true );
|
$this->toggle_cot_feature_and_usage( true );
|
||||||
$order = OrderHelper::create_complex_data_store_order( $this->order_data_store );
|
$order = OrderHelper::create_complex_data_store_order( $this->order_data_store );
|
||||||
$refund = wc_create_refund(
|
$refund = wc_create_refund(
|
||||||
array(
|
array(
|
||||||
|
|
Loading…
Reference in New Issue