Add unit tests for the DataRegenerator class
This commit is contained in:
parent
4d13b0ca07
commit
c4e7074c70
|
@ -60,7 +60,6 @@ class DataRegenerator {
|
||||||
999
|
999
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $this->regeneration_is_in_progress() ) {
|
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_run_product_attribute_lookup_update_callback',
|
'woocommerce_run_product_attribute_lookup_update_callback',
|
||||||
function () {
|
function () {
|
||||||
|
@ -68,7 +67,6 @@ class DataRegenerator {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class initialization, invoked by the DI container.
|
* Class initialization, invoked by the DI container.
|
||||||
|
@ -156,16 +154,18 @@ CREATE TABLE ' . $this->lookup_table_name . '(
|
||||||
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
|
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
|
||||||
|
|
||||||
$last_existing_product_id =
|
$last_existing_product_id =
|
||||||
wc_get_products(
|
WC()->call_function(
|
||||||
|
'wc_get_products',
|
||||||
array(
|
array(
|
||||||
'return' => 'ids',
|
'return' => 'ids',
|
||||||
'limit' => 1,
|
'limit' => 1,
|
||||||
'orderby' => 'id',
|
'orderby' => array(
|
||||||
'order' => 'DESC',
|
'ID' => 'DESC',
|
||||||
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( false === $last_existing_product_id ) {
|
if ( ! $last_existing_product_id ) {
|
||||||
// No products exist, nothing to (re)generate.
|
// No products exist, nothing to (re)generate.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ CREATE TABLE ' . $this->lookup_table_name . '(
|
||||||
*/
|
*/
|
||||||
private function enqueue_regeneration_step_run() {
|
private function enqueue_regeneration_step_run() {
|
||||||
WC()->queue()->schedule_single(
|
WC()->queue()->schedule_single(
|
||||||
time() + 1,
|
WC()->call_function( 'time' ) + 1,
|
||||||
'woocommerce_run_product_attribute_lookup_update_callback',
|
'woocommerce_run_product_attribute_lookup_update_callback',
|
||||||
array(),
|
array(),
|
||||||
'woocommerce-db-updates'
|
'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' );
|
$last_products_page_processed = get_option( 'woocommerce_attribute_lookup__last_products_page_processed' );
|
||||||
$current_products_page = (int) $last_products_page_processed + 1;
|
$current_products_page = (int) $last_products_page_processed + 1;
|
||||||
|
|
||||||
$product_ids = wc_get_products(
|
$product_ids = WC()->call_function(
|
||||||
|
'wc_get_products',
|
||||||
array(
|
array(
|
||||||
'limit' => self::PRODUCTS_PER_GENERATION_STEP,
|
'limit' => self::PRODUCTS_PER_GENERATION_STEP,
|
||||||
'page' => $current_products_page,
|
'page' => $current_products_page,
|
||||||
|
@ -226,11 +227,16 @@ CREATE TABLE ' . $this->lookup_table_name . '(
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( ! $product_ids ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ( $product_ids as $id ) {
|
foreach ( $product_ids as $id ) {
|
||||||
$this->data_store->update_data_for_product( $id );
|
$this->data_store->update_data_for_product( $id );
|
||||||
}
|
}
|
||||||
|
|
||||||
update_option( 'woocommerce_attribute_lookup__last_products_page_processed', $current_products_page );
|
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' );
|
$last_product_id_to_process = get_option( 'woocommerce_attribute_lookup__last_product_id_to_process' );
|
||||||
return end( $product_ids ) < $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 = '' ) {
|
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 = '' ) {
|
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