From 07f3c7097e583b148e8ca6b8a7f8d0ae01246f5a Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Mon, 11 Jun 2018 17:54:19 +0000 Subject: [PATCH] REST API: Improve test coverage by providing tests for term meta. See #38323. git-svn-id: https://develop.svn.wordpress.org/trunk@43340 602fd350-edb4-49c9-b593-d223f7449a82 --- .../tests/rest-api/rest-post-meta-fields.php | 2 +- .../tests/rest-api/rest-term-meta-fields.php | 1071 +++++++++++++++++ .../tests/rest-api/rest-users-controller.php | 6 +- 3 files changed, 1075 insertions(+), 4 deletions(-) create mode 100644 tests/phpunit/tests/rest-api/rest-term-meta-fields.php diff --git a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php index 05685791ad..ce04068f87 100644 --- a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php +++ b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php @@ -14,7 +14,7 @@ class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { protected static $post_id; public static function wpSetUpBeforeClass( $factory ) { - self::$wp_meta_keys_saved = $GLOBALS['wp_meta_keys']; + self::$wp_meta_keys_saved = isset( $GLOBALS['wp_meta_keys'] ) ? $GLOBALS['wp_meta_keys'] : array(); self::$post_id = $factory->post->create(); } diff --git a/tests/phpunit/tests/rest-api/rest-term-meta-fields.php b/tests/phpunit/tests/rest-api/rest-term-meta-fields.php new file mode 100644 index 0000000000..6680dde255 --- /dev/null +++ b/tests/phpunit/tests/rest-api/rest-term-meta-fields.php @@ -0,0 +1,1071 @@ +category->create(); + } + + public static function wpTearDownAfterClass() { + $GLOBALS['wp_meta_keys'] = self::$wp_meta_keys_saved; + wp_delete_term( self::$category_id, 'category' ); + } + + public function setUp() { + parent::setUp(); + + register_meta( + 'term', 'test_single', array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + ) + ); + register_meta( + 'term', 'test_multi', array( + 'show_in_rest' => true, + 'single' => false, + 'type' => 'string', + ) + ); + register_meta( + 'term', 'test_bad_auth', array( + 'show_in_rest' => true, + 'single' => true, + 'auth_callback' => '__return_false', + 'type' => 'string', + ) + ); + register_meta( + 'term', 'test_bad_auth_multi', array( + 'show_in_rest' => true, + 'single' => false, + 'auth_callback' => '__return_false', + 'type' => 'string', + ) + ); + register_meta( 'term', 'test_no_rest', array() ); + register_meta( + 'term', 'test_rest_disabled', array( + 'show_in_rest' => false, + 'type' => 'string', + ) + ); + register_meta( + 'term', 'test_custom_schema', array( + 'single' => true, + 'type' => 'integer', + 'show_in_rest' => array( + 'schema' => array( + 'type' => 'number', + ), + ), + ) + ); + register_meta( + 'term', 'test_custom_schema_multi', array( + 'single' => false, + 'type' => 'integer', + 'show_in_rest' => array( + 'schema' => array( + 'type' => 'number', + ), + ), + ) + ); + register_meta( + 'term', 'test_invalid_type', array( + 'single' => true, + 'type' => 'lalala', + 'show_in_rest' => true, + ) + ); + register_meta( + 'term', 'test_no_type', array( + 'single' => true, + 'type' => null, + 'show_in_rest' => true, + ) + ); + + register_meta( + 'term', 'test_custom_name', array( + 'single' => true, + 'type' => 'string', + 'show_in_rest' => array( + 'name' => 'new_name', + ), + ) + ); + + register_meta( + 'term', 'test_custom_name_multi', array( + 'single' => false, + 'type' => 'string', + 'show_in_rest' => array( + 'name' => 'new_name_multi', + ), + ) + ); + + /** @var WP_REST_Server $wp_rest_server */ + global $wp_rest_server; + $wp_rest_server = new Spy_REST_Server; + do_action( 'rest_api_init', $wp_rest_server ); + } + + protected function grant_write_permission() { + // Ensure we have write permission. + $user = $this->factory->user->create( + array( + 'role' => 'editor', + ) + ); + wp_set_current_user( $user ); + } + + public function test_get_value() { + add_term_meta( self::$category_id, 'test_single', 'testvalue' ); + + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $response = rest_get_server()->dispatch( $request ); + + $this->assertEquals( 200, $response->get_status() ); + + $data = $response->get_data(); + $this->assertArrayHasKey( 'meta', $data ); + + $meta = (array) $data['meta']; + $this->assertArrayHasKey( 'test_single', $meta ); + $this->assertEquals( 'testvalue', $meta['test_single'] ); + } + + /** + * @depends test_get_value + */ + public function test_get_multi_value() { + add_term_meta( self::$category_id, 'test_multi', 'value1' ); + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $data = $response->get_data(); + $meta = (array) $data['meta']; + $this->assertArrayHasKey( 'test_multi', $meta ); + $this->assertInternalType( 'array', $meta['test_multi'] ); + $this->assertContains( 'value1', $meta['test_multi'] ); + + // Check after an update. + add_term_meta( self::$category_id, 'test_multi', 'value2' ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + $data = $response->get_data(); + $meta = (array) $data['meta']; + $this->assertContains( 'value1', $meta['test_multi'] ); + $this->assertContains( 'value2', $meta['test_multi'] ); + } + + /** + * @depends test_get_value + */ + public function test_get_unregistered() { + add_term_meta( self::$category_id, 'test_unregistered', 'value1' ); + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $data = $response->get_data(); + $meta = (array) $data['meta']; + $this->assertArrayNotHasKey( 'test_unregistered', $meta ); + } + + /** + * @depends test_get_value + */ + public function test_get_registered_no_api_access() { + add_term_meta( self::$category_id, 'test_no_rest', 'for_the_wicked' ); + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $data = $response->get_data(); + $meta = (array) $data['meta']; + $this->assertArrayNotHasKey( 'test_no_rest', $meta ); + } + + /** + * @depends test_get_value + */ + public function test_get_registered_api_disabled() { + add_term_meta( self::$category_id, 'test_rest_disabled', 'sleepless_nights' ); + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $data = $response->get_data(); + $meta = (array) $data['meta']; + $this->assertArrayNotHasKey( 'test_rest_disabled', $meta ); + } + + public function test_get_value_types() { + register_meta( + 'term', 'test_string', array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + ) + ); + register_meta( + 'term', 'test_number', array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'number', + ) + ); + register_meta( + 'term', 'test_bool', array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'boolean', + ) + ); + + /** @var WP_REST_Server $wp_rest_server */ + global $wp_rest_server; + $wp_rest_server = new Spy_REST_Server; + do_action( 'rest_api_init', $wp_rest_server ); + + add_term_meta( self::$category_id, 'test_string', 42 ); + add_term_meta( self::$category_id, 'test_number', '42' ); + add_term_meta( self::$category_id, 'test_bool', 1 ); + + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $data = $response->get_data(); + $meta = (array) $data['meta']; + + $this->assertArrayHasKey( 'test_string', $meta ); + $this->assertInternalType( 'string', $meta['test_string'] ); + $this->assertSame( '42', $meta['test_string'] ); + + $this->assertArrayHasKey( 'test_number', $meta ); + $this->assertInternalType( 'float', $meta['test_number'] ); + $this->assertSame( 42.0, $meta['test_number'] ); + + $this->assertArrayHasKey( 'test_bool', $meta ); + $this->assertInternalType( 'boolean', $meta['test_bool'] ); + $this->assertSame( true, $meta['test_bool'] ); + } + + public function test_get_value_custom_name() { + add_term_meta( self::$category_id, 'test_custom_name', 'janet' ); + + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $response = rest_get_server()->dispatch( $request ); + + $this->assertEquals( 200, $response->get_status() ); + + $data = $response->get_data(); + $this->assertArrayHasKey( 'meta', $data ); + + $meta = (array) $data['meta']; + $this->assertArrayHasKey( 'new_name', $meta ); + $this->assertEquals( 'janet', $meta['new_name'] ); + } + + /** + * @depends test_get_value + */ + public function test_set_value() { + // Ensure no data exists currently. + $values = get_term_meta( self::$category_id, 'test_single', false ); + $this->assertEmpty( $values ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_single' => 'test_value', + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_single', false ); + $this->assertNotEmpty( $meta ); + $this->assertCount( 1, $meta ); + $this->assertEquals( 'test_value', $meta[0] ); + + $data = $response->get_data(); + $meta = (array) $data['meta']; + $this->assertArrayHasKey( 'test_single', $meta ); + $this->assertEquals( 'test_value', $meta['test_single'] ); + } + + /** + * @depends test_get_value + */ + public function test_set_duplicate_single_value() { + // Start with an existing metakey and value. + $values = update_term_meta( self::$category_id, 'test_single', 'test_value' ); + $this->assertEquals( 'test_value', get_term_meta( self::$category_id, 'test_single', true ) ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_single' => 'test_value', + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_single', true ); + $this->assertNotEmpty( $meta ); + $this->assertEquals( 'test_value', $meta ); + + $data = $response->get_data(); + $meta = (array) $data['meta']; + $this->assertArrayHasKey( 'test_single', $meta ); + $this->assertEquals( 'test_value', $meta['test_single'] ); + } + + /** + * @depends test_set_value + */ + public function test_set_value_unauthenticated() { + $data = array( + 'meta' => array( + 'test_single' => 'test_value', + ), + ); + + wp_set_current_user( 0 ); + + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_cannot_update', $response, 401 ); + + // Check that the value wasn't actually updated. + $this->assertEmpty( get_term_meta( self::$category_id, 'test_single', false ) ); + } + + /** + * @depends test_set_value + */ + public function test_set_value_blocked() { + $data = array( + 'meta' => array( + 'test_bad_auth' => 'test_value', + ), + ); + + $this->grant_write_permission(); + + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_cannot_update', $response, 403 ); + $this->assertEmpty( get_term_meta( self::$category_id, 'test_bad_auth', false ) ); + } + + /** + * @depends test_set_value + */ + public function test_set_value_db_error() { + $data = array( + 'meta' => array( + 'test_single' => 'test_value', + ), + ); + + $this->grant_write_permission(); + + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + /** + * Disable showing error as the below is going to intentionally + * trigger a DB error. + */ + global $wpdb; + $wpdb->suppress_errors = true; + add_filter( 'query', array( $this, 'error_insert_query' ) ); + + $response = rest_get_server()->dispatch( $request ); + remove_filter( 'query', array( $this, 'error_insert_query' ) ); + $wpdb->show_errors = true; + + $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 ); + } + + public function test_set_value_invalid_type() { + $values = get_term_meta( self::$category_id, 'test_invalid_type', false ); + $this->assertEmpty( $values ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_invalid_type' => 'test_value', + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEmpty( get_term_meta( self::$category_id, 'test_invalid_type', false ) ); + } + + public function test_set_value_multiple() { + // Ensure no data exists currently. + $values = get_term_meta( self::$category_id, 'test_multi', false ); + $this->assertEmpty( $values ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_multi' => array( 'val1' ), + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_multi', false ); + $this->assertNotEmpty( $meta ); + $this->assertCount( 1, $meta ); + $this->assertEquals( 'val1', $meta[0] ); + + // Add another value. + $data = array( + 'meta' => array( + 'test_multi' => array( 'val1', 'val2' ), + ), + ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_multi', false ); + $this->assertNotEmpty( $meta ); + $this->assertCount( 2, $meta ); + $this->assertContains( 'val1', $meta ); + $this->assertContains( 'val2', $meta ); + } + + /** + * Test removing only one item with duplicate items. + */ + public function test_set_value_remove_one() { + add_term_meta( self::$category_id, 'test_multi', 'c' ); + add_term_meta( self::$category_id, 'test_multi', 'n' ); + add_term_meta( self::$category_id, 'test_multi', 'n' ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_multi' => array( 'c', 'n' ), + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_multi', false ); + $this->assertNotEmpty( $meta ); + $this->assertCount( 2, $meta ); + $this->assertContains( 'c', $meta ); + $this->assertContains( 'n', $meta ); + } + + /** + * @depends test_set_value_multiple + */ + public function test_set_value_multiple_unauthenticated() { + // Ensure no data exists currently. + $values = get_term_meta( self::$category_id, 'test_multi', false ); + $this->assertEmpty( $values ); + + wp_set_current_user( 0 ); + + $data = array( + 'meta' => array( + 'test_multi' => array( 'val1' ), + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_cannot_update', $response, 401 ); + + $meta = get_term_meta( self::$category_id, 'test_multi', false ); + $this->assertEmpty( $meta ); + } + + public function test_set_value_invalid_value() { + register_meta( + 'term', 'my_meta_key', array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + ) + ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'my_meta_key' => array( 'c', 'n' ), + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + + public function test_set_value_invalid_value_multiple() { + register_meta( + 'term', 'my_meta_key', array( + 'show_in_rest' => true, + 'single' => false, + 'type' => 'string', + ) + ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'my_meta_key' => array( array( 'a' ) ), + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + } + + public function test_set_value_sanitized() { + register_meta( + 'term', 'my_meta_key', array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'integer', + ) + ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'my_meta_key' => '1', // Set to a string. + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertEquals( 1, $data['meta']['my_meta_key'] ); + } + + public function test_set_value_csv() { + register_meta( + 'term', 'my_meta_key', array( + 'show_in_rest' => true, + 'single' => false, + 'type' => 'integer', + ) + ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'my_meta_key' => '1,2,3', // Set to a string. + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + $this->assertEquals( array( 1, 2, 3 ), $data['meta']['my_meta_key'] ); + } + + /** + * @depends test_set_value_multiple + */ + public function test_set_value_multiple_blocked() { + $data = array( + 'meta' => array( + 'test_bad_auth_multi' => array( 'test_value' ), + ), + ); + + $this->grant_write_permission(); + + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_cannot_update', $response, 403 ); + $this->assertEmpty( get_term_meta( self::$category_id, 'test_bad_auth_multi', false ) ); + } + + public function test_add_multi_value_db_error() { + // Ensure no data exists currently. + $values = get_term_meta( self::$category_id, 'test_multi', false ); + $this->assertEmpty( $values ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_multi' => array( 'val1' ), + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + /** + * Disable showing error as the below is going to intentionally + * trigger a DB error. + */ + global $wpdb; + $wpdb->suppress_errors = true; + add_filter( 'query', array( $this, 'error_insert_query' ) ); + + $response = rest_get_server()->dispatch( $request ); + remove_filter( 'query', array( $this, 'error_insert_query' ) ); + $wpdb->show_errors = true; + + $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 ); + } + + /** + * @depends test_get_value + */ + public function test_set_value_single_custom_schema() { + // Ensure no data exists currently. + $values = get_term_meta( self::$category_id, 'test_custom_schema', false ); + $this->assertEmpty( $values ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_custom_schema' => 3, + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_custom_schema', false ); + $this->assertNotEmpty( $meta ); + $this->assertCount( 1, $meta ); + $this->assertEquals( 3, $meta[0] ); + + $data = $response->get_data(); + $meta = (array) $data['meta']; + $this->assertArrayHasKey( 'test_custom_schema', $meta ); + $this->assertEquals( 3, $meta['test_custom_schema'] ); + } + + public function test_set_value_multiple_custom_schema() { + // Ensure no data exists currently. + $values = get_term_meta( self::$category_id, 'test_custom_schema_multi', false ); + $this->assertEmpty( $values ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_custom_schema_multi' => array( 2 ), + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_custom_schema_multi', false ); + $this->assertNotEmpty( $meta ); + $this->assertCount( 1, $meta ); + $this->assertEquals( 2, $meta[0] ); + + // Add another value. + $data = array( + 'meta' => array( + 'test_custom_schema_multi' => array( 2, 8 ), + ), + ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_custom_schema_multi', false ); + $this->assertNotEmpty( $meta ); + $this->assertCount( 2, $meta ); + $this->assertContains( 2, $meta ); + $this->assertContains( 8, $meta ); + } + + /** + * @depends test_get_value_custom_name + */ + public function test_set_value_custom_name() { + // Ensure no data exists currently. + $values = get_term_meta( self::$category_id, 'test_custom_name', false ); + $this->assertEmpty( $values ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'new_name' => 'janet', + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_custom_name', false ); + $this->assertNotEmpty( $meta ); + $this->assertCount( 1, $meta ); + $this->assertEquals( 'janet', $meta[0] ); + + $data = $response->get_data(); + $meta = (array) $data['meta']; + $this->assertArrayHasKey( 'new_name', $meta ); + $this->assertEquals( 'janet', $meta['new_name'] ); + } + + public function test_set_value_custom_name_multiple() { + // Ensure no data exists currently. + $values = get_term_meta( self::$category_id, 'test_custom_name_multi', false ); + $this->assertEmpty( $values ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'new_name_multi' => array( 'janet' ), + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_custom_name_multi', false ); + $this->assertNotEmpty( $meta ); + $this->assertCount( 1, $meta ); + $this->assertEquals( 'janet', $meta[0] ); + + // Add another value. + $data = array( + 'meta' => array( + 'new_name_multi' => array( 'janet', 'graeme' ), + ), + ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_custom_name_multi', false ); + $this->assertNotEmpty( $meta ); + $this->assertCount( 2, $meta ); + $this->assertContains( 'janet', $meta ); + $this->assertContains( 'graeme', $meta ); + } + + /** + * @ticket 38989 + */ + public function test_set_value_invalid_meta_string_request_type() { + update_term_meta( self::$category_id, 'test_single', 'So I tied an onion to my belt, which was the style at the time.' ); + $term_original = get_term( self::$category_id ); + + $this->grant_write_permission(); + + $data = array( + 'name' => 'Ignore this name', + 'meta' => 'Not an array.', + ); + + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + + // The meta value should not have changed. + $current_value = get_term_meta( self::$category_id, 'test_single', true ); + $this->assertEquals( 'So I tied an onion to my belt, which was the style at the time.', $current_value ); + + // Ensure the term name update was not processed. + $term_updated = get_term( self::$category_id ); + $this->assertEquals( $term_original->name, $term_updated->name ); + } + + /** + * @ticket 38989 + */ + public function test_set_value_invalid_meta_float_request_type() { + update_term_meta( self::$category_id, 'test_single', 'Now, to take the ferry cost a nickel, and in those days, nickels had pictures of bumblebees on them.' ); + $term_original = get_term( self::$category_id ); + + $this->grant_write_permission(); + + $data = array( + 'name' => 'Ignore this name', + 'meta' => 1.234, + ); + + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); + + // The meta value should not have changed. + $current_value = get_term_meta( self::$category_id, 'test_single', true ); + $this->assertEquals( 'Now, to take the ferry cost a nickel, and in those days, nickels had pictures of bumblebees on them.', $current_value ); + + // Ensure the term name update was not processed. + $term_updated = get_term( self::$category_id ); + $this->assertEquals( $term_original->name, $term_updated->name ); + } + + public function test_remove_multi_value_db_error() { + add_term_meta( self::$category_id, 'test_multi', 'val1' ); + $values = get_term_meta( self::$category_id, 'test_multi', false ); + $this->assertEquals( array( 'val1' ), $values ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_multi' => array(), + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + /** + * Disable showing error as the below is going to intentionally + * trigger a DB error. + */ + global $wpdb; + $wpdb->suppress_errors = true; + add_filter( 'query', array( $this, 'error_delete_query' ) ); + + $response = rest_get_server()->dispatch( $request ); + remove_filter( 'query', array( $this, 'error_delete_query' ) ); + $wpdb->show_errors = true; + + $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 ); + } + + + public function test_delete_value() { + add_term_meta( self::$category_id, 'test_single', 'val1' ); + $current = get_term_meta( self::$category_id, 'test_single', true ); + $this->assertEquals( 'val1', $current ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_single' => null, + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_single', false ); + $this->assertEmpty( $meta ); + } + + /** + * @depends test_delete_value + */ + public function test_delete_value_blocked() { + add_term_meta( self::$category_id, 'test_bad_auth', 'val1' ); + $current = get_term_meta( self::$category_id, 'test_bad_auth', true ); + $this->assertEquals( 'val1', $current ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_bad_auth' => null, + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertErrorResponse( 'rest_cannot_delete', $response, 403 ); + + $meta = get_term_meta( self::$category_id, 'test_bad_auth', true ); + $this->assertEquals( 'val1', $meta ); + } + + /** + * @depends test_delete_value + */ + public function test_delete_value_db_error() { + add_term_meta( self::$category_id, 'test_single', 'val1' ); + $current = get_term_meta( self::$category_id, 'test_single', true ); + $this->assertEquals( 'val1', $current ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'test_single' => null, + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + /** + * Disable showing error as the below is going to intentionally + * trigger a DB error. + */ + global $wpdb; + $wpdb->suppress_errors = true; + add_filter( 'query', array( $this, 'error_delete_query' ) ); + + $response = rest_get_server()->dispatch( $request ); + remove_filter( 'query', array( $this, 'error_delete_query' ) ); + $wpdb->show_errors = true; + + $this->assertErrorResponse( 'rest_meta_database_error', $response, 500 ); + } + + public function test_delete_value_custom_name() { + add_term_meta( self::$category_id, 'test_custom_name', 'janet' ); + $current = get_term_meta( self::$category_id, 'test_custom_name', true ); + $this->assertEquals( 'janet', $current ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + 'new_name' => null, + ), + ); + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + $this->assertEquals( 200, $response->get_status() ); + + $meta = get_term_meta( self::$category_id, 'test_custom_name', false ); + $this->assertEmpty( $meta ); + } + + public function test_get_schema() { + $request = new WP_REST_Request( 'OPTIONS', sprintf( '/wp/v2/categories/%d', self::$category_id ) ); + $response = rest_get_server()->dispatch( $request ); + + $data = $response->get_data(); + $schema = $data['schema']; + + $this->assertArrayHasKey( 'meta', $schema['properties'] ); + $meta_schema = $schema['properties']['meta']['properties']; + + $this->assertArrayHasKey( 'test_single', $meta_schema ); + $this->assertEquals( 'string', $meta_schema['test_single']['type'] ); + + $this->assertArrayHasKey( 'test_multi', $meta_schema ); + $this->assertEquals( 'array', $meta_schema['test_multi']['type'] ); + $this->assertArrayHasKey( 'items', $meta_schema['test_multi'] ); + $this->assertEquals( 'string', $meta_schema['test_multi']['items']['type'] ); + + $this->assertArrayHasKey( 'test_custom_schema', $meta_schema ); + $this->assertEquals( 'number', $meta_schema['test_custom_schema']['type'] ); + + $this->assertArrayNotHasKey( 'test_no_rest', $meta_schema ); + $this->assertArrayNotHasKey( 'test_rest_disabled', $meta_schema ); + $this->assertArrayNotHasKey( 'test_invalid_type', $meta_schema ); + $this->assertArrayNotHasKey( 'test_no_type', $meta_schema ); + } + + /** + * Internal function used to disable an insert query which + * will trigger a wpdb error for testing purposes. + */ + public function error_insert_query( $query ) { + if ( strpos( $query, 'INSERT' ) === 0 ) { + $query = '],'; + } + return $query; + } + + /** + * Internal function used to disable an insert query which + * will trigger a wpdb error for testing purposes. + */ + public function error_delete_query( $query ) { + if ( strpos( $query, 'DELETE' ) === 0 ) { + $query = '],'; + } + return $query; + } +} diff --git a/tests/phpunit/tests/rest-api/rest-users-controller.php b/tests/phpunit/tests/rest-api/rest-users-controller.php index 0d3960b1c0..f07c2c1d03 100644 --- a/tests/phpunit/tests/rest-api/rest-users-controller.php +++ b/tests/phpunit/tests/rest-api/rest-users-controller.php @@ -884,7 +884,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase { public function test_get_user_invalid_id() { wp_set_current_user( self::$user ); - $request = new WP_REST_Request( 'GET', '/wp/v2/users/100' ); + $request = new WP_REST_Request( 'GET', '/wp/v2/users/7777' ); $response = rest_get_server()->dispatch( $request ); $this->assertErrorResponse( 'rest_user_invalid_id', $response, 404 ); @@ -2248,7 +2248,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase { $this->allow_user_to_manage_multisite(); wp_set_current_user( self::$user ); - $request = new WP_REST_Request( 'DELETE', '/wp/v2/users/100' ); + $request = new WP_REST_Request( 'DELETE', '/wp/v2/users/7777' ); $request['force'] = true; $request->set_param( 'reassign', false ); $response = rest_get_server()->dispatch( $request ); @@ -2300,7 +2300,7 @@ class WP_Test_REST_Users_Controller extends WP_Test_REST_Controller_Testcase { $request = new WP_REST_Request( 'DELETE', sprintf( '/wp/v2/users/%d', $user_id ) ); $request['force'] = true; - $request->set_param( 'reassign', 100 ); + $request->set_param( 'reassign', 7777 ); $response = rest_get_server()->dispatch( $request ); // Not implemented in multisite.