Make WordPress Core

Ticket #38323: 38323.2.diff

File 38323.2.diff, 25.2 KB (added by tharsheblows, 6 years ago)

unit tests for custom post type meta

  • tests/phpunit/tests/rest-api/rest-custom-post-type-meta-fields.php

     
     1<?php
     2/**
     3 * Unit tests covering WP_REST_Posts meta functionality.
     4 *
     5 * @package WordPress
     6 * @subpackage REST API
     7 */
     8
     9 /**
     10  * @group restapi
     11  */
     12class WP_Test_REST_Custom_Post_Type_Meta_Fields extends WP_Test_REST_TestCase {
     13        protected static $post_id;
     14
     15        public static function wpSetUpBeforeClass( $factory ) {
     16                self::$post_id = $factory->post->create( array( 'post_type' => 'cpt' ) );
     17        }
     18
     19        public static function wpTearDownAfterClass() {
     20                wp_delete_post( self::$post_id, true );
     21        }
     22
     23        public function setUp() {
     24                parent::setUp();
     25
     26                $args = array(
     27                        'show_in_rest' => true,
     28                        'supports' => array( 'custom-fields' ),
     29                );
     30
     31                register_post_type( 'cpt', $args );
     32
     33                register_meta( 'post', 'test_single', array(
     34                        'show_in_rest' => true,
     35                        'single' => true,
     36                ));
     37                register_meta( 'post', 'test_multi', array(
     38                        'show_in_rest' => true,
     39                        'single' => false,
     40                ));
     41                register_meta( 'post', 'test_bad_auth', array(
     42                        'show_in_rest' => true,
     43                        'single' => true,
     44                        'auth_callback' => '__return_false',
     45                ));
     46                register_meta( 'post', 'test_bad_auth_multi', array(
     47                        'show_in_rest' => true,
     48                        'single' => false,
     49                        'auth_callback' => '__return_false',
     50                ));
     51                register_meta( 'post', 'test_no_rest', array() );
     52                register_meta( 'post', 'test_rest_disabled', array(
     53                        'show_in_rest' => false,
     54                ));
     55                register_meta( 'post', 'test_custom_schema', array(
     56                        'single' => true,
     57                        'type' => 'integer',
     58                        'show_in_rest' => array(
     59                                'schema' => array(
     60                                        'type' => 'number',
     61                                ),
     62                        ),
     63                ));
     64                register_meta( 'post', 'test_custom_schema_multi', array(
     65                        'single' => false,
     66                        'type' => 'integer',
     67                        'show_in_rest' => array(
     68                                'schema' => array(
     69                                        'type' => 'number',
     70                                ),
     71                        ),
     72                ));
     73                register_meta( 'post', 'test_invalid_type', array(
     74                        'single' => true,
     75                        'type' => false,
     76                        'show_in_rest' => true,
     77                ));
     78                register_meta( 'post', 'test_no_type', array(
     79                        'single' => true,
     80                        'type' => null,
     81                        'show_in_rest' => true,
     82                ));
     83                register_meta( 'post', 'test_custom_name', array(
     84                        'single' => true,
     85                        'type' => 'string',
     86                        'show_in_rest' => array(
     87                                'name'  => 'new_name',
     88                        ),
     89                ));
     90                register_meta( 'post', 'test_custom_name_multi', array(
     91                        'single' => false,
     92                        'type' => 'string',
     93                        'show_in_rest' => array(
     94                                'name'  => 'new_name_multi',
     95                        ),
     96                ));
     97
     98                /** @var WP_REST_Server $wp_rest_server */
     99                global $wp_rest_server;
     100                $this->server = $wp_rest_server = new Spy_REST_Server;
     101                do_action( 'rest_api_init' );
     102        }
     103
     104        protected function grant_write_permission() {
     105                // Ensure we have write permission.
     106                $user = $this->factory->user->create( array(
     107                        'role' => 'editor',
     108                ));
     109                wp_set_current_user( $user );
     110        }
     111
     112        public function test_get_value() {
     113                add_post_meta( self::$post_id, 'test_single', 'testvalue' );
     114
     115                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     116                $response = $this->server->dispatch( $request );
     117
     118                $this->assertEquals( 200, $response->get_status() );
     119
     120                $data = $response->get_data();
     121                $this->assertArrayHasKey( 'meta', $data );
     122
     123                $meta = (array) $data['meta'];
     124                $this->assertArrayHasKey( 'test_single', $meta );
     125                $this->assertEquals( 'testvalue', $meta['test_single'] );
     126        }
     127
     128        /**
     129         * @depends test_get_value
     130         */
     131        public function test_get_multi_value() {
     132                add_post_meta( self::$post_id, 'test_multi', 'value1' );
     133                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     134
     135                $response = $this->server->dispatch( $request );
     136                $this->assertEquals( 200, $response->get_status() );
     137
     138                $data = $response->get_data();
     139                $meta = (array) $data['meta'];
     140                $this->assertArrayHasKey( 'test_multi', $meta );
     141                $this->assertInternalType( 'array', $meta['test_multi'] );
     142                $this->assertContains( 'value1', $meta['test_multi'] );
     143
     144                // Check after an update.
     145                add_post_meta( self::$post_id, 'test_multi', 'value2' );
     146
     147                $response = $this->server->dispatch( $request );
     148                $this->assertEquals( 200, $response->get_status() );
     149                $data = $response->get_data();
     150                $meta = (array) $data['meta'];
     151                $this->assertContains( 'value1', $meta['test_multi'] );
     152                $this->assertContains( 'value2', $meta['test_multi'] );
     153        }
     154
     155        /**
     156         * @depends test_get_value
     157         */
     158        public function test_get_unregistered() {
     159                add_post_meta( self::$post_id, 'test_unregistered', 'value1' );
     160                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     161
     162                $response = $this->server->dispatch( $request );
     163                $this->assertEquals( 200, $response->get_status() );
     164
     165                $data = $response->get_data();
     166                $meta = (array) $data['meta'];
     167                $this->assertArrayNotHasKey( 'test_unregistered', $meta );
     168        }
     169
     170        /**
     171         * @depends test_get_value
     172         */
     173        public function test_get_registered_no_api_access() {
     174                add_post_meta( self::$post_id, 'test_no_rest', 'for_the_wicked' );
     175                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     176
     177                $response = $this->server->dispatch( $request );
     178                $this->assertEquals( 200, $response->get_status() );
     179
     180                $data = $response->get_data();
     181                $meta = (array) $data['meta'];
     182                $this->assertArrayNotHasKey( 'test_no_rest', $meta );
     183        }
     184
     185        /**
     186         * @depends test_get_value
     187         */
     188        public function test_get_registered_api_disabled() {
     189                add_post_meta( self::$post_id, 'test_rest_disabled', 'sleepless_nights' );
     190                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     191
     192                $response = $this->server->dispatch( $request );
     193                $this->assertEquals( 200, $response->get_status() );
     194
     195                $data = $response->get_data();
     196                $meta = (array) $data['meta'];
     197                $this->assertArrayNotHasKey( 'test_rest_disabled', $meta );
     198        }
     199
     200        public function test_get_value_types() {
     201                register_meta( 'post', 'test_string', array(
     202                        'show_in_rest' => true,
     203                        'single' => true,
     204                        'type' => 'string',
     205                ));
     206                register_meta( 'post', 'test_number', array(
     207                        'show_in_rest' => true,
     208                        'single' => true,
     209                        'type' => 'number',
     210                ));
     211                register_meta( 'post', 'test_bool', array(
     212                        'show_in_rest' => true,
     213                        'single' => true,
     214                        'type' => 'boolean',
     215                ));
     216
     217                /** @var WP_REST_Server $wp_rest_server */
     218                global $wp_rest_server;
     219                $this->server = $wp_rest_server = new Spy_REST_Server;
     220                do_action( 'rest_api_init' );
     221
     222                add_post_meta( self::$post_id, 'test_string', 42 );
     223                add_post_meta( self::$post_id, 'test_number', '42' );
     224                add_post_meta( self::$post_id, 'test_bool', 1 );
     225
     226                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     227                $response = $this->server->dispatch( $request );
     228                $this->assertEquals( 200, $response->get_status() );
     229
     230                $data = $response->get_data();
     231                $meta = (array) $data['meta'];
     232
     233                $this->assertArrayHasKey( 'test_string', $meta );
     234                $this->assertInternalType( 'string', $meta['test_string'] );
     235                $this->assertSame( '42', $meta['test_string'] );
     236
     237                $this->assertArrayHasKey( 'test_number', $meta );
     238                $this->assertInternalType( 'float', $meta['test_number'] );
     239                $this->assertSame( 42.0, $meta['test_number'] );
     240
     241                $this->assertArrayHasKey( 'test_bool', $meta );
     242                $this->assertInternalType( 'boolean', $meta['test_bool'] );
     243                $this->assertSame( true, $meta['test_bool'] );
     244        }
     245
     246        public function test_get_value_custom_name() {
     247                add_post_meta( self::$post_id, 'test_custom_name', 'janet' );
     248
     249                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     250                $response = $this->server->dispatch( $request );
     251
     252                $this->assertEquals( 200, $response->get_status() );
     253
     254                $data = $response->get_data();
     255                $this->assertArrayHasKey( 'meta', $data );
     256
     257                $meta = (array) $data['meta'];
     258                $this->assertArrayHasKey( 'new_name', $meta );
     259                $this->assertEquals( 'janet', $meta['new_name'] );
     260        }
     261
     262        /**
     263         * @depends test_get_value
     264         */
     265        public function test_set_value() {
     266                // Ensure no data exists currently.
     267                $values = get_post_meta( self::$post_id, 'test_single', false );
     268                $this->assertEmpty( $values );
     269
     270                $this->grant_write_permission();
     271
     272                $data = array(
     273                        'meta' => array(
     274                                'test_single' => 'test_value',
     275                        ),
     276                );
     277                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     278                $request->set_body_params( $data );
     279
     280                $response = $this->server->dispatch( $request );
     281                $this->assertEquals( 200, $response->get_status() );
     282
     283                $meta = get_post_meta( self::$post_id, 'test_single', false );
     284                $this->assertNotEmpty( $meta );
     285                $this->assertCount( 1, $meta );
     286                $this->assertEquals( 'test_value', $meta[0] );
     287
     288                $data = $response->get_data();
     289                $meta = (array) $data['meta'];
     290                $this->assertArrayHasKey( 'test_single', $meta );
     291                $this->assertEquals( 'test_value', $meta['test_single'] );
     292        }
     293
     294        /**
     295         * @depends test_get_value
     296         */
     297        public function test_set_duplicate_single_value() {
     298                // Start with an existing metakey and value.
     299                $values = update_post_meta( self::$post_id, 'test_single', 'test_value' );
     300                $this->assertEquals( 'test_value', get_post_meta( self::$post_id, 'test_single', true ) );
     301
     302                $this->grant_write_permission();
     303
     304                $data = array(
     305                        'meta' => array(
     306                                'test_single' => 'test_value',
     307                        ),
     308                );
     309                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     310                $request->set_body_params( $data );
     311
     312                $response = $this->server->dispatch( $request );
     313                $this->assertEquals( 200, $response->get_status() );
     314
     315                $meta = get_post_meta( self::$post_id, 'test_single', true );
     316                $this->assertNotEmpty( $meta );
     317                $this->assertEquals( 'test_value', $meta );
     318
     319                $data = $response->get_data();
     320                $meta = (array) $data['meta'];
     321                $this->assertArrayHasKey( 'test_single', $meta );
     322                $this->assertEquals( 'test_value', $meta['test_single'] );
     323        }
     324
     325        /**
     326         * @depends test_set_value
     327         */
     328        public function test_set_value_unauthenticated() {
     329                $data = array(
     330                        'meta' => array(
     331                                'test_single' => 'test_value',
     332                        ),
     333                );
     334
     335                wp_set_current_user( 0 );
     336
     337                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     338                $request->set_body_params( $data );
     339
     340                $response = $this->server->dispatch( $request );
     341                $this->assertErrorResponse( 'rest_cannot_edit', $response, 401 );
     342
     343                // Check that the value wasn't actually updated.
     344                $this->assertEmpty( get_post_meta( self::$post_id, 'test_single', false ) );
     345        }
     346
     347        /**
     348         * @depends test_set_value
     349         */
     350        public function test_set_value_blocked() {
     351                $data = array(
     352                        'meta' => array(
     353                                'test_bad_auth' => 'test_value',
     354                        ),
     355                );
     356
     357                $this->grant_write_permission();
     358
     359                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     360                $request->set_body_params( $data );
     361
     362                $response = $this->server->dispatch( $request );
     363                $this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
     364                $this->assertEmpty( get_post_meta( self::$post_id, 'test_bad_auth', false ) );
     365        }
     366
     367        /**
     368         * @depends test_set_value
     369         */
     370        public function test_set_value_db_error() {
     371                $data = array(
     372                        'meta' => array(
     373                                'test_single' => 'test_value',
     374                        ),
     375                );
     376
     377                $this->grant_write_permission();
     378
     379                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     380                $request->set_body_params( $data );
     381
     382                /**
     383                 * Disable showing error as the below is going to intentionally
     384                 * trigger a DB error.
     385                 */
     386                global $wpdb;
     387                $wpdb->suppress_errors = true;
     388                add_filter( 'query', array( $this, 'error_insert_query' ) );
     389
     390                $response = $this->server->dispatch( $request );
     391                remove_filter( 'query', array( $this, 'error_insert_query' ) );
     392                $wpdb->show_errors = true;
     393        }
     394
     395        public function test_set_value_multiple() {
     396                // Ensure no data exists currently.
     397                $values = get_post_meta( self::$post_id, 'test_multi', false );
     398                $this->assertEmpty( $values );
     399
     400                $this->grant_write_permission();
     401
     402                $data = array(
     403                        'meta' => array(
     404                                'test_multi' => array( 'val1' ),
     405                        ),
     406                );
     407                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     408                $request->set_body_params( $data );
     409
     410                $response = $this->server->dispatch( $request );
     411                $this->assertEquals( 200, $response->get_status() );
     412
     413                $meta = get_post_meta( self::$post_id, 'test_multi', false );
     414                $this->assertNotEmpty( $meta );
     415                $this->assertCount( 1, $meta );
     416                $this->assertEquals( 'val1', $meta[0] );
     417
     418                // Add another value.
     419                $data = array(
     420                        'meta' => array(
     421                                'test_multi' => array( 'val1', 'val2' ),
     422                        ),
     423                );
     424                $request->set_body_params( $data );
     425
     426                $response = $this->server->dispatch( $request );
     427                $this->assertEquals( 200, $response->get_status() );
     428
     429                $meta = get_post_meta( self::$post_id, 'test_multi', false );
     430                $this->assertNotEmpty( $meta );
     431                $this->assertCount( 2, $meta );
     432                $this->assertContains( 'val1', $meta );
     433                $this->assertContains( 'val2', $meta );
     434        }
     435
     436        /**
     437         * Test removing only one item with duplicate items.
     438         */
     439        public function test_set_value_remove_one() {
     440                add_post_meta( self::$post_id, 'test_multi', 'c' );
     441                add_post_meta( self::$post_id, 'test_multi', 'n' );
     442                add_post_meta( self::$post_id, 'test_multi', 'n' );
     443
     444                $this->grant_write_permission();
     445
     446                $data = array(
     447                        'meta' => array(
     448                                'test_multi' => array( 'c', 'n' ),
     449                        ),
     450                );
     451                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     452                $request->set_body_params( $data );
     453
     454                $response = $this->server->dispatch( $request );
     455                $this->assertEquals( 200, $response->get_status() );
     456
     457                $meta = get_post_meta( self::$post_id, 'test_multi', false );
     458                $this->assertNotEmpty( $meta );
     459                $this->assertCount( 2, $meta );
     460                $this->assertContains( 'c', $meta );
     461                $this->assertContains( 'n', $meta );
     462        }
     463
     464        /**
     465         * @depends test_set_value_multiple
     466         */
     467        public function test_set_value_multiple_unauthenticated() {
     468                // Ensure no data exists currently.
     469                $values = get_post_meta( self::$post_id, 'test_multi', false );
     470                $this->assertEmpty( $values );
     471
     472                wp_set_current_user( 0 );
     473
     474                $data = array(
     475                        'meta' => array(
     476                                'test_multi' => array( 'val1' ),
     477                        ),
     478                );
     479                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     480                $request->set_body_params( $data );
     481
     482                $response = $this->server->dispatch( $request );
     483                $this->assertErrorResponse( 'rest_cannot_edit', $response, 401 );
     484
     485                $meta = get_post_meta( self::$post_id, 'test_multi', false );
     486                $this->assertEmpty( $meta );
     487        }
     488
     489        /**
     490         * @depends test_set_value_multiple
     491         */
     492        public function test_set_value_multiple_blocked() {
     493                $data = array(
     494                        'meta' => array(
     495                                'test_bad_auth_multi' => array( 'test_value' ),
     496                        ),
     497                );
     498
     499                $this->grant_write_permission();
     500
     501                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     502                $request->set_body_params( $data );
     503
     504                $response = $this->server->dispatch( $request );
     505                $this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
     506                $this->assertEmpty( get_post_meta( self::$post_id, 'test_bad_auth_multi', false ) );
     507        }
     508
     509        public function test_add_multi_value_db_error() {
     510                // Ensure no data exists currently.
     511                $values = get_post_meta( self::$post_id, 'test_multi', false );
     512                $this->assertEmpty( $values );
     513
     514                $this->grant_write_permission();
     515
     516                $data = array(
     517                        'meta' => array(
     518                                'test_multi' => array( 'val1' ),
     519                        ),
     520                );
     521                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     522                $request->set_body_params( $data );
     523
     524                /**
     525                 * Disable showing error as the below is going to intentionally
     526                 * trigger a DB error.
     527                 */
     528                global $wpdb;
     529                $wpdb->suppress_errors = true;
     530                add_filter( 'query', array( $this, 'error_insert_query' ) );
     531
     532                $response = $this->server->dispatch( $request );
     533                remove_filter( 'query', array( $this, 'error_insert_query' ) );
     534                $wpdb->show_errors = true;
     535
     536                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     537        }
     538
     539        public function test_set_value_multiple_custom_schema() {
     540                // Ensure no data exists currently.
     541                $values = get_post_meta( self::$post_id, 'test_custom_schema_multi', false );
     542                $this->assertEmpty( $values );
     543
     544                $this->grant_write_permission();
     545
     546                $data = array(
     547                        'meta' => array(
     548                                'test_custom_schema_multi' => array( 2 ),
     549                        ),
     550                );
     551                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     552                $request->set_body_params( $data );
     553
     554                $response = $this->server->dispatch( $request );
     555                $this->assertEquals( 200, $response->get_status() );
     556
     557                $meta = get_post_meta( self::$post_id, 'test_custom_schema_multi', false );
     558                $this->assertNotEmpty( $meta );
     559                $this->assertCount( 1, $meta );
     560                $this->assertEquals( 2, $meta[0] );
     561
     562                // Add another value.
     563                $data = array(
     564                        'meta' => array(
     565                                'test_custom_schema_multi' => array( 2, 8 ),
     566                        ),
     567                );
     568                $request->set_body_params( $data );
     569
     570                $response = $this->server->dispatch( $request );
     571                $this->assertEquals( 200, $response->get_status() );
     572
     573                $meta = get_post_meta( self::$post_id, 'test_custom_schema_multi', false );
     574                $this->assertNotEmpty( $meta );
     575                $this->assertCount( 2, $meta );
     576                $this->assertContains( 2, $meta );
     577                $this->assertContains( 8, $meta );
     578        }
     579
     580        /**
     581         * @depends test_get_value_custom_name
     582         */
     583        public function test_set_value_custom_name() {
     584                // Ensure no data exists currently.
     585                $values = get_post_meta( self::$post_id, 'test_custom_name', false );
     586                $this->assertEmpty( $values );
     587
     588                $this->grant_write_permission();
     589
     590                $data = array(
     591                        'meta' => array(
     592                                'new_name' => 'janet',
     593                        ),
     594                );
     595                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     596                $request->set_body_params( $data );
     597
     598                $response = $this->server->dispatch( $request );
     599                $this->assertEquals( 200, $response->get_status() );
     600
     601                $meta = get_post_meta( self::$post_id, 'test_custom_name', false );
     602                $this->assertNotEmpty( $meta );
     603                $this->assertCount( 1, $meta );
     604                $this->assertEquals( 'janet', $meta[0] );
     605
     606                $data = $response->get_data();
     607                $meta = (array) $data['meta'];
     608                $this->assertArrayHasKey( 'new_name', $meta );
     609                $this->assertEquals( 'janet', $meta['new_name'] );
     610        }
     611
     612        public function test_set_value_custom_name_multiple() {
     613                // Ensure no data exists currently.
     614                $values = get_post_meta( self::$post_id, 'test_custom_name_multi', false );
     615                $this->assertEmpty( $values );
     616
     617                $this->grant_write_permission();
     618
     619                $data = array(
     620                        'meta' => array(
     621                                'new_name_multi' => array( 'janet' ),
     622                        ),
     623                );
     624                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     625                $request->set_body_params( $data );
     626
     627                $response = $this->server->dispatch( $request );
     628                $this->assertEquals( 200, $response->get_status() );
     629
     630                $meta = get_post_meta( self::$post_id, 'test_custom_name_multi', false );
     631                $this->assertNotEmpty( $meta );
     632                $this->assertCount( 1, $meta );
     633                $this->assertEquals( 'janet', $meta[0] );
     634
     635                // Add another value.
     636                $data = array(
     637                        'meta' => array(
     638                                'new_name_multi' => array( 'janet', 'graeme' ),
     639                        ),
     640                );
     641                $request->set_body_params( $data );
     642
     643                $response = $this->server->dispatch( $request );
     644                $this->assertEquals( 200, $response->get_status() );
     645
     646                $meta = get_post_meta( self::$post_id, 'test_custom_name_multi', false );
     647                $this->assertNotEmpty( $meta );
     648                $this->assertCount( 2, $meta );
     649                $this->assertContains( 'janet', $meta );
     650                $this->assertContains( 'graeme', $meta );
     651        }
     652
     653        public function test_remove_multi_value_db_error() {
     654                add_post_meta( self::$post_id, 'test_multi', 'val1' );
     655                $values = get_post_meta( self::$post_id, 'test_multi', false );
     656                $this->assertEquals( array( 'val1' ), $values );
     657
     658                $this->grant_write_permission();
     659
     660                $data = array(
     661                        'meta' => array(
     662                                'test_multi' => array(),
     663                        ),
     664                );
     665                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     666                $request->set_body_params( $data );
     667
     668                /**
     669                 * Disable showing error as the below is going to intentionally
     670                 * trigger a DB error.
     671                 */
     672                global $wpdb;
     673                $wpdb->suppress_errors = true;
     674                add_filter( 'query', array( $this, 'error_delete_query' ) );
     675
     676                $response = $this->server->dispatch( $request );
     677                remove_filter( 'query', array( $this, 'error_delete_query' ) );
     678                $wpdb->show_errors = true;
     679
     680                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     681        }
     682
     683        public function test_delete_value() {
     684                add_post_meta( self::$post_id, 'test_single', 'val1' );
     685                $current = get_post_meta( self::$post_id, 'test_single', true );
     686                $this->assertEquals( 'val1', $current );
     687
     688                $this->grant_write_permission();
     689
     690                $data = array(
     691                        'meta' => array(
     692                                'test_single' => null,
     693                        ),
     694                );
     695                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     696                $request->set_body_params( $data );
     697
     698                $response = $this->server->dispatch( $request );
     699                $this->assertEquals( 200, $response->get_status() );
     700
     701                $meta = get_post_meta( self::$post_id, 'test_single', false );
     702                $this->assertEmpty( $meta );
     703        }
     704
     705        /**
     706         * @depends test_delete_value
     707         */
     708        public function test_delete_value_blocked() {
     709                add_post_meta( self::$post_id, 'test_bad_auth', 'val1' );
     710                $current = get_post_meta( self::$post_id, 'test_bad_auth', true );
     711                $this->assertEquals( 'val1', $current );
     712
     713                $this->grant_write_permission();
     714
     715                $data = array(
     716                        'meta' => array(
     717                                'test_bad_auth' => null,
     718                        ),
     719                );
     720                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     721                $request->set_body_params( $data );
     722
     723                $response = $this->server->dispatch( $request );
     724                $this->assertErrorResponse( 'rest_cannot_delete', $response, 403 );
     725
     726                $meta = get_post_meta( self::$post_id, 'test_bad_auth', true );
     727                $this->assertEquals( 'val1', $meta );
     728        }
     729
     730        /**
     731         * @depends test_delete_value
     732         */
     733        public function test_delete_value_db_error() {
     734                add_post_meta( self::$post_id, 'test_single', 'val1' );
     735                $current = get_post_meta( self::$post_id, 'test_single', true );
     736                $this->assertEquals( 'val1', $current );
     737
     738                $this->grant_write_permission();
     739
     740                $data = array(
     741                        'meta' => array(
     742                                'test_single' => null,
     743                        ),
     744                );
     745                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     746                $request->set_body_params( $data );
     747                /**
     748                 * Disable showing error as the below is going to intentionally
     749                 * trigger a DB error.
     750                 */
     751                global $wpdb;
     752                $wpdb->suppress_errors = true;
     753                add_filter( 'query', array( $this, 'error_delete_query' ) );
     754
     755                $response = $this->server->dispatch( $request );
     756                remove_filter( 'query', array( $this, 'error_delete_query' ) );
     757                $wpdb->show_errors = true;
     758
     759                $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 );
     760        }
     761
     762        public function test_delete_value_custom_name() {
     763                add_post_meta( self::$post_id, 'test_custom_name', 'janet' );
     764                $current = get_post_meta( self::$post_id, 'test_custom_name', true );
     765                $this->assertEquals( 'janet', $current );
     766
     767                $this->grant_write_permission();
     768
     769                $data = array(
     770                        'meta' => array(
     771                                'new_name' => null,
     772                        ),
     773                );
     774                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     775                $request->set_body_params( $data );
     776
     777                $response = $this->server->dispatch( $request );
     778                $this->assertEquals( 200, $response->get_status() );
     779
     780                $meta = get_post_meta( self::$post_id, 'test_custom_name', false );
     781                $this->assertEmpty( $meta );
     782        }
     783
     784        public function test_get_schema() {
     785                $request = new WP_REST_Request( 'OPTIONS', sprintf( '/wp/v2/cpt/%d', self::$post_id ) );
     786                $response = $this->server->dispatch( $request );
     787
     788                $data = $response->get_data();
     789                $schema = $data['schema'];
     790
     791                $this->assertArrayHasKey( 'meta', $schema['properties'] );
     792                $meta_schema = $schema['properties']['meta']['properties'];
     793
     794                $this->assertArrayHasKey( 'test_single', $meta_schema );
     795                $this->assertEquals( 'string', $meta_schema['test_single']['type'] );
     796
     797                $this->assertArrayHasKey( 'test_multi', $meta_schema );
     798                $this->assertEquals( 'array', $meta_schema['test_multi']['type'] );
     799                $this->assertArrayHasKey( 'items', $meta_schema['test_multi'] );
     800                $this->assertEquals( 'string', $meta_schema['test_multi']['items']['type'] );
     801
     802                $this->assertArrayHasKey( 'test_custom_schema', $meta_schema );
     803                $this->assertEquals( 'number', $meta_schema['test_custom_schema']['type'] );
     804
     805                $this->assertArrayNotHasKey( 'test_no_rest', $meta_schema );
     806                $this->assertArrayNotHasKey( 'test_rest_disabled', $meta_schema );
     807                $this->assertArrayNotHasKey( 'test_invalid_type', $meta_schema );
     808                $this->assertArrayNotHasKey( 'test_no_type', $meta_schema );
     809        }
     810
     811        /**
     812         * Internal function used to disable an insert query which
     813         * will trigger a wpdb error for testing purposes.
     814         */
     815        public function error_insert_query( $query ) {
     816                if ( strpos( $query, 'INSERT' ) === 0 ) {
     817                        $query = '],';
     818                }
     819                return $query;
     820        }
     821
     822        /**
     823         * Internal function used to disable an insert query which
     824         * will trigger a wpdb error for testing purposes.
     825         */
     826        public function error_delete_query( $query ) {
     827                if ( strpos( $query, 'DELETE' ) === 0 ) {
     828                        $query = '],';
     829                }
     830                return $query;
     831        }
     832}