Make WordPress Core


Ignore:
Timestamp:
09/30/2014 09:17:38 PM (10 years ago)
Author:
boonebgorges
Message:

Improve unit tests related to WP_Meta_Query.

  • More complete test coverage for publicly available methods of WP_Meta_Query.
  • Move tests that rely on WP_Query (via the meta_query parameter) to tests/post/query.php.
  • Better coverage for basic use cases of 'meta_query', including all values of 'compare' and default values of 'key', 'value', and 'compare'.
  • Improve performance for tests that run WP_Query, by retrieving only post IDs and not prefetching postmeta and post terms.
  • Add 'public' visibility keywords to test methods.
  • Whitespace cleanup.

Fixes #29560

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/meta/query.php

    r27689 r29799  
    33 * Test WP_Meta_Query, in wp-includes/meta.php
    44 *
     5 * See tests/post/query.php for tests that involve post queries.
     6 *
    57 * @group meta
    68 */
    79class Tests_Meta_Query extends WP_UnitTestCase {
    810
    9     function test_default_relation() {
     11    public function test_empty_meta_query_param() {
     12        $query = new WP_Meta_Query();
     13        $this->assertSame( null, $query->relation );
     14    }
     15
     16    public function test_default_relation() {
    1017        $query = new WP_Meta_Query( array( array( 'key' => 'abc' ) ) );
    11 
    1218        $this->assertEquals( 'AND', $query->relation );
    1319    }
    1420
    15     function test_set_relation() {
     21    public function test_set_relation() {
    1622
    1723        $query = new WP_Meta_Query( array( array( 'key' => 'abc' ), 'relation' => 'AND' ) );
     
    2228
    2329        $this->assertEquals( 'OR', $query->relation );
     30    }
     31
     32    /**
     33     * Non-arrays should not be added to the queries array.
     34     */
     35    public function test_invalid_query_clauses() {
     36        $query = new WP_Meta_Query( array(
     37            'foo', // empty string
     38            5, // int
     39            false, // bool
     40            array(),
     41        ) );
     42
     43        $this->assertSame( array( array() ), $query->queries );
    2444    }
    2545
     
    2949     * @ticket 19729
    3050     */
    31     function test_single_inner_join_for_keys_only() {
     51    public function test_single_inner_join_for_keys_only() {
    3252
    3353        global $wpdb;
     
    5878
    5979    /**
     80     * WP_Query-style query must be at index 0 for order_by=meta_value to work.
     81     */
     82    public function test_parse_query_vars_simple_query_index_0() {
     83        $qv = array(
     84            'meta_query' => array(
     85                array(
     86                    'key' => 'foo1',
     87                    'compare' => 'baz1',
     88                    'value' => 'bar1',
     89                ),
     90            ),
     91            'meta_key' => 'foo',
     92            'meta_compare' => 'bar',
     93            'meta_value' => 'baz',
     94        );
     95
     96        $query = new WP_Meta_Query();
     97        $query->parse_query_vars( $qv );
     98
     99        $expected0 = array(
     100            'key' => 'foo',
     101            'compare' => 'bar',
     102            'value' => 'baz',
     103        );
     104        $this->assertEquals( $expected0, $query->queries[0] );
     105
     106        $expected1 = array(
     107            'key' => 'foo1',
     108            'compare' => 'baz1',
     109            'value' => 'bar1',
     110        );
     111        $this->assertEquals( $expected1, $query->queries[1] );
     112    }
     113
     114    /**
     115     * When no meta_value is provided, no 'value' should be set in the parsed queries.
     116     */
     117    public function test_parse_query_vars_with_no_meta_value() {
     118        $qv = array(
     119            'meta_key' => 'foo',
     120            'meta_type' => 'bar',
     121            'meta_compare' => '=',
     122        );
     123
     124        $query = new WP_Meta_Query();
     125        $query->parse_query_vars( $qv );
     126
     127        $this->assertTrue( ! isset( $query->queries[0]['value'] ) );
     128    }
     129
     130    /**
     131     * WP_Query sets meta_value to '' by default. It should be removed by parse_query_vars().
     132     */
     133    public function test_parse_query_vars_with_default_meta_compare() {
     134        $qv = array(
     135            'meta_key' => 'foo',
     136            'meta_type' => 'bar',
     137            'meta_compare' => '=',
     138            'meta_value' => '',
     139        );
     140
     141        $query = new WP_Meta_Query();
     142        $query->parse_query_vars( $qv );
     143
     144        $this->assertTrue( ! isset( $query->queries[0]['value'] ) );
     145    }
     146
     147    /**
    60148     * Test the conversion between "WP_Query" style meta args (meta_value=x&meta_key=y)
    61      * to a meta query array
    62      */
    63     function test_parse_query_vars() {
     149     * to a meta query array.
     150     */
     151    public function test_parse_query_vars() {
    64152
    65153        $query = new WP_Meta_Query();
     
    82170
    83171    /**
    84      * @ticket 22096
    85      */
    86     function test_empty_value_sql() {
    87         global $wpdb;
    88 
    89         $query = new WP_Meta_Query();
    90 
    91         $the_complex_query['meta_query'] = array(
    92             array( 'key' => 'my_first_key', 'value' => 'my_amazing_value' ),
    93             array( 'key' => 'my_second_key', 'compare' => 'NOT EXISTS' ),
    94             array( 'key' => 'my_third_key', 'value' => array( ), 'compare' => 'IN' ),
    95         );
    96 
    97         $query->parse_query_vars( $the_complex_query );
    98 
    99         $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
    100 
    101         // We should have 2 joins - one for my_first_key and one for my_second_key
    102         $this->assertEquals( 2, substr_count( $sql['join'], 'INNER JOIN' ) );
    103 
    104         // The WHERE should check my_third_key against an unaliased table
    105         $this->assertEquals( 1, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'my_third_key'" ) );
    106 
    107     }
    108 
    109     /**
    110      * @ticket 22967
    111      */
    112     function test_null_value_sql() {
    113         global $wpdb;
    114 
    115         $query = new WP_Meta_Query( array(
    116             array( 'key' => 'abc', 'value' => null, 'compare' => '=' )
    117         ) );
    118         $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
    119 
    120         $this->assertEquals( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) = '')" ) );
    121     }
    122 
    123     /**
    124172     * @ticket 23033
    125173     */
    126     function test_get_cast_for_type() {
     174    public function test_get_cast_for_type() {
    127175        $query = new WP_Meta_Query();
    128176        $this->assertEquals( 'BINARY', $query->get_cast_for_type( 'BINARY' ) );
     
    151199        $this->assertEquals( 'CHAR', $query->get_cast_for_type( 'DECIMAL(10,  5)' ) );
    152200
     201        $this->assertEquals( 'CHAR', $query->get_cast_for_type() );
    153202        $this->assertEquals( 'CHAR', $query->get_cast_for_type( 'ANYTHING ELSE' ) );
    154203    }
    155204
    156     function test_not_exists() {
     205    /**
     206     * Invalid $type will fail to get a table from _get_meta_table()
     207     */
     208    public function test_get_sql_invalid_type() {
     209        $query = new WP_Meta_Query();
     210        $this->assertFalse( $query->get_sql( 'foo', 'foo', 'foo' ) );
     211    }
     212
     213    /**
     214     * @ticket 22096
     215     */
     216    public function test_empty_value_sql() {
     217        global $wpdb;
     218
     219        $query = new WP_Meta_Query();
     220
     221        $the_complex_query['meta_query'] = array(
     222            array( 'key' => 'my_first_key', 'value' => 'my_amazing_value' ),
     223            array( 'key' => 'my_second_key', 'compare' => 'NOT EXISTS' ),
     224            array( 'key' => 'my_third_key', 'value' => array( ), 'compare' => 'IN' ),
     225        );
     226
     227        $query->parse_query_vars( $the_complex_query );
     228
     229        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     230
     231        // We should have 2 joins - one for my_first_key and one for my_second_key
     232        $this->assertEquals( 2, substr_count( $sql['join'], 'INNER JOIN' ) );
     233
     234        // The WHERE should check my_third_key against an unaliased table
     235        $this->assertEquals( 1, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'my_third_key'" ) );
     236
     237    }
     238
     239    /**
     240     * @ticket 22967
     241     */
     242    public function test_null_value_sql() {
     243        global $wpdb;
     244
     245        $query = new WP_Meta_Query( array(
     246            array( 'key' => 'abc', 'value' => null, 'compare' => '=' )
     247        ) );
     248        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     249
     250        $this->assertEquals( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) = '')" ) );
     251    }
     252
     253    /**
     254     * "key only queries" are queries that don't need to match a value, so
     255     * they can be grouped together into a single clause without JOINs
     256     */
     257    public function test_get_sql_key_only_queries() {
     258        global $wpdb;
     259
     260        $query1 = new WP_Meta_Query( array(
     261            'relation' => 'OR',
     262
     263            // Empty 'compare'
     264            array(
     265                'key' => 'foo',
     266            ),
     267
     268            // Non-empty 'compare'
     269            array(
     270                'key' => 'bar',
     271                'compare' => '<',
     272            ),
     273
     274            // NOT EXISTS
     275            array(
     276                'key' => 'baz',
     277                'compare' => 'NOT EXISTS',
     278            ),
     279
     280            // Has a value
     281            array(
     282                'key' => 'barry',
     283                'value' => 'foo',
     284            ),
     285
     286            // Has no key
     287            array(
     288                'value' => 'bar',
     289            ),
     290        ) );
     291
     292        $sql = $query1->get_sql( 'post', $wpdb->posts, 'ID', $this );
     293
     294        // 'foo' and 'bar' should be queried against the non-aliased table
     295        $this->assertSame( 1, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'foo'" ) );
     296        $this->assertSame( 1, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'bar'" ) );
     297
     298        // NOT EXISTS compare queries are not key-only so should not be non-aliased
     299        $this->assertSame( 0, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'baz'" ) );
     300
     301        // When a value exists, it's not a key-only query
     302        $this->assertSame( 0, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'barry'" ) );
     303
     304        // 'AND' queries don't have key-only queries
     305        $query2 = new WP_Meta_Query( array(
     306            'relation' => 'AND',
     307
     308            // Empty 'compare'
     309            array(
     310                'key' => 'foo',
     311            ),
     312
     313            // Non-empty 'compare'
     314            array(
     315                'key' => 'bar',
     316                'compare' => '<',
     317            ),
     318        ) );
     319
     320        $sql = $query2->get_sql( 'post', $wpdb->posts, 'ID', $this );
     321
     322        // Only 'foo' should be queried against the non-aliased table
     323        $this->assertSame( 1, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'foo'" ) );
     324        $this->assertSame( 0, substr_count( $sql['where'], "$wpdb->postmeta.meta_key = 'bar'" ) );
     325    }
     326
     327    /**
     328     * Key-only and regular queries should have the key trimmed
     329     */
     330    public function test_get_sql_trim_key() {
     331        global $wpdb;
     332
     333        $query = new WP_Meta_Query( array(
     334            array(
     335                'key' => '  foo  ',
     336            ),
     337            array(
     338                'key' => '  bar  ',
     339                'value' => 'value',
     340            ),
     341        ) );
     342
     343        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     344
     345        $this->assertSame( 1, substr_count( $sql['where'], "meta_key = 'foo'" ) );
     346        $this->assertSame( 1, substr_count( $sql['where'], "meta_key = 'bar'" ) );
     347    }
     348
     349    public function test_convert_null_value_to_empty_string() {
     350        global $wpdb;
     351
     352        $query = new WP_Meta_Query( array(
     353            array(
     354                'key' => 'foo',
     355                'value' => null,
     356            ),
     357        ) );
     358
     359        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     360
     361        $this->assertSame( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) = ''" ) );
     362    }
     363
     364    public function test_get_sql_convert_lowercase_compare_to_uppercase() {
     365        global $wpdb;
     366
     367        $query = new WP_Meta_Query( array(
     368            array(
     369                'key' => 'foo',
     370                'value' => 'bar',
     371                'compare' => 'regExp',
     372            ),
     373        ) );
     374
     375        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     376
     377        $this->assertSame( 1, substr_count( $sql['where'], "REGEXP" ) );
     378    }
     379
     380    public function test_get_sql_empty_meta_compare_with_array_value() {
     381        global $wpdb;
     382
     383        $query = new WP_Meta_Query( array(
     384            array(
     385                'key' => 'foo',
     386                'value' => array( 'bar', 'baz' ),
     387            ),
     388        ) );
     389
     390        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     391
     392        $this->assertSame( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) IN" ) );
     393    }
     394
     395    public function test_get_sql_empty_meta_compare_with_non_array_value() {
     396        global $wpdb;
     397
     398        $query = new WP_Meta_Query( array(
     399            array(
     400                'key' => 'foo',
     401                'value' => 'bar',
     402            ),
     403        ) );
     404
     405        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     406
     407        $this->assertSame( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) =" ) );
     408    }
     409
     410    public function test_get_sql_invalid_meta_compare() {
     411        global $wpdb;
     412
     413        $query = new WP_Meta_Query( array(
     414            array(
     415                'key' => 'foo',
     416                'value' => 'bar',
     417                'compare' => 'INVALID COMPARE',
     418            ),
     419        ) );
     420
     421        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     422
     423        $this->assertSame( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) =" ) );
     424    }
     425
     426    /**
     427     * This is the clause that ensures that empty arrays are not valid queries.
     428     */
     429    public function test_get_sql_null_value_and_empty_key_should_not_have_table_join() {
     430        global $wpdb;
     431
     432        $query = new WP_Meta_Query( array(
     433            array(
     434                'key' => 'foo',
     435                'value' => 'bar',
     436            ),
     437            array(),
     438        ) );
     439
     440        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     441
     442        // There should be no JOIN against an aliased table.
     443        $this->assertSame( 0, substr_count( $sql['join'], "AS mt" ) );
     444    }
     445
     446    public function test_get_sql_compare_array_comma_separated_values() {
     447        global $wpdb;
     448
     449        // Single value.
     450        $query = new WP_Meta_Query( array(
     451            array(
     452                'key' => 'foo',
     453                'compare' => 'IN',
     454                'value' => 'bar',
     455            ),
     456        ) );
     457
     458        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     459
     460        $this->assertSame( 1, substr_count( $sql['where'], "('bar')" ) );
     461
     462        // Multiple values, no spaces.
     463        $query = new WP_Meta_Query( array(
     464            array(
     465                'key' => 'foo',
     466                'compare' => 'IN',
     467                'value' => 'bar,baz',
     468            ),
     469        ) );
     470
     471        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     472
     473        $this->assertSame( 1, substr_count( $sql['where'], "('bar','baz')" ) );
     474
     475        // Multiple values, spaces.
     476        $query = new WP_Meta_Query( array(
     477            array(
     478                'key' => 'foo',
     479                'compare' => 'IN',
     480                'value' => 'bar,baz,   barry',
     481            ),
     482        ) );
     483
     484        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     485
     486        $this->assertSame( 1, substr_count( $sql['where'], "('bar','baz','barry')" ) );
     487    }
     488
     489    public function test_get_sql_compare_array() {
     490        global $wpdb;
     491
     492        $query = new WP_Meta_Query( array(
     493            array(
     494                'key' => 'foo',
     495                'compare' => 'IN',
     496                'value' => array( 'bar', 'baz' ),
     497            ),
     498        ) );
     499
     500        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     501
     502        $this->assertSame( 1, substr_count( $sql['where'], "('bar','baz')" ) );
     503    }
     504
     505    /**
     506     * Non-array values are trimmed. @todo Why?
     507     */
     508    public function test_get_sql_trim_string_value() {
     509        global $wpdb;
     510
     511        $query = new WP_Meta_Query( array(
     512            array(
     513                'key' => 'foo',
     514                'value' => '  bar  ',
     515            ),
     516        ) );
     517
     518        $sql = $query->get_sql( 'post', $wpdb->posts, 'ID', $this );
     519
     520        $this->assertSame( 1, substr_count( $sql['where'], "CAST($wpdb->postmeta.meta_value AS CHAR) = 'bar'" ) );
     521    }
     522
     523    public function test_not_exists() {
    157524        global $wpdb;
    158525
     
    175542    }
    176543
    177     function test_empty_compare() {
     544    public function test_empty_compare() {
    178545        global $wpdb;
    179546
Note: See TracChangeset for help on using the changeset viewer.