wordpress-develop/tests/phpunit/tests/rest-api/rest-controller.php
Sergey Biryukov b0f085ece3 Tests: Second pass at merging file-level and class-level DocBlocks in various unit test files.
Per the[https://developer.wordpress.org/coding-standards/inline-documentation-standards/php/#6-file-headers documentation standards], whenever possible, all WordPress files should contain a header DocBlock, regardless of the file’s contents – this includes files containing classes.

However, this recommendation makes less sense for unit test classes if not applied consistently, and the duplicate tags cause some confusion.

This commit aims to reduce confusion and avoid repeating information by combining the DocBlocks.

Follow-up to [55337].

Props sakibmd, fuadragib, robinwpdeveloper, naeemhaque, seakashdiu, jakariaistauk, hasanmisbah, SergeyBiryukov.
Fixes #57723.

git-svn-id: https://develop.svn.wordpress.org/trunk@55457 602fd350-edb4-49c9-b593-d223f7449a82
2023-03-03 14:42:42 +00:00

728 lines
18 KiB
PHP

<?php
/**
* Unit tests covering WP_REST_Controller functionality
*
* @package WordPress
* @subpackage REST API
*
* @group restapi
*/
class WP_Test_REST_Controller extends WP_Test_REST_TestCase {
/**
* @var WP_REST_Request
*/
private $request;
public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
// Load the WP_REST_Test_Controller class if not already loaded.
require_once __DIR__ . '/rest-test-controller.php';
}
public function set_up() {
parent::set_up();
$this->request = new WP_REST_Request(
'GET',
'/wp/v2/testroute',
array(
'args' => array(
'someinteger' => array(
'type' => 'integer',
),
'someboolean' => array(
'type' => 'boolean',
),
'somestring' => array(
'type' => 'string',
),
'somehex' => array(
'type' => 'string',
'format' => 'hex-color',
),
'someenum' => array(
'type' => 'string',
'enum' => array( 'a' ),
),
'somedate' => array(
'type' => 'string',
'format' => 'date-time',
),
'someemail' => array(
'type' => 'string',
'format' => 'email',
),
'someuuid' => array(
'type' => 'string',
'format' => 'uuid',
),
'sometextfield' => array(
'type' => 'string',
'format' => 'text-field',
),
'sometextareafield' => array(
'type' => 'string',
'format' => 'textarea-field',
),
),
)
);
}
public function tear_down() {
global $wp_rest_additional_fields;
$wp_rest_additional_fields = array();
parent::tear_down();
}
public function test_validate_schema_type_integer() {
$this->assertTrue(
rest_validate_request_arg( '123', $this->request, 'someinteger' )
);
$this->assertErrorResponse(
'rest_invalid_type',
rest_validate_request_arg( 'abc', $this->request, 'someinteger' )
);
}
public function test_validate_schema_type_boolean() {
$this->assertTrue(
rest_validate_request_arg( true, $this->request, 'someboolean' )
);
$this->assertTrue(
rest_validate_request_arg( false, $this->request, 'someboolean' )
);
$this->assertTrue(
rest_validate_request_arg( 'true', $this->request, 'someboolean' )
);
$this->assertTrue(
rest_validate_request_arg( 'TRUE', $this->request, 'someboolean' )
);
$this->assertTrue(
rest_validate_request_arg( 'false', $this->request, 'someboolean' )
);
$this->assertTrue(
rest_validate_request_arg( 'False', $this->request, 'someboolean' )
);
$this->assertTrue(
rest_validate_request_arg( '1', $this->request, 'someboolean' )
);
$this->assertTrue(
rest_validate_request_arg( '0', $this->request, 'someboolean' )
);
$this->assertTrue(
rest_validate_request_arg( 1, $this->request, 'someboolean' )
);
$this->assertTrue(
rest_validate_request_arg( 0, $this->request, 'someboolean' )
);
// Check sanitize testing.
$this->assertFalse(
rest_sanitize_request_arg( 'false', $this->request, 'someboolean' )
);
$this->assertFalse(
rest_sanitize_request_arg( '0', $this->request, 'someboolean' )
);
$this->assertFalse(
rest_sanitize_request_arg( 0, $this->request, 'someboolean' )
);
$this->assertFalse(
rest_sanitize_request_arg( 'FALSE', $this->request, 'someboolean' )
);
$this->assertTrue(
rest_sanitize_request_arg( 'true', $this->request, 'someboolean' )
);
$this->assertTrue(
rest_sanitize_request_arg( '1', $this->request, 'someboolean' )
);
$this->assertTrue(
rest_sanitize_request_arg( 1, $this->request, 'someboolean' )
);
$this->assertTrue(
rest_sanitize_request_arg( 'TRUE', $this->request, 'someboolean' )
);
$this->assertErrorResponse(
'rest_invalid_type',
rest_validate_request_arg( '123', $this->request, 'someboolean' )
);
}
public function test_validate_schema_type_string() {
$this->assertTrue(
rest_validate_request_arg( '123', $this->request, 'somestring' )
);
$this->assertErrorResponse(
'rest_invalid_type',
rest_validate_request_arg( array( 'foo' => 'bar' ), $this->request, 'somestring' )
);
}
public function test_validate_schema_enum() {
$this->assertTrue(
rest_validate_request_arg( 'a', $this->request, 'someenum' )
);
$this->assertErrorResponse(
'rest_not_in_enum',
rest_validate_request_arg( 'd', $this->request, 'someenum' )
);
}
public function test_validate_schema_format_email() {
$this->assertTrue(
rest_validate_request_arg( 'joe@foo.bar', $this->request, 'someemail' )
);
$this->assertErrorResponse(
'rest_invalid_email',
rest_validate_request_arg( 'd', $this->request, 'someemail' )
);
}
/**
* @ticket 49270
*/
public function test_validate_schema_format_hex_color() {
$this->assertTrue(
rest_validate_request_arg( '#000000', $this->request, 'somehex' )
);
$this->assertErrorResponse(
'rest_invalid_hex_color',
rest_validate_request_arg( 'wibble', $this->request, 'somehex' )
);
}
public function test_validate_schema_format_date_time() {
$this->assertTrue(
rest_validate_request_arg( '2010-01-01T12:00:00', $this->request, 'somedate' )
);
$this->assertErrorResponse(
'rest_invalid_date',
rest_validate_request_arg( '2010-18-18T12:00:00', $this->request, 'somedate' )
);
}
/**
* @ticket 50053
*/
public function test_validate_schema_format_uuid() {
$this->assertTrue(
rest_validate_request_arg( '123e4567-e89b-12d3-a456-426655440000', $this->request, 'someuuid' )
);
$this->assertErrorResponse(
'rest_invalid_uuid',
rest_validate_request_arg( '123e4567-e89b-12d3-a456-426655440000X', $this->request, 'someuuid' )
);
}
/**
* @ticket 49960
*/
public function test_validate_schema_format_text_field() {
$this->assertTrue(
rest_validate_request_arg( 'Hello World', $this->request, 'sometextfield' )
);
$this->assertErrorResponse(
'rest_invalid_type',
rest_validate_request_arg( false, $this->request, 'sometextfield' )
);
$this->assertSame(
'Hello World',
rest_sanitize_request_arg( 'Hello World', $this->request, 'sometextfield' )
);
$this->assertSame(
'Hello World',
rest_sanitize_request_arg( '<p>Hello World</p>', $this->request, 'sometextfield' )
);
}
/**
* @ticket 49960
*/
public function test_validate_schema_format_textarea_field() {
$this->assertTrue(
rest_validate_request_arg( "Hello\nWorld", $this->request, 'sometextareafield' )
);
$this->assertErrorResponse(
'rest_invalid_type',
rest_validate_request_arg( false, $this->request, 'sometextareafield' )
);
$this->assertSame(
"Hello\nWorld",
rest_sanitize_request_arg( "Hello\nWorld", $this->request, 'sometextareafield' )
);
$this->assertSame(
"Hello\nWorld",
rest_sanitize_request_arg( "<p>Hello\nWorld</p>", $this->request, 'sometextareafield' )
);
}
/**
* @ticket 50876
*/
public function test_get_endpoint_args_for_item_schema() {
$controller = new WP_REST_Test_Controller();
$args = $controller->get_endpoint_args_for_item_schema();
$this->assertArrayHasKey( 'somestring', $args );
$this->assertArrayHasKey( 'someinteger', $args );
$this->assertArrayHasKey( 'someboolean', $args );
$this->assertArrayHasKey( 'someurl', $args );
$this->assertArrayHasKey( 'somedate', $args );
$this->assertArrayHasKey( 'someemail', $args );
$this->assertArrayHasKey( 'somehex', $args );
$this->assertArrayHasKey( 'someuuid', $args );
$this->assertArrayHasKey( 'sometextfield', $args );
$this->assertArrayHasKey( 'sometextareafield', $args );
$this->assertArrayHasKey( 'someenum', $args );
$this->assertArrayHasKey( 'someargoptions', $args );
$this->assertArrayHasKey( 'somedefault', $args );
$this->assertArrayHasKey( 'somearray', $args );
$this->assertArrayHasKey( 'someobject', $args );
}
public function test_get_endpoint_args_for_item_schema_description() {
$controller = new WP_REST_Test_Controller();
$args = rest_get_endpoint_args_for_schema( $controller->get_item_schema() );
$this->assertSame( 'A pretty string.', $args['somestring']['description'] );
$this->assertArrayNotHasKey( 'description', $args['someinteger'] );
}
public function test_get_endpoint_args_for_item_schema_arg_options() {
$controller = new WP_REST_Test_Controller();
$args = rest_get_endpoint_args_for_schema( $controller->get_item_schema() );
$this->assertFalse( $args['someargoptions']['required'] );
$this->assertSame( '__return_true', $args['someargoptions']['sanitize_callback'] );
}
public function test_get_endpoint_args_for_item_schema_default_value() {
$controller = new WP_REST_Test_Controller();
$args = rest_get_endpoint_args_for_schema( $controller->get_item_schema() );
$this->assertSame( 'a', $args['somedefault']['default'] );
}
/**
* @ticket 50301
*/
public function test_get_endpoint_args_for_item_schema_arg_properties() {
$controller = new WP_REST_Test_Controller();
$args = rest_get_endpoint_args_for_schema( $controller->get_item_schema() );
foreach ( array( 'minLength', 'maxLength', 'pattern' ) as $property ) {
$this->assertArrayHasKey( $property, $args['somestring'] );
}
foreach ( array( 'multipleOf', 'minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum' ) as $property ) {
$this->assertArrayHasKey( $property, $args['someinteger'] );
}
$this->assertArrayHasKey( 'items', $args['somearray'] );
foreach ( array( 'minItems', 'maxItems', 'uniqueItems' ) as $property ) {
$this->assertArrayHasKey( $property, $args['somearray'] );
}
$object_properties = array(
'properties',
'patternProperties',
'additionalProperties',
'minProperties',
'maxProperties',
'anyOf',
'oneOf',
);
foreach ( $object_properties as $property ) {
$this->assertArrayHasKey( $property, $args['someobject'] );
}
// Ignored properties.
$this->assertArrayNotHasKey( 'ignored_prop', $args['someobject'] );
}
/**
* @dataProvider data_get_fields_for_response
*/
public function test_get_fields_for_response( $param, $expected ) {
$controller = new WP_REST_Test_Controller();
$request = new WP_REST_Request( 'GET', '/wp/v2/testroute' );
$fields = $controller->get_fields_for_response( $request );
$this->assertSame(
array(
'somestring',
'someinteger',
'someboolean',
'someurl',
'somedate',
'someemail',
'somehex',
'someuuid',
'sometextfield',
'sometextareafield',
'someenum',
'someargoptions',
'somedefault',
'somearray',
'someobject',
'_links',
),
$fields
);
$request->set_param( '_fields', $param );
$fields = $controller->get_fields_for_response( $request );
$this->assertSame( $expected, $fields );
}
public function data_get_fields_for_response() {
return array(
array(
'somestring,someinteger,someinvalidkey',
array(
'somestring',
'someinteger',
),
),
array(
',,',
array(
'somestring',
'someinteger',
'someboolean',
'someurl',
'somedate',
'someemail',
'somehex',
'someuuid',
'sometextfield',
'sometextareafield',
'someenum',
'someargoptions',
'somedefault',
'somearray',
'someobject',
'_links',
),
),
);
}
public function test_get_fields_for_response_respects_embed() {
$controller = new WP_REST_Test_Controller();
$request = new WP_REST_Request( 'GET', '/wp/v2/testroute' );
$this->assertNotContains( '_embedded', $controller->get_fields_for_response( $request ) );
$request->set_param( '_embed', 1 );
$this->assertContains( '_embedded', $controller->get_fields_for_response( $request ) );
}
public function test_get_fields_for_response_filters_by_context() {
$controller = new WP_REST_Test_Controller();
$request = new WP_REST_Request( 'GET', '/wp/v2/testroute' );
$request->set_param( 'context', 'view' );
$schema = $controller->get_item_schema();
$field = 'somefield';
$listener = new MockAction();
$method = 'action';
register_rest_field(
$schema['title'],
$field,
array(
'schema' => array(
'type' => 'string',
'context' => array( 'embed' ),
),
'get_callback' => array( $listener, $method ),
)
);
$controller->prepare_item_for_response( array(), $request );
$this->assertSame( 0, $listener->get_call_count( $method ) );
$request->set_param( 'context', 'embed' );
$controller->prepare_item_for_response( array(), $request );
$this->assertGreaterThan( 0, $listener->get_call_count( $method ) );
}
public function test_filtering_fields_for_response_by_context_returns_fields_with_no_context() {
$controller = new WP_REST_Test_Controller();
$request = new WP_REST_Request( 'GET', '/wp/v2/testroute' );
$request->set_param( 'context', 'view' );
$schema = $controller->get_item_schema();
$field = 'somefield';
$listener = new MockAction();
$method = 'action';
register_rest_field(
$schema['title'],
$field,
array(
'schema' => array(
'type' => 'string',
),
'get_callback' => array( $listener, $method ),
)
);
$controller->prepare_item_for_response( array(), $request );
$this->assertGreaterThan( 0, $listener->get_call_count( $method ) );
}
public function test_filtering_fields_for_response_by_context_returns_fields_with_no_schema() {
$controller = new WP_REST_Test_Controller();
$request = new WP_REST_Request( 'GET', '/wp/v2/testroute' );
$request->set_param( 'context', 'view' );
$schema = $controller->get_item_schema();
$field = 'somefield';
$listener = new MockAction();
$method = 'action';
register_rest_field(
$schema['title'],
$field,
array(
'get_callback' => array( $listener, $method ),
)
);
$controller->prepare_item_for_response( array(), $request );
$this->assertGreaterThan( 0, $listener->get_call_count( $method ) );
}
/**
* @ticket 48785
*/
public function test_get_public_item_schema_with_properties() {
$schema = ( new WP_REST_Test_Controller() )->get_public_item_schema();
// Double-check that the public item schema set in WP_REST_Test_Controller still has properties.
$this->assertArrayHasKey( 'properties', $schema );
// But arg_options should be removed.
$this->assertArrayNotHasKey( 'arg_options', $schema['properties']['someargoptions'] );
}
/**
* @ticket 48785
*/
public function test_get_public_item_schema_no_properties() {
$controller = new WP_REST_Test_Configurable_Controller(
array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'foo',
'type' => 'string',
'description' => 'This is my magical endpoint that just returns a string.',
)
);
// Initial check that the test class is working as expected.
$this->assertArrayNotHasKey( 'properties', $controller->get_public_item_schema() );
// Test that the schema lacking 'properties' is returned as expected.
$this->assertSameSetsWithIndex( $controller->get_public_item_schema(), $controller->get_test_schema() );
}
public function test_add_additional_fields_to_object_respects_fields_param() {
$controller = new WP_REST_Test_Controller();
$request = new WP_REST_Request( 'GET', '/wp/v2/testroute' );
$schema = $controller->get_item_schema();
$field = 'somefield';
$listener = new MockAction();
$method = 'action';
register_rest_field(
$schema['title'],
$field,
array(
'get_callback' => array( $listener, $method ),
'schema' => array(
'type' => 'string',
),
)
);
$item = array();
$controller->prepare_item_for_response( $item, $request );
$first_call_count = $listener->get_call_count( $method );
$this->assertGreaterThan( 0, $first_call_count );
$request->set_param( '_fields', 'somestring' );
$controller->prepare_item_for_response( $item, $request );
$this->assertSame( $first_call_count, $listener->get_call_count( $method ) );
$request->set_param( '_fields', $field );
$controller->prepare_item_for_response( $item, $request );
$this->assertGreaterThan( $first_call_count, $listener->get_call_count( $method ) );
}
/**
* @dataProvider data_filter_nested_registered_rest_fields
* @ticket 49648
*/
public function test_filter_nested_registered_rest_fields( $filter, $expected ) {
$controller = new WP_REST_Test_Controller();
register_rest_field(
'type',
'field',
array(
'schema' => array(
'type' => 'object',
'description' => 'A complex object',
'context' => array( 'view', 'edit' ),
'properties' => array(
'a' => array(
'i' => 'string',
'ii' => 'string',
),
'b' => array(
'iii' => 'string',
'iv' => 'string',
),
),
),
'get_callback' => array( $this, 'register_nested_rest_field_get_callback' ),
)
);
$request = new WP_REST_Request( 'GET', '/wp/v2/testroute' );
$request->set_param( '_fields', $filter );
$response = $controller->prepare_item_for_response( array(), $request );
$response = rest_filter_response_fields( $response, rest_get_server(), $request );
$this->assertSame( $expected, $response->get_data() );
}
public function register_nested_rest_field_get_callback() {
return array(
'a' => array(
'i' => 'value i',
'ii' => 'value ii',
),
'b' => array(
'iii' => 'value iii',
'iv' => 'value iv',
),
);
}
public function data_filter_nested_registered_rest_fields() {
return array(
array(
'field',
array(
'field' => array(
'a' => array(
'i' => 'value i',
'ii' => 'value ii',
),
'b' => array(
'iii' => 'value iii',
'iv' => 'value iv',
),
),
),
),
array(
'field.a',
array(
'field' => array(
'a' => array(
'i' => 'value i',
'ii' => 'value ii',
),
),
),
),
array(
'field.b',
array(
'field' => array(
'b' => array(
'iii' => 'value iii',
'iv' => 'value iv',
),
),
),
),
array(
'field.a.i,field.b.iv',
array(
'field' => array(
'a' => array(
'i' => 'value i',
),
'b' => array(
'iv' => 'value iv',
),
),
),
),
array(
'field.a,field.b.iii',
array(
'field' => array(
'a' => array(
'i' => 'value i',
'ii' => 'value ii',
),
'b' => array(
'iii' => 'value iii',
),
),
),
),
);
}
}