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:
Nestor Soriano 2023-03-24 16:43:56 +01:00
parent bafcd8752a
commit 48081b3351
No known key found for this signature in database
GPG Key ID: 08110F3518C12CAD
8 changed files with 320 additions and 152 deletions

View File

@ -331,5 +331,4 @@ class OrderHelper {
return $order; return $order;
} }
} }

View File

@ -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.
*/ */

View File

@ -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();

View File

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

View File

@ -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 );
}
}

View File

@ -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 );

View File

@ -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 Suites use of temporary tables https://wordpress.stackexchange.com/a/220308. // Remove the Test Suites 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 );
}
} }

View File

@ -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(