Add unit tests for LookupDataStore::update_data_for_product (simple products)
Also: - Add the FakeQueue class - Fix LookupDataStore, it was using a hardcoded "wp_" lookup table name
This commit is contained in:
parent
e58d26f377
commit
467af94b1d
|
@ -14,6 +14,22 @@ defined( 'ABSPATH' ) || exit;
|
||||||
*/
|
*/
|
||||||
class LookupDataStore {
|
class LookupDataStore {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The lookup table name.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $lookup_table_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LookupDataStore constructor.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
$this->lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert or update the lookup data for a given product or variation.
|
* Insert or update the lookup data for a given product or variation.
|
||||||
* If a variable product is passed the information is updated for all of its variations.
|
* If a variable product is passed the information is updated for all of its variations.
|
||||||
|
@ -50,12 +66,14 @@ class LookupDataStore {
|
||||||
private function delete_lookup_table_entries_for( int $product_id ) {
|
private function delete_lookup_table_entries_for( int $product_id ) {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
|
|
||||||
|
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||||
$wpdb->query(
|
$wpdb->query(
|
||||||
$wpdb->prepare(
|
$wpdb->prepare(
|
||||||
'DELETE FROM wp_wc_product_attributes_lookup WHERE product_or_parent_id = %d',
|
'DELETE FROM ' . $this->lookup_table_name . ' WHERE product_or_parent_id = %d',
|
||||||
$product_id
|
$product_id
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -252,9 +270,10 @@ class LookupDataStore {
|
||||||
private function insert_lookup_table_data( int $product_id, int $product_or_parent_id, string $taxonomy, int $term_id, bool $is_variation_attribute, bool $has_stock ) {
|
private function insert_lookup_table_data( int $product_id, int $product_or_parent_id, string $taxonomy, int $term_id, bool $is_variation_attribute, bool $has_stock ) {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
|
|
||||||
|
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||||
$wpdb->query(
|
$wpdb->query(
|
||||||
$wpdb->prepare(
|
$wpdb->prepare(
|
||||||
'INSERT INTO wp_wc_product_attributes_lookup (
|
'INSERT INTO ' . $this->lookup_table_name . ' (
|
||||||
product_id,
|
product_id,
|
||||||
product_or_parent_id,
|
product_or_parent_id,
|
||||||
taxonomy,
|
taxonomy,
|
||||||
|
@ -271,5 +290,6 @@ class LookupDataStore {
|
||||||
$has_stock ? 1 : 0
|
$has_stock ? 1 : 0
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* FakeQueue class file.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\Testing\Tools
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Automattic\WooCommerce\Testing\Tools;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fake scheduled actions queue for unit tests, it just records all the method calls
|
||||||
|
* in a publicly accessible $methods_called property.
|
||||||
|
*
|
||||||
|
* To use, add this to the setUp method of the unit tests class:
|
||||||
|
*
|
||||||
|
* add_filter( 'woocommerce_queue_class', function() { return FakeQueue::class; } );
|
||||||
|
*
|
||||||
|
* then WC->queue() will return an instance of this class.
|
||||||
|
*/
|
||||||
|
class FakeQueue implements \WC_Queue_Interface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records all the method calls to this instance.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $methods_called = array();
|
||||||
|
|
||||||
|
// phpcs:disable Squiz.Commenting.FunctionComment.Missing
|
||||||
|
|
||||||
|
public function add( $hook, $args = array(), $group = '' ) {
|
||||||
|
// TODO: Implement add() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function schedule_single( $timestamp, $hook, $args = array(), $group = '' ) {
|
||||||
|
$this->add_to_methods_called( 'schedule_single', $args, $group, array( 'hook' => $hook ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function schedule_recurring( $timestamp, $interval_in_seconds, $hook, $args = array(), $group = '' ) {
|
||||||
|
// TODO: Implement schedule_recurring() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function schedule_cron( $timestamp, $cron_schedule, $hook, $args = array(), $group = '' ) {
|
||||||
|
// TODO: Implement schedule_cron() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cancel( $hook, $args = array(), $group = '' ) {
|
||||||
|
// TODO: Implement cancel() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cancel_all( $hook, $args = array(), $group = '' ) {
|
||||||
|
// TODO: Implement cancel_all() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_next( $hook, $args = null, $group = '' ) {
|
||||||
|
// TODO: Implement get_next() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
public function search( $args = array(), $return_format = OBJECT ) {
|
||||||
|
// TODO: Implement search() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:enable Squiz.Commenting.FunctionComment.Missing
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a method call for this instance.
|
||||||
|
*
|
||||||
|
* @param string $method Name of the invoked method.
|
||||||
|
* @param array $args Arguments passed in '$args' to the method call.
|
||||||
|
* @param string $group Group name passed in '$group' to the method call.
|
||||||
|
* @param array $extra_args Any extra information to store about the method call.
|
||||||
|
*/
|
||||||
|
private function add_to_methods_called( $method, $args, $group, $extra_args = array() ) {
|
||||||
|
$value = array(
|
||||||
|
'method' => $method,
|
||||||
|
'args' => $args,
|
||||||
|
'group' => $group,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->methods_called[] = array_merge( $value, $extra_args );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* LookupDataStoreTest 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;
|
||||||
|
use Automattic\WooCommerce\Utilities\ArrayUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the LookupDataStore class.
|
||||||
|
* @package Automattic\WooCommerce\Tests\Internal\ProductAttributesLookup
|
||||||
|
*/
|
||||||
|
class LookupDataStoreTest extends \WC_Unit_Test_Case {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The system under test.
|
||||||
|
*
|
||||||
|
* @var LookupDataStore
|
||||||
|
*/
|
||||||
|
private $sut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs before each test.
|
||||||
|
*/
|
||||||
|
public function setUp() {
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
$this->sut = new LookupDataStore();
|
||||||
|
|
||||||
|
// Initiating regeneration with a fake queue will just create the lookup table in the database.
|
||||||
|
add_filter(
|
||||||
|
'woocommerce_queue_class',
|
||||||
|
function() {
|
||||||
|
return FakeQueue::class;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$this->get_instance_of( DataRegenerator::class )->initiate_regeneration();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @testdox `test_update_data_for_product` throws an exception if a variation is passed.
|
||||||
|
*/
|
||||||
|
public function test_update_data_for_product_throws_if_variation_is_passed() {
|
||||||
|
$product = new \WC_Product_Variation();
|
||||||
|
|
||||||
|
$this->expectException( \Exception::class );
|
||||||
|
$this->expectExceptionMessage( "LookupDataStore::update_data_for_product can't be called for variations." );
|
||||||
|
|
||||||
|
$this->sut->update_data_for_product( $product );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @testdox `test_update_data_for_product` creates the appropriate entries for simple products, skipping custom product attributes.
|
||||||
|
*
|
||||||
|
* @testWith [true]
|
||||||
|
* [false]
|
||||||
|
*
|
||||||
|
* @param bool $in_stock 'true' if the product is supposed to be in stock.
|
||||||
|
*/
|
||||||
|
public function test_update_data_for_simple_product( $in_stock ) {
|
||||||
|
$product = new \WC_Product_Simple();
|
||||||
|
$product->set_id( 10 );
|
||||||
|
$this->set_product_attributes(
|
||||||
|
$product,
|
||||||
|
array(
|
||||||
|
'pa_attribute_1' => array(
|
||||||
|
'id' => 100,
|
||||||
|
'options' => array( 51, 52 ),
|
||||||
|
),
|
||||||
|
'pa_attribute_2' => array(
|
||||||
|
'id' => 200,
|
||||||
|
'options' => array( 73, 74 ),
|
||||||
|
),
|
||||||
|
'pa_custom_attribute' => array(
|
||||||
|
'id' => 0,
|
||||||
|
'options' => array( 'foo', 'bar' ),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( $in_stock ) {
|
||||||
|
$product->set_stock_status( 'instock' );
|
||||||
|
$expected_in_stock = 1;
|
||||||
|
} else {
|
||||||
|
$product->set_stock_status( 'outofstock' );
|
||||||
|
$expected_in_stock = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->sut->update_data_for_product( $product );
|
||||||
|
|
||||||
|
$expected = array(
|
||||||
|
array(
|
||||||
|
'product_id' => 10,
|
||||||
|
'product_or_parent_id' => 10,
|
||||||
|
'taxonomy' => 'pa_attribute_1',
|
||||||
|
'term_id' => 51,
|
||||||
|
'in_stock' => $expected_in_stock,
|
||||||
|
'is_variation_attribute' => 0,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'product_id' => 10,
|
||||||
|
'product_or_parent_id' => 10,
|
||||||
|
'taxonomy' => 'pa_attribute_1',
|
||||||
|
'term_id' => 52,
|
||||||
|
'in_stock' => $expected_in_stock,
|
||||||
|
'is_variation_attribute' => 0,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'product_id' => 10,
|
||||||
|
'product_or_parent_id' => 10,
|
||||||
|
'taxonomy' => 'pa_attribute_2',
|
||||||
|
'term_id' => 73,
|
||||||
|
'in_stock' => $expected_in_stock,
|
||||||
|
'is_variation_attribute' => 0,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'product_id' => 10,
|
||||||
|
'product_or_parent_id' => 10,
|
||||||
|
'taxonomy' => 'pa_attribute_2',
|
||||||
|
'term_id' => 74,
|
||||||
|
'in_stock' => $expected_in_stock,
|
||||||
|
'is_variation_attribute' => 0,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$actual = $this->get_lookup_table_data();
|
||||||
|
|
||||||
|
$this->assertEquals( $expected, $actual );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the product attributes from an array with this format:
|
||||||
|
*
|
||||||
|
* [
|
||||||
|
* 'taxonomy_or_custom_attribute_name' =>
|
||||||
|
* [
|
||||||
|
* 'id' => attribute id (0 for custom product attribute),
|
||||||
|
* 'options' => [term_id, term_id...] (for custom product attributes: ['term', 'term'...]
|
||||||
|
* 'variation' => 1|0 (optional, default 0)
|
||||||
|
* ], ...
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* @param WC_Product $product The product to set the attributes.
|
||||||
|
* @param array $attributes_data The attributes to set.
|
||||||
|
*/
|
||||||
|
private function set_product_attributes( $product, $attributes_data ) {
|
||||||
|
$attributes = array();
|
||||||
|
foreach ( $attributes_data as $taxonomy => $attribute_data ) {
|
||||||
|
$attribute = new \WC_Product_Attribute();
|
||||||
|
$attribute->set_id( $attribute_data['id'] );
|
||||||
|
$attribute->set_name( $taxonomy );
|
||||||
|
$attribute->set_options( $attribute_data['options'] );
|
||||||
|
$attribute->set_variation( ArrayUtil::get_value_or_default( $attribute_data, 'variation', false ) );
|
||||||
|
$attributes[] = $attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
$product->set_attributes( $attributes );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the data in the lookup table as an array of associative arrays.
|
||||||
|
*
|
||||||
|
* @return array All the rows in the lookup table as an array of associative arrays.
|
||||||
|
*/
|
||||||
|
private function get_lookup_table_data() {
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
$result = $wpdb->get_results( 'select * from ' . $wpdb->prefix . 'wc_product_attributes_lookup', ARRAY_A );
|
||||||
|
|
||||||
|
foreach ( $result as $row ) {
|
||||||
|
foreach ( $row as $column_name => $value ) {
|
||||||
|
if ( 'taxonomy' !== $column_name ) {
|
||||||
|
$row[ $column_name ] = (int) $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue