Add unit tests for the Filterer class (variable products)

This commit is contained in:
Nestor Soriano 2021-05-31 16:54:55 +02:00
parent 9878aa37aa
commit c78627e6ee
No known key found for this signature in database
GPG Key ID: 08110F3518C12CAD
1 changed files with 637 additions and 28 deletions

View File

@ -4,6 +4,7 @@ namespace Automattic\WooCommerce\Tests\Internal\ProductAttributesLookup;
use Automattic\WooCommerce\Internal\AttributesHelper;
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper;
use Automattic\WooCommerce\Utilities\ArrayUtil;
/**
* Tests related to filtering for WC_Query.
@ -88,30 +89,49 @@ class FiltererTest extends \WC_Unit_Test_Case {
/**
* Core function to create a product.
*
* Format of $product_attributes is:
*
* [
* 'non_variation_defining' => [
* 'Name' => ['Value','Value'],...
* ]
* 'variation_defining' => [
* 'Name' => ['Value','Value'],...
* ]
* ]
*
* @param string $class_name The name of the product class that will be instantiated to create the product.
* @param array $attribute_terms_by_name An array of product attributes, keys are attribute names, values are arrays of attribute term names.
* @param bool $attributes_define_variations True if the attributes are used to define variations.
* @param array $product_attributes The product attributes.
* @return mixed An instance of the class passed in $class_name representing the created product.
*/
private function create_product_core( $class_name, $attribute_terms_by_name, $attributes_define_variations ) {
private function create_product_core( $class_name, $product_attributes ) {
$attributes = array();
$attribute_ids_by_name = wc_get_attribute_taxonomy_ids();
foreach ( $attribute_terms_by_name as $attribute_name => $attribute_terms ) {
$sanitized_attribute_name = wc_sanitize_taxonomy_name( $attribute_name );
$product_attributes = array(
false => ArrayUtil::get_value_or_default( $product_attributes, 'non_variation_defining', array() ),
true => ArrayUtil::get_value_or_default( $product_attributes, 'variation_defining', array() ),
);
foreach ( $product_attributes as $defines_variation => $attribute_terms_by_name ) {
foreach ( $attribute_terms_by_name as $attribute_name => $attribute_terms ) {
if ( ! is_array( $attribute_terms ) ) {
$attribute_terms = array( $attribute_terms );
}
$sanitized_attribute_name = wc_sanitize_taxonomy_name( $attribute_name );
$term_ids = array();
foreach ( $attribute_terms as $term ) {
$term_ids[] = (int) term_exists( $term, 'pa_' . $sanitized_attribute_name )['term_id'];
$term_ids = array();
foreach ( $attribute_terms as $term ) {
$term_ids[] = (int) term_exists( $term, 'pa_' . $sanitized_attribute_name )['term_id'];
}
$attribute = new \WC_Product_Attribute();
$attribute->set_id( $attribute_ids_by_name );
$attribute->set_name( 'pa_' . $sanitized_attribute_name );
$attribute->set_options( $term_ids );
$attribute->set_visible( true );
$attribute->set_variation( $defines_variation );
$attributes[] = $attribute;
}
$attribute = new \WC_Product_Attribute();
$attribute->set_id( $attribute_ids_by_name );
$attribute->set_name( 'pa_' . $sanitized_attribute_name );
$attribute->set_options( $term_ids );
$attribute->set_visible( true );
$attribute->set_variation( $attributes_define_variations );
$attributes[] = $attribute;
}
$product = new $class_name();
@ -141,7 +161,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
* @return array The product data, as generated by the REST API product creation entry point.
*/
private function create_simple_product( $attribute_terms_by_name, $in_stock ) {
$product = $this->create_product_core( \WC_Product_Simple::class, $attribute_terms_by_name, false );
$product = $this->create_product_core( \WC_Product_Simple::class, array( 'non_variation_defining' => $attribute_terms_by_name ) );
$product->set_stock_status( $in_stock ? 'instock' : 'outofstock' );
@ -164,6 +184,132 @@ class FiltererTest extends \WC_Unit_Test_Case {
return $product;
}
/**
* Creates a variable product.
* Format for the supplied data:
*
* variation_attributes => [
* Color => [Red, Blue, Green],
* Size => [Big, Medium, Small]
* ],
* non_variation_attributes => [
* Features => [Washable, Ironable]
* ],
* variations => [
* [
* defining_attributes => [
* Color => Red,
* Size => Small
* ],
* in_stock => true
* ],
* [
* defining_attributes => [
* Color => Red,
* Size => null //Means "Any"
* ],
* in_stock => false
* ],
* ]
*
* Format for the returned data:
*
* [
* id => 1,
* variation_ids => [2,3]
* ]
*
* @param array $data The data for creating the product.
* @returns array The product and variation ids.
*/
private function create_variable_product( $data ) {
// * First create the main product.
$product = $this->create_product_core(
\WC_Product_Variable::class,
array(
'non_variation_defining' => $data['non_variation_attributes'],
'variation_defining' => $data['variation_attributes'],
)
);
$product->save();
$product_id = $product->get_id();
// * Now create the variations.
$variation_ids = array();
foreach ( $data['variations'] as $variation_data ) {
$variation = new \WC_Product_Variation();
$variation->set_props(
array(
'parent_id' => $product->get_id(),
'regular_price' => 10,
)
);
$attributes = array();
foreach ( $variation_data['defining_attributes'] as $attribute_name => $attribute_value ) {
$attribute_name = wc_attribute_taxonomy_name( $attribute_name );
$attribute_value = wc_sanitize_taxonomy_name( $attribute_value );
$attributes[ $attribute_name ] = $attribute_value;
}
$variation->set_attributes( $attributes );
$variation->set_stock_status( $variation_data['in_stock'] ? 'instock' : 'outofstock' );
$variation->save();
$variation_ids[] = $variation->get_id();
}
// This is needed because it's not done by the REST API.
\WC_Product_Variable::sync_stock_status( $product_id );
// * And finally, insert the data in the lookup table.
$lookup_insert_clauses = array();
$lookup_insert_values = array();
if ( ! empty( $data['non_variation_attributes'] ) ) {
$main_product_in_stock = ! empty(
array_filter(
$data['variations'],
function( $variation ) {
return $variation['in_stock'];
}
)
);
foreach ( $data['non_variation_attributes'] as $name => $terms ) {
$this->compose_lookup_table_insert( $product->get_id(), $product->get_id(), $name, $terms, $lookup_insert_clauses, $lookup_insert_values, $main_product_in_stock, false );
}
}
reset( $variation_ids );
foreach ( $data['variations'] as $variation_data ) {
$variation_id = current( $variation_ids );
foreach ( $variation_data['defining_attributes'] as $attribute_name => $attribute_value ) {
if ( is_null( $attribute_value ) ) {
$attribute_values = $data['variation_attributes'][ $attribute_name ];
} else {
$attribute_values = array( $attribute_value );
}
$this->compose_lookup_table_insert( $variation_id, $product->get_id(), $attribute_name, $attribute_values, $lookup_insert_clauses, $lookup_insert_values, $variation_data['in_stock'], true );
}
next( $variation_ids );
}
$this->run_lookup_table_insert( $lookup_insert_clauses, $lookup_insert_values );
return array(
'id' => $product_id,
'variation_ids' => $variation_ids,
);
}
/**
* Compose the values part of a query to insert data in the lookup table.
@ -179,7 +325,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
*/
private function compose_lookup_table_insert( $product_id, $product_or_parent_id, $attribute_name, $terms, &$insert_query_parts, &$insert_query_values, $in_stock, $is_variation ) {
$taxonomy_name = wc_attribute_taxonomy_name( $attribute_name );
$term_objects = get_terms( $taxonomy_name );
$term_objects = get_terms( $taxonomy_name, array( 'hide_empty' => false ) );
$term_ids_by_names = wp_list_pluck( $term_objects, 'term_id', 'name' );
foreach ( $terms as $term ) {
@ -255,7 +401,9 @@ class FiltererTest extends \WC_Unit_Test_Case {
global $wp_the_query;
foreach ( $filters as $name => $values ) {
$_GET[ 'filter_' . wc_sanitize_taxonomy_name( $name ) ] = join( ',', array_map( 'wc_sanitize_taxonomy_name', $values ) );
if ( ! empty( $values ) ) {
$_GET[ 'filter_' . wc_sanitize_taxonomy_name( $name ) ] = join( ',', array_map( 'wc_sanitize_taxonomy_name', $values ) );
}
}
foreach ( $query_types as $name => $value ) {
@ -330,7 +478,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
*/
public function test_filtering_simple_product_in_stock_using_lookup_table( $attributes, $filter_type, $expected_to_be_visible ) {
$this->set_use_lookup_table( true );
$this->test_filtering_simple_product_in_stock_core( $attributes, $filter_type, $expected_to_be_visible );
$this->base_test_filtering_simple_product_in_stock( $attributes, $filter_type, $expected_to_be_visible );
}
/**
@ -344,7 +492,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
*/
public function test_filtering_simple_product_in_stock_not_using_lookup_table( $attributes, $filter_type, $expected_to_be_visible ) {
$this->set_use_lookup_table( false );
$this->test_filtering_simple_product_in_stock_core( $attributes, $filter_type, $expected_to_be_visible );
$this->base_test_filtering_simple_product_in_stock( $attributes, $filter_type, $expected_to_be_visible );
}
/**
@ -354,7 +502,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
* @param string $filter_type The filtering type, "or" or "and".
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
private function test_filtering_simple_product_in_stock_core( $attributes, $filter_type, $expected_to_be_visible ) {
private function base_test_filtering_simple_product_in_stock( $attributes, $filter_type, $expected_to_be_visible ) {
$this->create_product_attribute( 'Color', array( 'Blue', 'Red', 'Green' ) );
$product = $this->create_simple_product(
@ -409,7 +557,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
*/
public function test_filtering_simple_product_out_of_stock_using_lookup_table( $hide_out_of_stock, $is_in_stock, $expected_to_be_visible ) {
$this->set_use_lookup_table( true );
$this->test_filtering_simple_product_out_of_stock_core( $hide_out_of_stock, $is_in_stock, $expected_to_be_visible );
$this->base_test_filtering_simple_product_out_of_stock( $hide_out_of_stock, $is_in_stock, $expected_to_be_visible );
}
/**
@ -428,7 +576,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
*/
public function test_filtering_simple_product_out_of_stock_not_using_lookup_table( $hide_out_of_stock, $is_in_stock, $expected_to_be_visible ) {
$this->set_use_lookup_table( false );
$this->test_filtering_simple_product_out_of_stock_core( $hide_out_of_stock, $is_in_stock, $expected_to_be_visible );
$this->base_test_filtering_simple_product_out_of_stock( $hide_out_of_stock, $is_in_stock, $expected_to_be_visible );
}
/**
@ -438,7 +586,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
* @param bool $is_in_stock True if the product is in stock, false otherwise.
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
private function test_filtering_simple_product_out_of_stock_core( $hide_out_of_stock, $is_in_stock, $expected_to_be_visible ) {
private function base_test_filtering_simple_product_out_of_stock( $hide_out_of_stock, $is_in_stock, $expected_to_be_visible ) {
$this->create_product_attribute( 'Features', array( 'Washable', 'Ironable', 'Elastic' ) );
$product = $this->create_simple_product(
@ -490,7 +638,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
*/
public function test_filtering_simple_product_by_multiple_attributes_using_lookup_table( $attributes_1, $attributes_2, $expected_to_be_visible ) {
$this->set_use_lookup_table( true );
$this->test_filtering_simple_product_by_multiple_attributes_core( $attributes_1, $attributes_2, $expected_to_be_visible );
$this->base_test_filtering_simple_product_by_multiple_attributes( $attributes_1, $attributes_2, $expected_to_be_visible );
}
/**
@ -506,7 +654,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
*/
public function test_filtering_simple_product_by_multiple_attributes_not_using_using_lookup_table( $attributes_1, $attributes_2, $expected_to_be_visible ) {
$this->set_use_lookup_table( false );
$this->test_filtering_simple_product_by_multiple_attributes_core( $attributes_1, $attributes_2, $expected_to_be_visible );
$this->base_test_filtering_simple_product_by_multiple_attributes( $attributes_1, $attributes_2, $expected_to_be_visible );
}
/**
@ -516,7 +664,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
* @param array $attributes_2 The features attribute names that will be included in the query.
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
private function test_filtering_simple_product_by_multiple_attributes_core( $attributes_1, $attributes_2, $expected_to_be_visible ) {
private function base_test_filtering_simple_product_by_multiple_attributes( $attributes_1, $attributes_2, $expected_to_be_visible ) {
$this->create_product_attribute( 'Color', array( 'Blue', 'Red' ) );
$this->create_product_attribute( 'Features', array( 'Ironable', 'Washable' ) );
@ -548,4 +696,465 @@ class FiltererTest extends \WC_Unit_Test_Case {
$this->assert_counters( 'Color', $expected_to_be_visible ? array( 'Blue' ) : array() );
$this->assert_counters( 'Features', $expected_to_be_visible ? array( 'Ironable' ) : array() );
}
/**
* Data provider for the test_filtering_variable_product_in_stock_for_non_variation_defining_attributes tests.
*
* @return array[]
*/
public function data_provider_for_test_filtering_variable_product_in_stock_for_non_variation_defining_attributes() {
return array(
array( array(), 'and', true ),
array( array(), 'or', true ),
array( array( 'Washable' ), 'and', true ),
array( array( 'Washable' ), 'or', true ),
array( array( 'Washable', 'Ironable' ), 'and', true ),
array( array( 'Washable', 'Ironable' ), 'or', true ),
array( array( 'Elastic' ), 'and', false ),
array( array( 'Elastic' ), 'or', false ),
array( array( 'Washable', 'Elastic' ), 'and', false ),
array( array( 'Washable', 'Elastic' ), 'or', true ),
);
}
/**
* @testdox The product query shows a variable product only if it's not filtered out by the specified attribute filters (for non-variation-defining attributes), using the lookup table.
*
* @dataProvider data_provider_for_test_filtering_variable_product_in_stock_for_non_variation_defining_attributes
*
* @param array $attributes The feature attribute names that will be included in the query.
* @param string $filter_type The filtering type, "or" or "and".
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
public function test_filtering_variable_product_in_stock_for_non_variation_defining_attributes_using_lookup_table( $attributes, $filter_type, $expected_to_be_visible ) {
$this->set_use_lookup_table( true );
$this->base_test_filtering_variable_product_in_stock_for_non_variation_defining_attributes( $attributes, $filter_type, $expected_to_be_visible );
}
/**
* @testdox The product query shows a variable product only if it's not filtered out by the specified attribute filters (for non-variation-defining attributes), not using the lookup table.
*
* @dataProvider data_provider_for_test_filtering_variable_product_in_stock_for_non_variation_defining_attributes
*
* @param array $attributes The feature attribute names that will be included in the query.
* @param string $filter_type The filtering type, "or" or "and".
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
public function test_filtering_variable_product_in_stock_for_non_variation_defining_attributes_not_using_lookup_table( $attributes, $filter_type, $expected_to_be_visible ) {
$this->set_use_lookup_table( false );
$this->base_test_filtering_variable_product_in_stock_for_non_variation_defining_attributes( $attributes, $filter_type, $expected_to_be_visible );
}
/**
* Main code for the test_filtering_variable_product_in_stock_for_non_variation_defining_attributes tests.
*
* @param array $attributes The feature attribute names that will be included in the query.
* @param string $filter_type The filtering type, "or" or "and".
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
private function base_test_filtering_variable_product_in_stock_for_non_variation_defining_attributes( $attributes, $filter_type, $expected_to_be_visible ) {
$this->create_product_attribute( 'Color', array( 'Blue', 'Red' ) );
$this->create_product_attribute( 'Features', array( 'Washable', 'Ironable', 'Elastic' ) );
$product = $this->create_variable_product(
array(
'variation_attributes' => array(
'Color' => array( 'Blue', 'Red' ),
),
'non_variation_attributes' => array(
'Features' => array( 'Washable', 'Ironable' ),
),
'variations' => array(
array(
'in_stock' => true,
'defining_attributes' => array(
'Color' => 'Blue',
),
),
array(
'in_stock' => true,
'defining_attributes' => array(
'Color' => 'Red',
),
),
),
)
);
$filtered_product_ids = $this->do_product_request( array( 'Features' => $attributes ), array( 'Features' => $filter_type ) );
if ( $expected_to_be_visible ) {
$this->assertEquals( array( $product['id'] ), $filtered_product_ids );
} else {
$this->assertEmpty( $filtered_product_ids );
}
$expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible;
$this->assert_counters( 'Features', $expected_to_be_included_in_count ? array( 'Washable', 'Ironable' ) : array(), $filter_type );
}
/**
* Data provider for the test_filtering_variable_product_out_of_stock tests.
*
* @return array[]
*/
public function data_provider_for_test_filtering_variable_product_out_of_stock() {
return array(
array( false, true, true, true ),
array( false, true, false, true ),
array( false, false, true, true ),
array( false, false, false, true ),
array( true, true, true, true ),
array( true, true, false, true ),
array( true, false, true, true ),
array( true, false, false, false ),
);
}
/**
* @testdox The product query shows a variable product only if at least one of the variations is in stock OR we don't have "hide out of stock items" set (using the lookup table).
*
* @dataProvider data_provider_for_test_filtering_variable_product_out_of_stock
*
* @param bool $hide_out_of_stock The value of the "hide out of stock products" option.
* @param bool $variation_1_is_in_stock True if the first variation is in stock, false otherwise.
* @param bool $variation_2_is_in_stock True if the second variation is in stock, false otherwise.
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
public function test_filtering_variable_product_out_of_stock_using_lookup_table( $hide_out_of_stock, $variation_1_is_in_stock, $variation_2_is_in_stock, $expected_to_be_visible ) {
$this->set_use_lookup_table( true );
$this->base_test_filtering_variable_product_out_of_stock( $hide_out_of_stock, $variation_1_is_in_stock, $variation_2_is_in_stock, $expected_to_be_visible, true );
}
/**
* @testdox The product query shows a variable product only if at least one of the variations is in stock OR we don't have "hide out of stock items" set (using the lookup table).
*
* @dataProvider data_provider_for_test_filtering_variable_product_out_of_stock
*
* @param bool $hide_out_of_stock The value of the "hide out of stock products" option.
* @param bool $variation_1_is_in_stock True if the first variation is in stock, false otherwise.
* @param bool $variation_2_is_in_stock True if the second variation is in stock, false otherwise.
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
public function test_filtering_variable_product_out_of_stock_not_using_lookup_table( $hide_out_of_stock, $variation_1_is_in_stock, $variation_2_is_in_stock, $expected_to_be_visible ) {
$this->set_use_lookup_table( false );
$this->base_test_filtering_variable_product_out_of_stock( $hide_out_of_stock, $variation_1_is_in_stock, $variation_2_is_in_stock, $expected_to_be_visible, false );
}
/**
* Main code for the test_filtering_variable_product_out_of_stock tests.
*
* @param bool $hide_out_of_stock The value of the "hide out of stock products" option.
* @param bool $variation_1_is_in_stock True if the first variation is in stock, false otherwise.
* @param bool $variation_2_is_in_stock True if the second variation is in stock, false otherwise.
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
* @param bool $using_lookup_table Are we using the lookup table?.
*/
private function base_test_filtering_variable_product_out_of_stock( $hide_out_of_stock, $variation_1_is_in_stock, $variation_2_is_in_stock, $expected_to_be_visible, $using_lookup_table ) {
$this->create_product_attribute( 'Color', array( 'Blue', 'Red' ) );
$product = $this->create_variable_product(
array(
'variation_attributes' => array(
'Color' => array( 'Blue', 'Red' ),
),
'non_variation_attributes' => array(),
'variations' => array(
array(
'in_stock' => $variation_1_is_in_stock,
'defining_attributes' => array(
'Color' => 'Blue',
),
),
array(
'in_stock' => $variation_2_is_in_stock,
'defining_attributes' => array(
'Color' => 'Red',
),
),
),
)
);
$this->set_hide_out_of_stock_items( $hide_out_of_stock );
$filtered_product_ids = $this->do_product_request( array() );
if ( $expected_to_be_visible ) {
$this->assertEquals( array( $product['id'] ), $filtered_product_ids );
} else {
$this->assertEmpty( $filtered_product_ids );
}
/**
* When using the lookup table, attribute counters only take in account in stock variations.
* When not using it, all variations are accounted if at least one of them has stock.
*/
$expected_visible_attributes = array();
if ( $using_lookup_table ) {
if ( ! $hide_out_of_stock || $variation_1_is_in_stock ) {
$expected_visible_attributes[] = 'Blue';
}
if ( ! $hide_out_of_stock || $variation_2_is_in_stock ) {
$expected_visible_attributes[] = 'Red';
}
} elseif ( ! $hide_out_of_stock || $variation_1_is_in_stock || $variation_2_is_in_stock ) {
$expected_visible_attributes = array( 'Blue', 'Red' );
}
$this->assert_counters( 'Color', $expected_visible_attributes );
}
/**
* Base data provider for the test_filtering_variable_product_in_stock_for_variation_defining_attributes tests.
*
* @return array[]
*/
private function data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_core() {
return array(
array( array(), 'and', true ),
array( array(), 'or', true ),
array( array( 'Blue' ), 'and', true ),
array( array( 'Blue' ), 'or', true ),
array( array( 'Blue', 'Red' ), 'and', true ),
array( array( 'Blue', 'Red' ), 'or', true ),
array( array( 'Green' ), 'and', false ),
array( array( 'Green' ), 'or', false ),
);
}
/**
* Data provider for test_filtering_variable_product_in_stock_for_variation_defining_attributes_using_lookup_table.
*
* @return array[]
*/
public function data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_using_lookup_table() {
$data = $this->data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_core();
/**
* When filtering by an attribute having a variation AND another one not having it:
* The product shows, since when dealing with variation attributes we're effectively doing OR.
*/
$data[] = array( array( 'Blue', 'Green' ), 'and', true );
return $data;
}
/**
* @testdox The product query shows a variable product only if it's not filtered out by the specified attribute filters (for variation-defining attributes), using the lookup table.
*
* Note that the difference with the simple product or the non-variation attributes case is that "and" is equivalent to "or".
*
* @dataProvider data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_using_lookup_table
*
* @param array $attributes The color attribute names that will be included in the query.
* @param string $filter_type The filtering type, "or" or "and".
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
public function test_filtering_variable_product_in_stock_for_variation_defining_attributes_using_lookup_table( $attributes, $filter_type, $expected_to_be_visible ) {
$this->set_use_lookup_table( true );
$this->base_test_filtering_variable_product_in_stock_for_variation_defining_attributes( $attributes, $filter_type, $expected_to_be_visible );
}
/**
* Data provider for test_filtering_variable_product_in_stock_for_variation_defining_attributes_not_using_lookup_table.
*
* @return array[]
*/
public function data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_not_using_lookup_table() {
$data = $this->data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_core();
/**
* When filtering by an attribute having a variation AND another one not having it:
* The product doesn't show because variation attributes are treated as non-variation ones.
*/
$data[] = array( array( 'Blue', 'Green' ), 'and', false );
return $data;
}
/**
* @testdox The product query shows a variable product only if it's not filtered out by the specified attribute filters (for variation-defining attributes), not using the lookup table.
*
* Note that the difference with the simple product or the non-variation attributes case is that "and" is equivalent to "or".
*
* @dataProvider data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_not_using_lookup_table
*
* @param array $attributes The color attribute names that will be included in the query.
* @param string $filter_type The filtering type, "or" or "and".
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
public function test_filtering_variable_product_in_stock_for_variation_defining_attributes_not_using_lookup_table( $attributes, $filter_type, $expected_to_be_visible ) {
$this->set_use_lookup_table( false );
$this->base_test_filtering_variable_product_in_stock_for_variation_defining_attributes( $attributes, $filter_type, $expected_to_be_visible );
}
/**
* Main code for the test_filtering_variable_product_in_stock_for_variation_defining_attributes tests.
*
* @param array $attributes The color attribute names that will be included in the query.
* @param string $filter_type The filtering type, "or" or "and".
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
private function base_test_filtering_variable_product_in_stock_for_variation_defining_attributes( $attributes, $filter_type, $expected_to_be_visible ) {
$this->create_product_attribute( 'Color', array( 'Blue', 'Red', 'Green' ) );
$product = $this->create_variable_product(
array(
'variation_attributes' => array(
'Color' => array( 'Blue', 'Red' ),
),
'non_variation_attributes' => array(),
'variations' => array(
array(
'in_stock' => true,
'defining_attributes' => array(
'Color' => 'Blue',
),
),
array(
'in_stock' => true,
'defining_attributes' => array(
'Color' => 'Red',
),
),
),
)
);
$filtered_product_ids = $this->do_product_request( array( 'Color' => $attributes ), array( 'Color' => $filter_type ) );
if ( $expected_to_be_visible ) {
$this->assertEquals( array( $product['id'] ), $filtered_product_ids );
} else {
$this->assertEmpty( $filtered_product_ids );
}
$expected_counted_attributes = 'or' === $filter_type || $expected_to_be_visible ? array( 'Blue', 'Red' ) : array();
$this->assert_counters( 'Color', $expected_counted_attributes, $filter_type );
}
/**
* Base data provider for the test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value tests.
*
* @return array[]
*/
private function data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value_core() {
return array(
array( array(), 'and', true ),
array( array(), 'or', true ),
array( array( 'Blue' ), 'and', true ),
array( array( 'Blue' ), 'or', true ),
array( array( 'Red' ), 'and', true ),
array( array( 'Red' ), 'or', true ),
array( array( 'Green' ), 'and', true ),
array( array( 'Green' ), 'or', true ),
array( array( 'White' ), 'and', false ),
array( array( 'White' ), 'or', false ),
);
}
/**
* Data provider for test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value_using_lookup_table.
*
* @return array[]
*/
public function data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value_using_lookup_table() {
$data = $this->data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value_core();
/**
* When filtering by attributes having a variation AND others not having it:
* The product shows, since when dealing with variation attributes we're effectively doing OR.
*/
$data[] = array( array( 'Blue', 'Red', 'Green', 'White' ), 'and', true );
return $data;
}
/**
* @testdox The product query shows a variable product only if it's not filtered out by the specified attribute filters (for variation-defining attributes, with "Any" values), using the lookup table.
*
* @dataProvider data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value_using_lookup_table
*
* @param array $attributes The color attribute names that will be included in the query.
* @param string $filter_type The filtering type, "or" or "and".
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
public function test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value_using_lookup_table( $attributes, $filter_type, $expected_to_be_visible ) {
$this->set_use_lookup_table( true );
$this->base_test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value( $attributes, $filter_type, $expected_to_be_visible );
}
/**
* Data provider for test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value_not_using_lookup_table.
*
* @return array[]
*/
public function data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value_not_using_lookup_table() {
$data = $this->data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value_core();
/**
* When filtering by attributes having a variation AND others not having it:
* The product doesn't show because variation attributes are treated as non-variation ones.
*/
$data[] = array( array( 'Blue', 'Red', 'Green', 'White' ), 'and', false );
return $data;
}
/**
* @testdox The product query shows a variable product only if it's not filtered out by the specified attribute filters (for variation-defining attributes, with "Any" values), not using the lookup table.
*
* @dataProvider data_provider_for_test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value_not_using_lookup_table
*
* @param array $attributes The color attribute names that will be included in the query.
* @param string $filter_type The filtering type, "or" or "and".
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
public function test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value_not_using_lookup_table( $attributes, $filter_type, $expected_to_be_visible ) {
$this->set_use_lookup_table( false );
$this->base_test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value( $attributes, $filter_type, $expected_to_be_visible );
}
/**
* Main code for the test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value tests.
*
* @param array $attributes The color attribute names that will be included in the query.
* @param string $filter_type The filtering type, "or" or "and".
* @param bool $expected_to_be_visible True if the product is expected to be returned by the query, false otherwise.
*/
private function base_test_filtering_variable_product_in_stock_for_variation_defining_attributes_with_any_value( $attributes, $filter_type, $expected_to_be_visible ) {
$this->create_product_attribute( 'Color', array( 'Blue', 'Red', 'Green', 'White' ) );
$product = $this->create_variable_product(
array(
'variation_attributes' => array(
'Color' => array( 'Blue', 'Red', 'Green' ),
),
'non_variation_attributes' => array(),
'variations' => array(
array(
'in_stock' => true,
'defining_attributes' => array(
'Color' => null,
),
),
),
)
);
$filtered_product_ids = $this->do_product_request( array( 'Color' => $attributes ), array( 'Color' => $filter_type ) );
if ( $expected_to_be_visible ) {
$this->assertEquals( array( $product['id'] ), $filtered_product_ids );
} else {
$this->assertEmpty( $filtered_product_ids );
}
$expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible;
$this->assert_counters( 'Color', $expected_to_be_included_in_count ? array( 'Blue', 'Red', 'Green' ) : array(), $filter_type );
}
}