Add unit tests for the DataRegenerator class
This commit is contained in:
parent
4d13b0ca07
commit
c4e7074c70
|
@ -60,14 +60,12 @@ class DataRegenerator {
|
|||
999
|
||||
);
|
||||
|
||||
if ( $this->regeneration_is_in_progress() ) {
|
||||
add_action(
|
||||
'woocommerce_run_product_attribute_lookup_update_callback',
|
||||
function () {
|
||||
$this->run_regeneration_step_callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
add_action(
|
||||
'woocommerce_run_product_attribute_lookup_update_callback',
|
||||
function () {
|
||||
$this->run_regeneration_step_callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,16 +154,18 @@ CREATE TABLE ' . $this->lookup_table_name . '(
|
|||
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
|
||||
|
||||
$last_existing_product_id =
|
||||
wc_get_products(
|
||||
WC()->call_function(
|
||||
'wc_get_products',
|
||||
array(
|
||||
'return' => 'ids',
|
||||
'limit' => 1,
|
||||
'orderby' => 'id',
|
||||
'order' => 'DESC',
|
||||
'orderby' => array(
|
||||
'ID' => 'DESC',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
if ( false === $last_existing_product_id ) {
|
||||
if ( ! $last_existing_product_id ) {
|
||||
// No products exist, nothing to (re)generate.
|
||||
return false;
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ CREATE TABLE ' . $this->lookup_table_name . '(
|
|||
*/
|
||||
private function enqueue_regeneration_step_run() {
|
||||
WC()->queue()->schedule_single(
|
||||
time() + 1,
|
||||
WC()->call_function( 'time' ) + 1,
|
||||
'woocommerce_run_product_attribute_lookup_update_callback',
|
||||
array(),
|
||||
'woocommerce-db-updates'
|
||||
|
@ -215,7 +215,8 @@ CREATE TABLE ' . $this->lookup_table_name . '(
|
|||
$last_products_page_processed = get_option( 'woocommerce_attribute_lookup__last_products_page_processed' );
|
||||
$current_products_page = (int) $last_products_page_processed + 1;
|
||||
|
||||
$product_ids = wc_get_products(
|
||||
$product_ids = WC()->call_function(
|
||||
'wc_get_products',
|
||||
array(
|
||||
'limit' => self::PRODUCTS_PER_GENERATION_STEP,
|
||||
'page' => $current_products_page,
|
||||
|
@ -226,11 +227,16 @@ CREATE TABLE ' . $this->lookup_table_name . '(
|
|||
)
|
||||
);
|
||||
|
||||
if ( ! $product_ids ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( $product_ids as $id ) {
|
||||
$this->data_store->update_data_for_product( $id );
|
||||
}
|
||||
|
||||
update_option( 'woocommerce_attribute_lookup__last_products_page_processed', $current_products_page );
|
||||
|
||||
$last_product_id_to_process = get_option( 'woocommerce_attribute_lookup__last_product_id_to_process' );
|
||||
return end( $product_ids ) < $last_product_id_to_process;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,15 @@ class FakeQueue implements \WC_Queue_Interface {
|
|||
}
|
||||
|
||||
public function schedule_single( $timestamp, $hook, $args = array(), $group = '' ) {
|
||||
$this->add_to_methods_called( 'schedule_single', $args, $group, array( 'hook' => $hook ) );
|
||||
$this->add_to_methods_called(
|
||||
'schedule_single',
|
||||
$args,
|
||||
$group,
|
||||
array(
|
||||
'timestamp' => $timestamp,
|
||||
'hook' => $hook,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function schedule_recurring( $timestamp, $interval_in_seconds, $hook, $args = array(), $group = '' ) {
|
||||
|
|
|
@ -0,0 +1,244 @@
|
|||
<?php
|
||||
/**
|
||||
* DataRegeneratorTest class file.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Tests\Internal\ProductAttributesLookup;
|
||||
|
||||
use Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator;
|
||||
use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore;
|
||||
use Automattic\WooCommerce\Testing\Tools\FakeQueue;
|
||||
|
||||
/**
|
||||
* Tests for the DataRegenerator class.
|
||||
* @package Automattic\WooCommerce\Tests\Internal\ProductAttributesLookup
|
||||
*/
|
||||
class DataRegeneratorTest extends \WC_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
* The system under test.
|
||||
*
|
||||
* @var DataRegenerator
|
||||
*/
|
||||
private $sut;
|
||||
|
||||
/**
|
||||
* @var LookupDataStore
|
||||
*/
|
||||
private $lookup_data_store;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $lookup_table_name;
|
||||
|
||||
/**
|
||||
* Runs before all the tests in the class.
|
||||
*/
|
||||
public static function setUpBeforeClass() {
|
||||
\WC_Queue::reset_instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs before each test.
|
||||
*/
|
||||
public function setUp() {
|
||||
global $wpdb;
|
||||
|
||||
$this->lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup';
|
||||
|
||||
add_filter(
|
||||
'woocommerce_queue_class',
|
||||
function() {
|
||||
return FakeQueue::class;
|
||||
}
|
||||
);
|
||||
|
||||
// phpcs:disable Squiz.Commenting
|
||||
$this->lookup_data_store = new class() extends LookupDataStore {
|
||||
public $passed_products = array();
|
||||
|
||||
public function update_data_for_product( $product ) {
|
||||
$this->passed_products[] = $product;
|
||||
}
|
||||
};
|
||||
// phpcs:enable Squiz.Commenting
|
||||
|
||||
// This is needed to prevent the hook to act on the already registered LookupDataStore class.
|
||||
remove_all_actions( 'woocommerce_run_product_attribute_lookup_update_callback' );
|
||||
|
||||
$container = wc_get_container();
|
||||
$container->reset_all_resolved();
|
||||
$container->replace( LookupDataStore::class, $this->lookup_data_store );
|
||||
$this->sut = $container->get( DataRegenerator::class );
|
||||
|
||||
WC()->queue()->methods_called = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @testdox `initiate_regeneration` creates the lookup table, deleting it first if it already existed.
|
||||
*
|
||||
* @testWith [false]
|
||||
* [true]
|
||||
*
|
||||
* @param bool $previously_existing True to create a lookup table beforehand.
|
||||
*/
|
||||
public function test_initiate_regeneration_creates_looukp_table( $previously_existing ) {
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||
|
||||
$wpdb->query( 'DROP TABLE IF EXISTS ' . $this->lookup_table_name );
|
||||
|
||||
if ( $previously_existing ) {
|
||||
$wpdb->query( 'CREATE TABLE ' . $this->lookup_table_name . ' (foo int);' );
|
||||
}
|
||||
|
||||
$this->sut->initiate_regeneration();
|
||||
|
||||
$query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $this->lookup_table_name ) );
|
||||
|
||||
$this->assertEquals( $this->lookup_table_name, $wpdb->get_var( $query ) );
|
||||
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
|
||||
}
|
||||
|
||||
/**
|
||||
* @testdox `initiate_regeneration` initializes the transient options, and enqueues the first step for time()+1.
|
||||
*/
|
||||
public function test_initiate_regeneration_initializes_temporary_options_and_enqueues_regeneration_step() {
|
||||
$this->register_legacy_proxy_function_mocks(
|
||||
array(
|
||||
'wc_get_products' => function( $args ) {
|
||||
return array( 100 );
|
||||
},
|
||||
'time' => function() {
|
||||
return 1000;
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
$this->sut->initiate_regeneration();
|
||||
|
||||
$this->assertEquals( 100, get_option( 'woocommerce_attribute_lookup__last_product_id_to_process' ) );
|
||||
$this->assertEquals( 0, get_option( 'woocommerce_attribute_lookup__last_products_page_processed' ) );
|
||||
$this->assertFalse( get_option( 'woocommerce_attribute_lookup__enabled' ) );
|
||||
|
||||
$expected_enqueued = array(
|
||||
'method' => 'schedule_single',
|
||||
'args' => array(),
|
||||
'timestamp' => 1001,
|
||||
'hook' => 'woocommerce_run_product_attribute_lookup_update_callback',
|
||||
'group' => 'woocommerce-db-updates',
|
||||
);
|
||||
$actual_enqueued = current( WC()->queue()->methods_called );
|
||||
|
||||
$this->assertEquals( sort( $expected_enqueued ), sort( $actual_enqueued ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testdox `initiate_regeneration` finalizes the regeneration process without enqueueing any step if the db is empty.
|
||||
*
|
||||
* @testWith [false]
|
||||
* [[]]
|
||||
*
|
||||
* @param mixed $get_products_result Result from wc_get_products.
|
||||
*/
|
||||
public function test_initiate_regeneration_does_not_enqueues_regeneration_step_when_no_products( $get_products_result ) {
|
||||
$this->register_legacy_proxy_function_mocks(
|
||||
array(
|
||||
'wc_get_products' => function( $args ) use ( $get_products_result ) {
|
||||
return $get_products_result;
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
$this->sut->initiate_regeneration();
|
||||
|
||||
$this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_product_id_to_process' ) );
|
||||
$this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_products_page_processed' ) );
|
||||
$this->assertEquals( 'no', get_option( 'woocommerce_attribute_lookup__enabled' ) );
|
||||
$this->assertEmpty( WC()->queue()->methods_called );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testdox `initiate_regeneration` processes one chunk of products IDs and enqueues next step if there are more products available.
|
||||
*/
|
||||
public function test_initiate_regeneration_correctly_processes_ids_and_enqueues_next_step() {
|
||||
$requested_products_pages = array();
|
||||
|
||||
$this->register_legacy_proxy_function_mocks(
|
||||
array(
|
||||
'wc_get_products' => function( $args ) use ( &$requested_products_pages ) {
|
||||
if ( 'DESC' === current( $args['orderby'] ) ) {
|
||||
return array( 100 );
|
||||
} else {
|
||||
$requested_products_pages[] = $args['page'];
|
||||
return array( 1, 2, 3 );
|
||||
}
|
||||
},
|
||||
'time' => function() {
|
||||
return 1000;
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
$this->sut->initiate_regeneration();
|
||||
WC()->queue()->methods_called = array();
|
||||
|
||||
update_option( 'woocommerce_attribute_lookup__last_products_page_processed', 7 );
|
||||
|
||||
do_action( 'woocommerce_run_product_attribute_lookup_update_callback' );
|
||||
|
||||
$this->assertEquals( array( 1, 2, 3 ), $this->lookup_data_store->passed_products );
|
||||
$this->assertEquals( array( 8 ), $requested_products_pages );
|
||||
$this->assertEquals( 8, get_option( 'woocommerce_attribute_lookup__last_products_page_processed' ) );
|
||||
|
||||
$expected_enqueued = array(
|
||||
'method' => 'schedule_single',
|
||||
'args' => array(),
|
||||
'timestamp' => 1001,
|
||||
'hook' => 'woocommerce_run_product_attribute_lookup_update_callback',
|
||||
'group' => 'woocommerce-db-updates',
|
||||
);
|
||||
$actual_enqueued = current( WC()->queue()->methods_called );
|
||||
$this->assertEquals( sort( $expected_enqueued ), sort( $actual_enqueued ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testdox `initiate_regeneration` finishes regeneration when the max product id is reached or no more products are returned.
|
||||
*
|
||||
* @testWith [[98,99,100]]
|
||||
* [[99,100,101]]
|
||||
* [[]]
|
||||
*
|
||||
* @param array $product_ids The products ids that wc_get_products will return.
|
||||
*/
|
||||
public function test_initiate_regeneration_finishes_when_no_more_products_available( $product_ids ) {
|
||||
$requested_products_pages = array();
|
||||
|
||||
$this->register_legacy_proxy_function_mocks(
|
||||
array(
|
||||
'wc_get_products' => function( $args ) use ( &$requested_products_pages, $product_ids ) {
|
||||
if ( 'DESC' === current( $args['orderby'] ) ) {
|
||||
return array( 100 );
|
||||
} else {
|
||||
$requested_products_pages[] = $args['page'];
|
||||
return $product_ids;
|
||||
}
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
$this->sut->initiate_regeneration();
|
||||
WC()->queue()->methods_called = array();
|
||||
|
||||
do_action( 'woocommerce_run_product_attribute_lookup_update_callback' );
|
||||
|
||||
$this->assertEquals( $product_ids, $this->lookup_data_store->passed_products );
|
||||
$this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_product_id_to_process' ) );
|
||||
$this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_products_page_processed' ) );
|
||||
$this->assertEquals( 'no', get_option( 'woocommerce_attribute_lookup__enabled' ) );
|
||||
$this->assertEmpty( WC()->queue()->methods_called );
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue