REST API: Introduce the Content API endpoints.

REST API endpoints for your WordPress content. These endpoints provide machine-readable external access to your WordPress site with a clear, standards-driven interface, allowing new and innovative apps for interacting with your site. These endpoints support all of the following:
- Posts: Read and write access to all post data, for all types of post-based data, including pages and media.
- Comments: Read and write access to all comment data. This includes pingbacks and trackbacks.
- Terms: Read and write access to all term data.
- Users: Read and write access to all user data. This includes public access to some data for post authors.
- Meta: Read and write access to metadata for posts, comments, terms, and users, on an opt-in basis from plugins.
- Settings: Read and write access to settings, on an opt-in basis from plugins and core. This enables API management of key site content values that are technically stored in options, such as site title and byline.

Love your REST API, WordPress!  The infrastructure says, "Let's do lunch!" but the content API endpoints say, "You're paying!"

Props rmccue, rachelbaker, danielbachhuber, joehoyle, adamsilverstein, afurculita, ahmadawais, airesvsg, alisspers, antisilent, apokalyptik, artoliukkonen, attitude, boonebgorges, bradyvercher, brianhogg, caseypatrickdriscoll, chopinbach, chredd, christianesperar, chrisvanpatten, claudiolabarbera, claudiosmweb, cmmarslender, codebykat, coderkevin, codfish, codonnell822, daggerhart, danielpunkass, davidbhayes, delphinus, desrosj, dimadin, dotancohen, DrewAPicture, Dudo1985, duncanjbrown, eherman24, eivhyl, eliorivero, elyobo, en-alis, ericandrewlewis, ericpedia, evansobkowicz, fjarrett, frozzare, georgestephanis, greatislander, guavaworks, hideokamoto, hkdobrev, hubdotcom, hurtige, iandunn, ircrash, ironpaperweight, iseulde, Japh, jaredcobb, JDGrimes, jdolan, jdoubleu, jeremyfelt, jimt, jjeaton, jmusal, jnylen0, johanmynhardt, johnbillion, jonathanbardo, jorbin, joshkadis, JPry, jshreve, jtsternberg, JustinSainton, kacperszurek, kadamwhite, kalenjohnson, kellbot, kjbenk, kokarn, krogsgard, kuchenundkakao, kuldipem, kwight, lgedeon, lukepettway, mantismamita, markoheijnen, matrixik, mattheu, mauteri, maxcutler, mayukojpn, michael-arestad, miyauchi, mjbanks, modemlooper, mrbobbybryant, NateWr, nathanrice, netweb, NikV, nullvariable, oskosk, oso96_2000, oxymoron, pcfreak30, pento, peterwilsoncc, Pezzab, phh, pippinsplugins, pjgalbraith, pkevan, pollyplummer, pushred, quasel, QWp6t, schlessera, schrapel, Shelob9, shprink, simonlampen, Soean, solal, tapsboy, tfrommen, tharsheblows, thenbrent, tierra, tlovett1, tnegri, tobych, Toddses, toro_unit, traversal, vanillalounge, vishalkakadiya, wanecek, web2style, webbgaraget, websupporter, westonruter, whyisjake, wonderboymusic, wpsmith, xknown, zyphonic.
Fixes #38373.

git-svn-id: https://develop.svn.wordpress.org/trunk@38832 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Rachel Baker
2016-10-20 02:54:12 +00:00
parent de3c65804a
commit ede099a704
47 changed files with 21284 additions and 1 deletions
@@ -0,0 +1,862 @@
<?php
/**
* Unit tests covering WP_REST_Attachments_Controller functionality
*
* @package WordPress
* @subpackage REST API
*/
/**
* @group restapi
*/
class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Controller_Testcase {
public function setUp() {
parent::setUp();
$this->editor_id = $this->factory->user->create( array(
'role' => 'editor',
) );
$this->author_id = $this->factory->user->create( array(
'role' => 'author',
) );
$this->contributor_id = $this->factory->user->create( array(
'role' => 'contributor',
) );
// Add an uploader role to test upload capabilities.
add_role( 'uploader', 'File upload role' );
$role = get_role( 'uploader' );
$role->add_cap( 'upload_files' );
$role->add_cap( 'read' );
$role->add_cap( 'level_0' );
$this->uploader_id = $this->factory->user->create( array(
'role' => 'uploader',
) );
$orig_file = DIR_TESTDATA . '/images/canola.jpg';
$this->test_file = '/tmp/canola.jpg';
copy( $orig_file, $this->test_file );
$orig_file2 = DIR_TESTDATA . '/images/codeispoetry.png';
$this->test_file2 = '/tmp/codeispoetry.png';
copy( $orig_file2, $this->test_file2 );
}
public function test_register_routes() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( '/wp/v2/media', $routes );
$this->assertCount( 2, $routes['/wp/v2/media'] );
$this->assertArrayHasKey( '/wp/v2/media/(?P<id>[\d]+)', $routes );
$this->assertCount( 3, $routes['/wp/v2/media/(?P<id>[\d]+)'] );
}
public static function disposition_provider() {
return array(
// Types
array( 'attachment; filename="foo.jpg"', 'foo.jpg' ),
array( 'inline; filename="foo.jpg"', 'foo.jpg' ),
array( 'form-data; filename="foo.jpg"', 'foo.jpg' ),
// Formatting
array( 'attachment; filename="foo.jpg"', 'foo.jpg' ),
array( 'attachment; filename=foo.jpg', 'foo.jpg' ),
array( 'attachment;filename="foo.jpg"', 'foo.jpg' ),
array( 'attachment;filename=foo.jpg', 'foo.jpg' ),
array( 'attachment; filename = "foo.jpg"', 'foo.jpg' ),
array( 'attachment; filename = foo.jpg', 'foo.jpg' ),
array( "attachment;\tfilename\t=\t\"foo.jpg\"", 'foo.jpg' ),
array( "attachment;\tfilename\t=\tfoo.jpg", 'foo.jpg' ),
array( 'attachment; filename = my foo picture.jpg', 'my foo picture.jpg' ),
// Extensions
array( 'form-data; name="myfile"; filename="foo.jpg"', 'foo.jpg' ),
array( 'form-data; name="myfile"; filename="foo.jpg"; something="else"', 'foo.jpg' ),
array( 'form-data; name=myfile; filename=foo.jpg; something=else', 'foo.jpg' ),
array( 'form-data; name=myfile; filename=my foo.jpg; something=else', 'my foo.jpg' ),
// Invalid
array( 'filename="foo.jpg"', null ),
array( 'filename-foo.jpg', null ),
array( 'foo.jpg', null ),
array( 'unknown; notfilename="foo.jpg"', null ),
);
}
/**
* @dataProvider disposition_provider
*/
public function test_parse_disposition( $header, $expected ) {
$header_list = array( $header );
$parsed = WP_REST_Attachments_Controller::get_filename_from_disposition( $header_list );
$this->assertEquals( $expected, $parsed );
}
public function test_context_param() {
// Collection
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/media' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEquals( array( 'view', 'embed', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
// Single
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/media/' . $attachment_id );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEquals( array( 'view', 'embed', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
}
public function test_registered_query_params() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/media' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$keys = array_keys( $data['endpoints'][0]['args'] );
sort( $keys );
$this->assertEquals( array(
'after',
'author',
'author_exclude',
'before',
'context',
'exclude',
'filter',
'include',
'media_type',
'mime_type',
'offset',
'order',
'orderby',
'page',
'parent',
'parent_exclude',
'per_page',
'search',
'slug',
'status',
), $keys );
$media_types = array(
'application',
'video',
'image',
'audio',
);
if ( ! is_multisite() ) {
$media_types[] = 'text';
}
$this->assertEqualSets( $media_types, $data['endpoints'][0]['args']['media_type']['enum'] );
}
public function test_get_items() {
wp_set_current_user( 0 );
$id1 = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$draft_post = $this->factory->post->create( array( 'post_status' => 'draft' ) );
$id2 = $this->factory->attachment->create_object( $this->test_file, $draft_post, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$published_post = $this->factory->post->create( array( 'post_status' => 'publish' ) );
$id3 = $this->factory->attachment->create_object( $this->test_file, $published_post, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertCount( 2, $data );
$ids = wp_list_pluck( $data, 'id' );
$this->assertTrue( in_array( $id1, $ids, true ) );
$this->assertFalse( in_array( $id2, $ids, true ) );
$this->assertTrue( in_array( $id3, $ids, true ) );
$this->check_get_posts_response( $response );
}
public function test_get_items_logged_in_editor() {
wp_set_current_user( $this->editor_id );
$id1 = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$draft_post = $this->factory->post->create( array( 'post_status' => 'draft' ) );
$id2 = $this->factory->attachment->create_object( $this->test_file, $draft_post, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$published_post = $this->factory->post->create( array( 'post_status' => 'publish' ) );
$id3 = $this->factory->attachment->create_object( $this->test_file, $published_post, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertCount( 3, $data );
$ids = wp_list_pluck( $data, 'id' );
$this->assertTrue( in_array( $id1, $ids, true ) );
$this->assertTrue( in_array( $id2, $ids, true ) );
$this->assertTrue( in_array( $id3, $ids, true ) );
}
public function test_get_items_media_type() {
$id1 = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( $id1, $data[0]['id'] );
// media_type=video
$request->set_param( 'media_type', 'video' );
$response = $this->server->dispatch( $request );
$this->assertCount( 0, $response->get_data() );
// media_type=image
$request->set_param( 'media_type', 'image' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( $id1, $data[0]['id'] );
}
public function test_get_items_mime_type() {
$id1 = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( $id1, $data[0]['id'] );
// mime_type=image/png
$request->set_param( 'mime_type', 'image/png' );
$response = $this->server->dispatch( $request );
$this->assertCount( 0, $response->get_data() );
// mime_type=image/jpeg
$request->set_param( 'mime_type', 'image/jpeg' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( $id1, $data[0]['id'] );
}
public function test_get_items_parent() {
$post_id = $this->factory->post->create( array( 'post_title' => 'Test Post' ) );
$attachment_id = $this->factory->attachment->create_object( $this->test_file, $post_id, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$attachment_id2 = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
// all attachments
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 2, count( $response->get_data() ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
// attachments without a parent
$request->set_param( 'parent', 0 );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( $attachment_id2, $data[0]['id'] );
// attachments with parent=post_id
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
$request->set_param( 'parent', $post_id );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( $attachment_id, $data[0]['id'] );
// attachments with invalid parent
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
$request->set_param( 'parent', REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 0, count( $data ) );
}
public function test_get_items_invalid_status_param_is_discarded() {
wp_set_current_user( $this->editor_id );
$this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
$request->set_param( 'status', 'publish' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertCount( 1, $data );
$this->assertEquals( 'inherit', $data[0]['status'] );
}
public function test_get_items_private_status() {
// Logged out users can't make the request
wp_set_current_user( 0 );
$attachment_id1 = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
'post_status' => 'private',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
$request->set_param( 'status', 'private' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
// Properly authorized users can make the request
wp_set_current_user( $this->editor_id );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( $attachment_id1, $data[0]['id'] );
}
public function test_get_items_invalid_date() {
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
$request->set_param( 'after', rand_str() );
$request->set_param( 'before', rand_str() );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
}
public function test_get_items_valid_date() {
$id1 = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_date' => '2016-01-15T00:00:00Z',
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$id2 = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_date' => '2016-01-16T00:00:00Z',
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$id3 = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_date' => '2016-01-17T00:00:00Z',
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
$request->set_param( 'after', '2016-01-15T00:00:00Z' );
$request->set_param( 'before', '2016-01-17T00:00:00Z' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertCount( 1, $data );
$this->assertEquals( $id2, $data[0]['id'] );
}
public function test_get_item() {
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
update_post_meta( $attachment_id, '_wp_attachment_image_alt', 'Sample alt text' );
$request = new WP_REST_Request( 'GET', '/wp/v2/media/' . $attachment_id );
$response = $this->server->dispatch( $request );
$this->check_get_post_response( $response );
$data = $response->get_data();
$this->assertEquals( 'image/jpeg', $data['mime_type'] );
}
public function test_get_item_sizes() {
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
), $this->test_file );
add_image_size( 'rest-api-test', 119, 119, true );
wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $this->test_file ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/media/' . $attachment_id );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$image_src = wp_get_attachment_image_src( $attachment_id, 'rest-api-test' );
$original_image_src = wp_get_attachment_image_src( $attachment_id, 'full' );
remove_image_size( 'rest-api-test' );
$this->assertEquals( $image_src[0], $data['media_details']['sizes']['rest-api-test']['source_url'] );
$this->assertEquals( 'image/jpeg', $data['media_details']['sizes']['rest-api-test']['mime_type'] );
$this->assertEquals( $original_image_src[0], $data['media_details']['sizes']['full']['source_url'] );
$this->assertEquals( 'image/jpeg', $data['media_details']['sizes']['full']['mime_type'] );
}
public function test_get_item_sizes_with_no_url() {
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
), $this->test_file );
add_image_size( 'rest-api-test', 119, 119, true );
wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $this->test_file ) );
add_filter( 'wp_get_attachment_image_src', '__return_false' );
$request = new WP_REST_Request( 'GET', '/wp/v2/media/' . $attachment_id );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
remove_filter( 'wp_get_attachment_image_src', '__return_false' );
remove_image_size( 'rest-api-test' );
$this->assertFalse( isset( $data['media_details']['sizes']['rest-api-test']['source_url'] ) );
}
public function test_get_item_private_post() {
wp_set_current_user( 0 );
$draft_post = $this->factory->post->create( array( 'post_status' => 'draft' ) );
$id1 = $this->factory->attachment->create_object( $this->test_file, $draft_post, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/media/' . $id1 );
$response = $this->server->dispatch( $request );
$this->assertEquals( 403, $response->get_status() );
}
public function test_create_item() {
wp_set_current_user( $this->author_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_header( 'Content-Type', 'image/jpeg' );
$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );
$request->set_body( file_get_contents( $this->test_file ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 201, $response->get_status() );
$this->assertEquals( 'image', $data['media_type'] );
$this->assertEquals( 'A field of amazing canola', $data['title']['rendered'] );
$this->assertEquals( 'The description for the image', $data['caption'] );
}
public function test_create_item_default_filename_title() {
wp_set_current_user( $this->author_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_file_params( array(
'file' => array(
'file' => file_get_contents( $this->test_file2 ),
'name' => 'codeispoetry.jpg',
'size' => filesize( $this->test_file2 ),
'tmp_name' => $this->test_file2,
),
) );
$request->set_header( 'Content-MD5', md5_file( $this->test_file2 ) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 201, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 'codeispoetry', $data['title']['raw'] );
}
public function test_create_item_with_files() {
wp_set_current_user( $this->author_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_file_params( array(
'file' => array(
'file' => file_get_contents( $this->test_file ),
'name' => 'canola.jpg',
'size' => filesize( $this->test_file ),
'tmp_name' => $this->test_file,
),
) );
$request->set_header( 'Content-MD5', md5_file( $this->test_file ) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 201, $response->get_status() );
}
public function test_create_item_with_upload_files_role() {
wp_set_current_user( $this->uploader_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_file_params( array(
'file' => array(
'file' => file_get_contents( $this->test_file ),
'name' => 'canola.jpg',
'size' => filesize( $this->test_file ),
'tmp_name' => $this->test_file,
),
) );
$request->set_header( 'Content-MD5', md5_file( $this->test_file ) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 201, $response->get_status() );
}
public function test_create_item_empty_body() {
wp_set_current_user( $this->author_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_upload_no_data', $response, 400 );
}
public function test_create_item_missing_content_type() {
wp_set_current_user( $this->author_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_body( file_get_contents( $this->test_file ) );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_upload_no_content_type', $response, 400 );
}
public function test_create_item_missing_content_disposition() {
wp_set_current_user( $this->author_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_header( 'Content-Type', 'image/jpeg' );
$request->set_body( file_get_contents( $this->test_file ) );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_upload_no_content_disposition', $response, 400 );
}
public function test_create_item_bad_md5_header() {
wp_set_current_user( $this->author_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_header( 'Content-Type', 'image/jpeg' );
$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );
$request->set_header( 'Content-MD5', 'abc123' );
$request->set_body( file_get_contents( $this->test_file ) );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_upload_hash_mismatch', $response, 412 );
}
public function test_create_item_with_files_bad_md5_header() {
wp_set_current_user( $this->author_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_file_params( array(
'file' => array(
'file' => file_get_contents( $this->test_file ),
'name' => 'canola.jpg',
'size' => filesize( $this->test_file ),
'tmp_name' => $this->test_file,
),
) );
$request->set_header( 'Content-MD5', 'abc123' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_upload_hash_mismatch', $response, 412 );
}
public function test_create_item_invalid_upload_files_capability() {
wp_set_current_user( $this->contributor_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_create', $response, 403 );
}
public function test_create_item_invalid_edit_permissions() {
$post_id = $this->factory->post->create( array( 'post_author' => $this->editor_id ) );
wp_set_current_user( $this->author_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_param( 'post', $post_id );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_edit', $response, 403 );
}
public function test_create_item_invalid_upload_permissions() {
$post_id = $this->factory->post->create( array( 'post_author' => $this->editor_id ) );
wp_set_current_user( $this->uploader_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_param( 'post', $post_id );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_edit', $response, 403 );
}
public function test_create_item_invalid_post_type() {
$attachment_id = $this->factory->post->create( array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_parent' => 0 ) );
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_header( 'Content-Type', 'image/jpeg' );
$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );
$request->set_body( file_get_contents( $this->test_file ) );
$request->set_param( 'post', $attachment_id );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
}
public function test_create_item_alt_text() {
wp_set_current_user( $this->author_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_header( 'Content-Type', 'image/jpeg' );
$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );
$request->set_body( file_get_contents( $this->test_file ) );
$request->set_param( 'alt_text', 'test alt text' );
$response = $this->server->dispatch( $request );
$attachment = $response->get_data();
$this->assertEquals( 'test alt text', $attachment['alt_text'] );
}
public function test_create_item_unsafe_alt_text() {
wp_set_current_user( $this->author_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
$request->set_header( 'Content-Type', 'image/jpeg' );
$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );
$request->set_body( file_get_contents( $this->test_file ) );
$request->set_param( 'alt_text', '<script>alert(document.cookie)</script>' );
$response = $this->server->dispatch( $request );
$attachment = $response->get_data();
$this->assertEquals( '', $attachment['alt_text'] );
}
public function test_update_item() {
wp_set_current_user( $this->editor_id );
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
'post_author' => $this->editor_id,
) );
$request = new WP_REST_Request( 'POST', '/wp/v2/media/' . $attachment_id );
$request->set_param( 'title', 'My title is very cool' );
$request->set_param( 'caption', 'This is a better caption.' );
$request->set_param( 'description', 'Without a description, my attachment is descriptionless.' );
$request->set_param( 'alt_text', 'Alt text is stored outside post schema.' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$attachment = get_post( $data['id'] );
$this->assertEquals( 'My title is very cool', $data['title']['raw'] );
$this->assertEquals( 'My title is very cool', $attachment->post_title );
$this->assertEquals( 'This is a better caption.', $data['caption'] );
$this->assertEquals( 'This is a better caption.', $attachment->post_excerpt );
$this->assertEquals( 'Without a description, my attachment is descriptionless.', $data['description'] );
$this->assertEquals( 'Without a description, my attachment is descriptionless.', $attachment->post_content );
$this->assertEquals( 'Alt text is stored outside post schema.', $data['alt_text'] );
$this->assertEquals( 'Alt text is stored outside post schema.', get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ) );
}
public function test_update_item_parent() {
wp_set_current_user( $this->editor_id );
$original_parent = $this->factory->post->create( array() );
$attachment_id = $this->factory->attachment->create_object( $this->test_file, $original_parent, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
'post_author' => $this->editor_id,
) );
$attachment = get_post( $attachment_id );
$this->assertEquals( $original_parent, $attachment->post_parent );
$new_parent = $this->factory->post->create( array() );
$request = new WP_REST_Request( 'POST', '/wp/v2/media/' . $attachment_id );
$request->set_param( 'post', $new_parent );
$this->server->dispatch( $request );
$attachment = get_post( $attachment_id );
$this->assertEquals( $new_parent, $attachment->post_parent );
}
public function test_update_item_invalid_permissions() {
wp_set_current_user( $this->author_id );
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
'post_author' => $this->editor_id,
) );
$request = new WP_REST_Request( 'POST', '/wp/v2/media/' . $attachment_id );
$request->set_param( 'caption', 'This is a better caption.' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_edit', $response, 403 );
}
public function test_update_item_invalid_post_type() {
$attachment_id = $this->factory->post->create( array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_parent' => 0 ) );
wp_set_current_user( $this->editor_id );
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
'post_author' => $this->editor_id,
) );
$request = new WP_REST_Request( 'POST', '/wp/v2/media/' . $attachment_id );
$request->set_param( 'post', $attachment_id );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
}
public function test_delete_item() {
wp_set_current_user( $this->editor_id );
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/media/' . $attachment_id );
$request['force'] = true;
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
}
public function test_delete_item_no_trash() {
wp_set_current_user( $this->editor_id );
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
// Attempt trashing
$request = new WP_REST_Request( 'DELETE', '/wp/v2/media/' . $attachment_id );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_trash_not_supported', $response, 501 );
// Ensure the post still exists
$post = get_post( $attachment_id );
$this->assertNotEmpty( $post );
}
public function test_delete_item_invalid_delete_permissions() {
wp_set_current_user( $this->author_id );
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
'post_author' => $this->editor_id,
) );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/media/' . $attachment_id );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_delete', $response, 403 );
}
public function test_prepare_item() {
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
'post_author' => $this->editor_id,
) );
$attachment = get_post( $attachment_id );
$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/media/%d', $attachment_id ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->check_post_data( $attachment, $data, 'view', $response->get_links() );
$this->check_post_data( $attachment, $data, 'embed', $response->get_links() );
}
public function test_get_item_schema() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/media' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertEquals( 23, count( $properties ) );
$this->assertArrayHasKey( 'author', $properties );
$this->assertArrayHasKey( 'alt_text', $properties );
$this->assertArrayHasKey( 'caption', $properties );
$this->assertArrayHasKey( 'description', $properties );
$this->assertArrayHasKey( 'comment_status', $properties );
$this->assertArrayHasKey( 'date', $properties );
$this->assertArrayHasKey( 'date_gmt', $properties );
$this->assertArrayHasKey( 'guid', $properties );
$this->assertArrayHasKey( 'id', $properties );
$this->assertArrayHasKey( 'link', $properties );
$this->assertArrayHasKey( 'media_type', $properties );
$this->assertArrayHasKey( 'meta', $properties );
$this->assertArrayHasKey( 'mime_type', $properties );
$this->assertArrayHasKey( 'media_details', $properties );
$this->assertArrayHasKey( 'modified', $properties );
$this->assertArrayHasKey( 'modified_gmt', $properties );
$this->assertArrayHasKey( 'post', $properties );
$this->assertArrayHasKey( 'ping_status', $properties );
$this->assertArrayHasKey( 'status', $properties );
$this->assertArrayHasKey( 'slug', $properties );
$this->assertArrayHasKey( 'source_url', $properties );
$this->assertArrayHasKey( 'title', $properties );
$this->assertArrayHasKey( 'type', $properties );
}
public function test_get_additional_field_registration() {
$schema = array(
'type' => 'integer',
'description' => 'Some integer of mine',
'enum' => array( 1, 2, 3, 4 ),
'context' => array( 'view', 'edit' ),
);
register_rest_field( 'attachment', 'my_custom_int', array(
'schema' => $schema,
'get_callback' => array( $this, 'additional_field_get_callback' ),
) );
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/media' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertArrayHasKey( 'my_custom_int', $data['schema']['properties'] );
$this->assertEquals( $schema, $data['schema']['properties']['my_custom_int'] );
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/media/' . $attachment_id );
$response = $this->server->dispatch( $request );
$this->assertArrayHasKey( 'my_custom_int', $response->data );
global $wp_rest_additional_fields;
$wp_rest_additional_fields = array();
}
public function test_additional_field_update_errors() {
$schema = array(
'type' => 'integer',
'description' => 'Some integer of mine',
'enum' => array( 1, 2, 3, 4 ),
'context' => array( 'view', 'edit' ),
);
register_rest_field( 'attachment', 'my_custom_int', array(
'schema' => $schema,
'get_callback' => array( $this, 'additional_field_get_callback' ),
'update_callback' => array( $this, 'additional_field_update_callback' ),
) );
wp_set_current_user( $this->editor_id );
$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
'post_author' => $this->editor_id,
) );
// Check for error on update.
$request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/media/%d', $attachment_id ) );
$request->set_body_params(array(
'my_custom_int' => 'returnError',
));
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
global $wp_rest_additional_fields;
$wp_rest_additional_fields = array();
}
public function additional_field_get_callback( $object, $request ) {
return 123;
}
public function additional_field_update_callback( $value, $attachment ) {
if ( 'returnError' === $value ) {
return new WP_Error( 'rest_invalid_param', 'Testing an error.', array( 'status' => 400 ) );
}
}
public function tearDown() {
parent::tearDown();
if ( file_exists( $this->test_file ) ) {
unlink( $this->test_file );
}
if ( file_exists( $this->test_file2 ) ) {
unlink( $this->test_file2 );
}
}
protected function check_post_data( $attachment, $data, $context = 'view', $links ) {
parent::check_post_data( $attachment, $data, $context, $links );
$this->assertEquals( get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ), $data['alt_text'] );
$this->assertEquals( $attachment->post_excerpt, $data['caption'] );
$this->assertEquals( $attachment->post_content, $data['description'] );
$this->assertTrue( isset( $data['media_details'] ) );
if ( $attachment->post_parent ) {
$this->assertEquals( $attachment->post_parent, $data['post'] );
} else {
$this->assertNull( $data['post'] );
}
$this->assertEquals( wp_get_attachment_url( $attachment->ID ), $data['source_url'] );
}
}
@@ -0,0 +1,882 @@
<?php
/**
* Unit tests covering WP_REST_Terms_Controller functionality, used for
* Categories.
*
* @package WordPress
* @subpackage REST API
*/
/**
* @group restapi
*/
class WP_Test_REST_Categories_Controller extends WP_Test_REST_Controller_Testcase {
public function setUp() {
parent::setUp();
$this->administrator = $this->factory->user->create( array(
'role' => 'administrator',
) );
$this->subscriber = $this->factory->user->create( array(
'role' => 'subscriber',
) );
}
public function test_register_routes() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( '/wp/v2/categories', $routes );
$this->assertArrayHasKey( '/wp/v2/categories/(?P<id>[\d]+)', $routes );
}
public function test_context_param() {
// Collection
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/categories' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'view', 'embed', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
// Single
$category1 = $this->factory->category->create( array( 'name' => 'Season 5' ) );
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/categories/' . $category1 );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'view', 'embed', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
}
public function test_registered_query_params() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/categories' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$keys = array_keys( $data['endpoints'][0]['args'] );
sort( $keys );
$this->assertEquals( array(
'context',
'exclude',
'hide_empty',
'include',
'order',
'orderby',
'page',
'parent',
'per_page',
'post',
'search',
'slug',
), $keys );
}
public function test_get_items() {
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$response = $this->server->dispatch( $request );
$this->check_get_taxonomy_terms_response( $response );
}
public function test_get_items_invalid_permission_for_context() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_forbidden_context', $response, 401 );
}
public function test_get_items_hide_empty_arg() {
$post_id = $this->factory->post->create();
$category1 = $this->factory->category->create( array( 'name' => 'Season 5' ) );
$category2 = $this->factory->category->create( array( 'name' => 'The Be Sharps' ) );
wp_set_object_terms( $post_id, array( $category1, $category2 ), 'category' );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'hide_empty', true );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( 'Season 5', $data[0]['name'] );
$this->assertEquals( 'The Be Sharps', $data[1]['name'] );
}
public function test_get_items_parent_zero_arg() {
$parent1 = $this->factory->category->create( array( 'name' => 'Homer' ) );
$parent2 = $this->factory->category->create( array( 'name' => 'Marge' ) );
$this->factory->category->create(
array(
'name' => 'Bart',
'parent' => $parent1,
)
);
$this->factory->category->create(
array(
'name' => 'Lisa',
'parent' => $parent2,
)
);
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'parent', 0 );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$args = array(
'hide_empty' => false,
'parent' => 0,
);
$categories = get_terms( 'category', $args );
$this->assertEquals( count( $categories ), count( $data ) );
}
public function test_get_items_parent_zero_arg_string() {
$parent1 = $this->factory->category->create( array( 'name' => 'Homer' ) );
$parent2 = $this->factory->category->create( array( 'name' => 'Marge' ) );
$this->factory->category->create(
array(
'name' => 'Bart',
'parent' => $parent1,
)
);
$this->factory->category->create(
array(
'name' => 'Lisa',
'parent' => $parent2,
)
);
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'parent', '0' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$args = array(
'hide_empty' => false,
'parent' => 0,
);
$categories = get_terms( 'category', $args );
$this->assertEquals( count( $categories ), count( $data ) );
}
public function test_get_items_by_parent_non_found() {
$parent1 = $this->factory->category->create( array( 'name' => 'Homer' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'parent', $parent1 );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( array(), $data );
}
public function test_get_items_invalid_page() {
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'page', 0 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
$data = $response->get_data();
$first_error = array_shift( $data['data']['params'] );
$this->assertContains( 'page must be greater than 1 (inclusive)', $first_error );
}
public function test_get_items_include_query() {
$id1 = $this->factory->category->create();
$this->factory->category->create();
$id3 = $this->factory->category->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
// Orderby=>asc
$request->set_param( 'include', array( $id3, $id1 ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( $id1, $data[0]['id'] );
// Orderby=>include
$request->set_param( 'orderby', 'include' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( $id3, $data[0]['id'] );
}
public function test_get_items_exclude_query() {
$id1 = $this->factory->category->create();
$id2 = $this->factory->category->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertTrue( in_array( $id1, wp_list_pluck( $data, 'id' ), true ) );
$this->assertTrue( in_array( $id2, wp_list_pluck( $data, 'id' ), true ) );
$request->set_param( 'exclude', array( $id2 ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertTrue( in_array( $id1, wp_list_pluck( $data, 'id' ), true ) );
$this->assertFalse( in_array( $id2, wp_list_pluck( $data, 'id' ), true ) );
}
public function test_get_items_orderby_args() {
$this->factory->category->create( array( 'name' => 'Apple' ) );
$this->factory->category->create( array( 'name' => 'Banana' ) );
/*
* Tests:
* - orderby
* - order
* - per_page
*/
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'orderby', 'name' );
$request->set_param( 'order', 'desc' );
$request->set_param( 'per_page', 1 );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( 'Uncategorized', $data[0]['name'] );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'orderby', 'name' );
$request->set_param( 'order', 'asc' );
$request->set_param( 'per_page', 2 );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( 'Apple', $data[0]['name'] );
}
public function test_get_items_orderby_id() {
$this->factory->category->create( array( 'name' => 'Cantaloupe' ) );
$this->factory->category->create( array( 'name' => 'Apple' ) );
$this->factory->category->create( array( 'name' => 'Banana' ) );
// defaults to orderby=name, order=asc
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 'Apple', $data[0]['name'] );
$this->assertEquals( 'Banana', $data[1]['name'] );
$this->assertEquals( 'Cantaloupe', $data[2]['name'] );
$this->assertEquals( 'Uncategorized', $data[3]['name'] );
// orderby=id, with default order=asc
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'orderby', 'id' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 'Uncategorized', $data[0]['name'] );
$this->assertEquals( 'Cantaloupe', $data[1]['name'] );
$this->assertEquals( 'Apple', $data[2]['name'] );
$this->assertEquals( 'Banana', $data[3]['name'] );
// orderby=id, order=desc
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'orderby', 'id' );
$request->set_param( 'order', 'desc' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 'Banana', $data[0]['name'] );
$this->assertEquals( 'Apple', $data[1]['name'] );
$this->assertEquals( 'Cantaloupe', $data[2]['name'] );
}
protected function post_with_categories() {
$post_id = $this->factory->post->create();
$category1 = $this->factory->category->create( array(
'name' => 'DC',
'description' => 'Purveyor of fine detective comics',
) );
$category2 = $this->factory->category->create( array(
'name' => 'Marvel',
'description' => 'Home of the Marvel Universe',
) );
$category3 = $this->factory->category->create( array(
'name' => 'Image',
'description' => 'American independent comic publisher',
) );
wp_set_object_terms( $post_id, array( $category1, $category2, $category3 ), 'category' );
return $post_id;
}
public function test_get_items_post_args() {
$post_id = $this->post_with_categories();
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'post', $post_id );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 3, count( $data ) );
// Check ordered by name by default
$names = wp_list_pluck( $data, 'name' );
$this->assertEquals( array( 'DC', 'Image', 'Marvel' ), $names );
}
public function test_get_items_post_ordered_by_description() {
$post_id = $this->post_with_categories();
// Regular request
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'post', $post_id );
$request->set_param( 'orderby', 'description' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 3, count( $data ) );
$names = wp_list_pluck( $data, 'name' );
$this->assertEquals( array( 'Image', 'Marvel', 'DC' ), $names, 'Terms should be ordered by description' );
// Flip the order
$request->set_param( 'order', 'desc' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 3, count( $data ) );
$names = wp_list_pluck( $data, 'name' );
$this->assertEquals( array( 'DC', 'Marvel', 'Image' ), $names, 'Terms should be reverse-ordered by description' );
}
public function test_get_items_post_ordered_by_id() {
$post_id = $this->post_with_categories();
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'post', $post_id );
$request->set_param( 'orderby', 'id' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 3, count( $data ) );
$names = wp_list_pluck( $data, 'name' );
$this->assertEquals( array( 'DC', 'Marvel', 'Image' ), $names );
}
public function test_get_items_custom_tax_post_args() {
register_taxonomy( 'batman', 'post', array( 'show_in_rest' => true ) );
$controller = new WP_REST_Terms_Controller( 'batman' );
$controller->register_routes();
$term1 = $this->factory->term->create( array( 'name' => 'Cape', 'taxonomy' => 'batman' ) );
$term2 = $this->factory->term->create( array( 'name' => 'Mask', 'taxonomy' => 'batman' ) );
$this->factory->term->create( array( 'name' => 'Car', 'taxonomy' => 'batman' ) );
$post_id = $this->factory->post->create();
wp_set_object_terms( $post_id, array( $term1, $term2 ), 'batman' );
$request = new WP_REST_Request( 'GET', '/wp/v2/batman' );
$request->set_param( 'post', $post_id );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( 'Cape', $data[0]['name'] );
}
public function test_get_items_search_args() {
$this->factory->category->create( array( 'name' => 'Apple' ) );
$this->factory->category->create( array( 'name' => 'Banana' ) );
/*
* Tests:
* - search
*/
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'search', 'App' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( 'Apple', $data[0]['name'] );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'search', 'Garbage' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 0, count( $data ) );
}
public function test_get_items_slug_arg() {
$this->factory->category->create( array( 'name' => 'Apple' ) );
$this->factory->category->create( array( 'name' => 'Banana' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'slug', 'apple' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( 'Apple', $data[0]['name'] );
}
public function test_get_terms_parent_arg() {
$category1 = $this->factory->category->create( array( 'name' => 'Parent' ) );
$this->factory->category->create( array( 'name' => 'Child', 'parent' => $category1 ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'parent', $category1 );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( 'Child', $data[0]['name'] );
}
public function test_get_terms_private_taxonomy() {
register_taxonomy( 'robin', 'post', array( 'public' => false ) );
$this->factory->term->create( array( 'name' => 'Cape', 'taxonomy' => 'robin' ) );
$this->factory->term->create( array( 'name' => 'Mask', 'taxonomy' => 'robin' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/terms/robin' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_no_route', $response, 404 );
}
public function test_get_terms_invalid_taxonomy() {
$request = new WP_REST_Request( 'GET', '/wp/v2/invalid-taxonomy' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_no_route', $response, 404 );
}
public function test_get_terms_pagination_headers() {
// Start of the index + Uncategorized default term
for ( $i = 0; $i < 49; $i++ ) {
$this->factory->category->create( array(
'name' => "Category {$i}",
) );
}
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$response = $this->server->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 50, $headers['X-WP-Total'] );
$this->assertEquals( 5, $headers['X-WP-TotalPages'] );
$this->assertCount( 10, $response->get_data() );
$next_link = add_query_arg( array(
'page' => 2,
), rest_url( 'wp/v2/categories' ) );
$this->assertFalse( stripos( $headers['Link'], 'rel="prev"' ) );
$this->assertContains( '<' . $next_link . '>; rel="next"', $headers['Link'] );
// 3rd page
$this->factory->category->create( array(
'name' => 'Category 51',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'page', 3 );
$response = $this->server->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 51, $headers['X-WP-Total'] );
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
$this->assertCount( 10, $response->get_data() );
$prev_link = add_query_arg( array(
'page' => 2,
), rest_url( 'wp/v2/categories' ) );
$this->assertContains( '<' . $prev_link . '>; rel="prev"', $headers['Link'] );
$next_link = add_query_arg( array(
'page' => 4,
), rest_url( 'wp/v2/categories' ) );
$this->assertContains( '<' . $next_link . '>; rel="next"', $headers['Link'] );
// Last page
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'page', 6 );
$response = $this->server->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 51, $headers['X-WP-Total'] );
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
$this->assertCount( 1, $response->get_data() );
$prev_link = add_query_arg( array(
'page' => 5,
), rest_url( 'wp/v2/categories' ) );
$this->assertContains( '<' . $prev_link . '>; rel="prev"', $headers['Link'] );
$this->assertFalse( stripos( $headers['Link'], 'rel="next"' ) );
// Out of bounds
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'page', 8 );
$response = $this->server->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 51, $headers['X-WP-Total'] );
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
$this->assertCount( 0, $response->get_data() );
$prev_link = add_query_arg( array(
'page' => 6,
), rest_url( 'wp/v2/categories' ) );
$this->assertContains( '<' . $prev_link . '>; rel="prev"', $headers['Link'] );
$this->assertFalse( stripos( $headers['Link'], 'rel="next"' ) );
}
public function test_get_items_per_page_exceeds_number_of_items() {
// Start of the index + Uncategorized default term
for ( $i = 0; $i < 17; $i++ ) {
$this->factory->category->create( array(
'name' => "Category {$i}",
) );
}
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'page', 1 );
$request->set_param( 'per_page', 100 );
$response = $this->server->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 18, $headers['X-WP-Total'] );
$this->assertEquals( 1, $headers['X-WP-TotalPages'] );
$this->assertCount( 18, $response->get_data() );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
$request->set_param( 'page', 2 );
$request->set_param( 'per_page', 100 );
$response = $this->server->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 18, $headers['X-WP-Total'] );
$this->assertEquals( 1, $headers['X-WP-TotalPages'] );
$this->assertCount( 0, $response->get_data() );
}
public function test_get_item() {
$request = new WP_REST_Request( 'GET', '/wp/v2/categories/1' );
$response = $this->server->dispatch( $request );
$this->check_get_taxonomy_term_response( $response );
}
public function test_get_term_invalid_taxonomy() {
$request = new WP_REST_Request( 'GET', '/wp/v2/invalid-taxonomy/1' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_no_route', $response, 404 );
}
public function test_get_term_invalid_term() {
$request = new WP_REST_Request( 'GET', '/wp/v2/categories/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_term_invalid', $response, 404 );
}
public function test_get_item_invalid_permission_for_context() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories/1' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_forbidden_context', $response, 401 );
}
public function test_get_term_private_taxonomy() {
register_taxonomy( 'robin', 'post', array( 'public' => false ) );
$term1 = $this->factory->term->create( array( 'name' => 'Cape', 'taxonomy' => 'robin' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/terms/robin/' . $term1 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_no_route', $response, 404 );
}
public function test_get_item_incorrect_taxonomy() {
register_taxonomy( 'robin', 'post' );
$term1 = $this->factory->term->create( array( 'name' => 'Cape', 'taxonomy' => 'robin' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories/' . $term1 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_term_invalid', $response, 404 );
}
public function test_create_item() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'POST', '/wp/v2/categories' );
$request->set_param( 'name', 'My Awesome Term' );
$request->set_param( 'description', 'This term is so awesome.' );
$request->set_param( 'slug', 'so-awesome' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 201, $response->get_status() );
$headers = $response->get_headers();
$data = $response->get_data();
$this->assertContains( '/wp/v2/categories/' . $data['id'], $headers['Location'] );
$this->assertEquals( 'My Awesome Term', $data['name'] );
$this->assertEquals( 'This term is so awesome.', $data['description'] );
$this->assertEquals( 'so-awesome', $data['slug'] );
}
public function test_create_item_invalid_taxonomy() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'POST', '/wp/v2/invalid-taxonomy' );
$request->set_param( 'name', 'Invalid Taxonomy' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_no_route', $response, 404 );
}
public function test_create_item_incorrect_permissions() {
wp_set_current_user( $this->subscriber );
$request = new WP_REST_Request( 'POST', '/wp/v2/categories' );
$request->set_param( 'name', 'Incorrect permissions' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_create', $response, 403 );
}
public function test_create_item_missing_arguments() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'POST', '/wp/v2/categories' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_missing_callback_param', $response, 400 );
}
public function test_create_item_with_parent() {
wp_set_current_user( $this->administrator );
$parent = wp_insert_term( 'test-category', 'category' );
$request = new WP_REST_Request( 'POST', '/wp/v2/categories' );
$request->set_param( 'name', 'My Awesome Term' );
$request->set_param( 'parent', $parent['term_id'] );
$response = $this->server->dispatch( $request );
$this->assertEquals( 201, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( $parent['term_id'], $data['parent'] );
}
public function test_create_item_invalid_parent() {
wp_set_current_user( $this->administrator );
$term = get_term_by( 'id', $this->factory->category->create(), 'category' );
$request = new WP_REST_Request( 'POST', '/wp/v2/categories/' . $term->term_id );
$request->set_param( 'name', 'My Awesome Term' );
$request->set_param( 'parent', REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_term_invalid', $response, 400 );
}
public function test_update_item() {
wp_set_current_user( $this->administrator );
$orig_args = array(
'name' => 'Original Name',
'description' => 'Original Description',
'slug' => 'original-slug',
);
$term = get_term_by( 'id', $this->factory->category->create( $orig_args ), 'category' );
$request = new WP_REST_Request( 'POST', '/wp/v2/categories/' . $term->term_id );
$request->set_param( 'name', 'New Name' );
$request->set_param( 'description', 'New Description' );
$request->set_param( 'slug', 'new-slug' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 'New Name', $data['name'] );
$this->assertEquals( 'New Description', $data['description'] );
$this->assertEquals( 'new-slug', $data['slug'] );
}
public function test_update_item_invalid_taxonomy() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'POST', '/wp/v2/invalid-taxonomy/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$request->set_param( 'name', 'Invalid Taxonomy' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_no_route', $response, 404 );
}
public function test_update_item_invalid_term() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'POST', '/wp/v2/categories/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$request->set_param( 'name', 'Invalid Term' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_term_invalid', $response, 404 );
}
public function test_update_item_incorrect_permissions() {
wp_set_current_user( $this->subscriber );
$term = get_term_by( 'id', $this->factory->category->create(), 'category' );
$request = new WP_REST_Request( 'POST', '/wp/v2/categories/' . $term->term_id );
$request->set_param( 'name', 'Incorrect permissions' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
}
public function test_update_item_parent() {
wp_set_current_user( $this->administrator );
$parent = get_term_by( 'id', $this->factory->category->create(), 'category' );
$term = get_term_by( 'id', $this->factory->category->create(), 'category' );
$request = new WP_REST_Request( 'POST', '/wp/v2/categories/' . $term->term_taxonomy_id );
$request->set_param( 'parent', $parent->term_id );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( $parent->term_id, $data['parent'] );
}
public function test_update_item_invalid_parent() {
wp_set_current_user( $this->administrator );
$term = get_term_by( 'id', $this->factory->category->create(), 'category' );
$request = new WP_REST_Request( 'POST', '/wp/v2/categories/' . $term->term_id );
$request->set_param( 'parent', REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_term_invalid', $response, 400 );
}
public function test_delete_item() {
wp_set_current_user( $this->administrator );
$term = get_term_by( 'id', $this->factory->category->create( array( 'name' => 'Deleted Category' ) ), 'category' );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/categories/' . $term->term_id );
$request->set_param( 'force', true );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 'Deleted Category', $data['name'] );
}
public function test_delete_item_force_false() {
wp_set_current_user( $this->administrator );
$term = get_term_by( 'id', $this->factory->category->create( array( 'name' => 'Deleted Category' ) ), 'category' );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/categories/' . $term->term_id );
// force defaults to false
$response = $this->server->dispatch( $request );
$this->assertEquals( 501, $response->get_status() );
}
public function test_delete_item_invalid_taxonomy() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/invalid-taxonomy/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_no_route', $response, 404 );
}
public function test_delete_item_invalid_term() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/categories/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_term_invalid', $response, 404 );
}
public function test_delete_item_incorrect_permissions() {
wp_set_current_user( $this->subscriber );
$term = get_term_by( 'id', $this->factory->category->create(), 'category' );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/categories/' . $term->term_id );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_delete', $response, 403 );
}
public function test_prepare_item() {
$term = get_term( 1, 'category' );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories/1' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->check_taxonomy_term( $term, $data, $response->get_links() );
}
public function test_prepare_taxonomy_term_child() {
$child = $this->factory->category->create( array(
'parent' => 1,
) );
$term = get_term( $child, 'category' );
$request = new WP_REST_Request( 'GET', '/wp/v2/categories/' . $child );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->check_taxonomy_term( $term, $data, $response->get_links() );
$this->assertEquals( 1, $data['parent'] );
$links = $response->get_links();
$this->assertEquals( rest_url( 'wp/v2/categories/1' ), $links['up'][0]['href'] );
}
public function test_get_item_schema() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/categories' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertEquals( 9, count( $properties ) );
$this->assertArrayHasKey( 'id', $properties );
$this->assertArrayHasKey( 'count', $properties );
$this->assertArrayHasKey( 'description', $properties );
$this->assertArrayHasKey( 'link', $properties );
$this->assertArrayHasKey( 'meta', $properties );
$this->assertArrayHasKey( 'name', $properties );
$this->assertArrayHasKey( 'parent', $properties );
$this->assertArrayHasKey( 'slug', $properties );
$this->assertArrayHasKey( 'taxonomy', $properties );
$this->assertEquals( array_keys( get_taxonomies() ), $properties['taxonomy']['enum'] );
}
public function test_get_additional_field_registration() {
$schema = array(
'type' => 'integer',
'description' => 'Some integer of mine',
'enum' => array( 1, 2, 3, 4 ),
'context' => array( 'view', 'edit' ),
);
register_rest_field( 'category', 'my_custom_int', array(
'schema' => $schema,
'get_callback' => array( $this, 'additional_field_get_callback' ),
) );
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/categories' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertArrayHasKey( 'my_custom_int', $data['schema']['properties'] );
$this->assertEquals( $schema, $data['schema']['properties']['my_custom_int'] );
$category_id = $this->factory->category->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/categories/' . $category_id );
$response = $this->server->dispatch( $request );
$this->assertArrayHasKey( 'my_custom_int', $response->data );
global $wp_rest_additional_fields;
$wp_rest_additional_fields = array();
}
public function additional_field_get_callback( $object, $request ) {
return 123;
}
public function tearDown() {
_unregister_taxonomy( 'batman' );
_unregister_taxonomy( 'robin' );
parent::tearDown();
}
protected function check_get_taxonomy_terms_response( $response ) {
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$args = array(
'hide_empty' => false,
);
$categories = get_terms( 'category', $args );
$this->assertEquals( count( $categories ), count( $data ) );
$this->assertEquals( $categories[0]->term_id, $data[0]['id'] );
$this->assertEquals( $categories[0]->name, $data[0]['name'] );
$this->assertEquals( $categories[0]->slug, $data[0]['slug'] );
$this->assertEquals( $categories[0]->taxonomy, $data[0]['taxonomy'] );
$this->assertEquals( $categories[0]->description, $data[0]['description'] );
$this->assertEquals( $categories[0]->count, $data[0]['count'] );
}
protected function check_taxonomy_term( $term, $data, $links ) {
$this->assertEquals( $term->term_id, $data['id'] );
$this->assertEquals( $term->name, $data['name'] );
$this->assertEquals( $term->slug, $data['slug'] );
$this->assertEquals( $term->description, $data['description'] );
$this->assertEquals( get_term_link( $term ), $data['link'] );
$this->assertEquals( $term->count, $data['count'] );
$taxonomy = get_taxonomy( $term->taxonomy );
if ( $taxonomy->hierarchical ) {
$this->assertEquals( $term->parent, $data['parent'] );
} else {
$this->assertFalse( isset( $term->parent ) );
}
$relations = array(
'self',
'collection',
'about',
'https://api.w.org/post_type',
);
if ( ! empty( $data['parent'] ) ) {
$relations[] = 'up';
}
$this->assertEqualSets( $relations, array_keys( $links ) );
$this->assertContains( 'wp/v2/taxonomies/' . $term->taxonomy, $links['about'][0]['href'] );
$this->assertEquals( add_query_arg( 'categories', $term->term_id, rest_url( 'wp/v2/posts' ) ), $links['https://api.w.org/post_type'][0]['href'] );
}
protected function check_get_taxonomy_term_response( $response ) {
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$category = get_term( 1, 'category' );
$this->check_taxonomy_term( $category, $data, $response->get_links() );
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,217 @@
<?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 {
public function setUp() {
parent::setUp();
$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',
),
'someenum' => array(
'type' => 'string',
'enum' => array( 'a' ),
),
'somedate' => array(
'type' => 'string',
'format' => 'date-time',
),
'someemail' => array(
'type' => 'string',
'format' => 'email',
),
),
));
}
public function test_validate_schema_type_integer() {
$this->assertTrue(
rest_validate_request_arg( '123', $this->request, 'someinteger' )
);
$this->assertErrorResponse(
'rest_invalid_param',
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->assertEquals( false,
rest_sanitize_request_arg( 'false', $this->request, 'someboolean' )
);
$this->assertEquals( false,
rest_sanitize_request_arg( '0', $this->request, 'someboolean' )
);
$this->assertEquals( false,
rest_sanitize_request_arg( 0, $this->request, 'someboolean' )
);
$this->assertEquals( false,
rest_sanitize_request_arg( 'FALSE', $this->request, 'someboolean' )
);
$this->assertEquals( true,
rest_sanitize_request_arg( 'true', $this->request, 'someboolean' )
);
$this->assertEquals( true,
rest_sanitize_request_arg( '1', $this->request, 'someboolean' )
);
$this->assertEquals( true,
rest_sanitize_request_arg( 1, $this->request, 'someboolean' )
);
$this->assertEquals( true,
rest_sanitize_request_arg( 'TRUE', $this->request, 'someboolean' )
);
$this->assertErrorResponse(
'rest_invalid_param',
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_param',
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_invalid_param',
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' )
);
}
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' )
);
}
public function test_get_endpoint_args_for_item_schema_description() {
$controller = new WP_REST_Test_Controller();
$args = $controller->get_endpoint_args_for_item_schema();
$this->assertEquals( 'A pretty string.', $args['somestring']['description'] );
$this->assertFalse( isset( $args['someinteger']['description'] ) );
}
public function test_get_endpoint_args_for_item_schema_arg_options() {
$controller = new WP_REST_Test_Controller();
$args = $controller->get_endpoint_args_for_item_schema();
$this->assertFalse( $args['someargoptions']['required'] );
$this->assertEquals( '__return_true', $args['someargoptions']['sanitize_callback'] );
}
public function test_get_endpoint_args_for_item_schema_default_value() {
$controller = new WP_REST_Test_Controller();
$args = $controller->get_endpoint_args_for_item_schema();
$this->assertEquals( 'a', $args['somedefault']['default'] );
}
public $rest_the_post_filter_apply_count = 0;
public function test_get_post() {
$post_id = $this->factory()->post->create( array( 'post_title' => 'Original' ) );
$controller = new WP_REST_Test_Controller();
$post = $controller->get_post( $post_id );
$this->assertEquals( 'Original', $post->post_title );
$filter_apply_count = $this->rest_the_post_filter_apply_count;
add_filter( 'rest_the_post', array( $this, 'filter_rest_the_post_for_test_get_post' ), 10, 2 );
$post = $controller->get_post( $post_id );
$this->assertEquals( 'Overridden', $post->post_title );
$this->assertEquals( 1 + $filter_apply_count, $this->rest_the_post_filter_apply_count );
}
public function filter_rest_the_post_for_test_get_post( $post, $post_id ) {
$this->assertInstanceOf( 'WP_Post', $post );
$this->assertInternalType( 'int', $post_id );
$post->post_title = 'Overridden';
$this->rest_the_post_filter_apply_count += 1;
return $post;
}
}
@@ -0,0 +1,407 @@
<?php
/**
* Unit tests covering WP_REST_Posts_Controller functionality, used for
* Pages
*
* @package WordPress
* @subpackage REST API
*/
/**
* @group restapi
*/
class WP_Test_REST_Pages_Controller extends WP_Test_REST_Post_Type_Controller_Testcase {
public function setUp() {
parent::setUp();
$this->editor_id = $this->factory->user->create( array(
'role' => 'editor',
) );
$this->author_id = $this->factory->user->create( array(
'role' => 'author',
) );
$this->has_setup_template = false;
add_filter( 'theme_page_templates', array( $this, 'filter_theme_page_templates' ) );
}
public function test_register_routes() {
}
public function test_context_param() {
// Collection
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/pages' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEquals( array( 'view', 'embed', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
// Single
$page_id = $this->factory->post->create( array( 'post_type' => 'page' ) );
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/pages/' . $page_id );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEquals( array( 'view', 'embed', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
}
public function test_registered_query_params() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/pages' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$keys = array_keys( $data['endpoints'][0]['args'] );
sort( $keys );
$this->assertEquals( array(
'after',
'author',
'author_exclude',
'before',
'context',
'exclude',
'filter',
'include',
'menu_order',
'offset',
'order',
'orderby',
'page',
'parent',
'parent_exclude',
'per_page',
'search',
'slug',
'status',
), $keys );
}
public function test_get_items() {
}
public function test_get_items_parent_query() {
$id1 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page' ) );
$id2 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page', 'post_parent' => $id1 ) );
// No parent
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
// Filter to parent
$request->set_param( 'parent', $id1 );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( $id2, $data[0]['id'] );
}
public function test_get_items_parents_query() {
$id1 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page' ) );
$id2 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page', 'post_parent' => $id1 ) );
$id3 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page' ) );
$id4 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page', 'post_parent' => $id3 ) );
// No parent
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 4, count( $data ) );
// Filter to parents
$request->set_param( 'parent', array( $id1, $id3 ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEqualSets( array( $id2, $id4 ), wp_list_pluck( $data, 'id' ) );
}
public function test_get_items_parent_exclude_query() {
$id1 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page' ) );
$this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page', 'post_parent' => $id1 ) );
// No parent
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
// Filter to parent
$request->set_param( 'parent_exclude', $id1 );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( $id1, $data[0]['id'] );
}
public function test_get_items_menu_order_query() {
$id1 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page' ) );
$id2 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page', 'menu_order' => 2 ) );
$id3 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page', 'menu_order' => 3 ) );
$id4 = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page', 'menu_order' => 1 ) );
// No parent
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEqualSets( array( $id1, $id2, $id3, $id4 ), wp_list_pluck( $data, 'id' ) );
// Filter to menu_order
$request->set_param( 'menu_order', 1 );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEqualSets( array( $id4 ), wp_list_pluck( $data, 'id' ) );
// Order by menu order
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$request->set_param( 'order', 'asc' );
$request->set_param( 'orderby', 'menu_order' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( $id1, $data[0]['id'] );
$this->assertEquals( $id4, $data[1]['id'] );
$this->assertEquals( $id2, $data[2]['id'] );
$this->assertEquals( $id3, $data[3]['id'] );
}
public function test_get_items_min_max_pages_query() {
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$request->set_param( 'per_page', 0 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
$data = $response->get_data();
// Safe format for 4.4 and 4.5 https://core.trac.wordpress.org/ticket/35028
$first_error = array_shift( $data['data']['params'] );
$this->assertContains( 'per_page must be between 1 (inclusive) and 100 (inclusive)', $first_error );
$request->set_param( 'per_page', 101 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
$data = $response->get_data();
$first_error = array_shift( $data['data']['params'] );
$this->assertContains( 'per_page must be between 1 (inclusive) and 100 (inclusive)', $first_error );
}
public function test_get_items_private_filter_query_var() {
// Private query vars inaccessible to unauthorized users
wp_set_current_user( 0 );
$page_id = $this->factory->post->create( array( 'post_status' => 'publish', 'post_type' => 'page' ) );
$draft_id = $this->factory->post->create( array( 'post_status' => 'draft', 'post_type' => 'page' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$request->set_param( 'filter', array( 'post_status' => 'draft' ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertCount( 1, $data );
$this->assertEquals( $page_id, $data[0]['id'] );
// But they are accessible to authorized users
wp_set_current_user( $this->editor_id );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertCount( 1, $data );
$this->assertEquals( $draft_id, $data[0]['id'] );
}
public function test_get_items_invalid_date() {
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$request->set_param( 'after', rand_str() );
$request->set_param( 'before', rand_str() );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
}
public function test_get_items_valid_date() {
$post1 = $this->factory->post->create( array( 'post_date' => '2016-01-15T00:00:00Z', 'post_type' => 'page' ) );
$post2 = $this->factory->post->create( array( 'post_date' => '2016-01-16T00:00:00Z', 'post_type' => 'page' ) );
$post3 = $this->factory->post->create( array( 'post_date' => '2016-01-17T00:00:00Z', 'post_type' => 'page' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$request->set_param( 'after', '2016-01-15T00:00:00Z' );
$request->set_param( 'before', '2016-01-17T00:00:00Z' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertCount( 1, $data );
$this->assertEquals( $post2, $data[0]['id'] );
}
public function test_get_item() {
}
public function test_get_item_invalid_post_type() {
$post_id = $this->factory->post->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/pages/' . $post_id );
$response = $this->server->dispatch( $request );
$this->assertEquals( 404, $response->get_status() );
}
public function test_create_item() {
}
public function test_create_item_with_template() {
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/pages' );
$params = $this->set_post_data( array(
'template' => 'page-my-test-template.php',
) );
$request->set_body_params( $params );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$new_post = get_post( $data['id'] );
$this->assertEquals( 'page-my-test-template.php', $data['template'] );
$this->assertEquals( 'page-my-test-template.php', get_page_template_slug( $new_post->ID ) );
}
public function test_create_page_with_parent() {
$page_id = $this->factory->post->create( array(
'type' => 'page',
) );
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/pages' );
$params = $this->set_post_data( array(
'parent' => $page_id,
) );
$request->set_body_params( $params );
$response = $this->server->dispatch( $request );
$this->assertEquals( 201, $response->get_status() );
$links = $response->get_links();
$this->assertArrayHasKey( 'up', $links );
$data = $response->get_data();
$new_post = get_post( $data['id'] );
$this->assertEquals( $page_id, $data['parent'] );
$this->assertEquals( $page_id, $new_post->post_parent );
}
public function test_create_page_with_invalid_parent() {
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'POST', '/wp/v2/pages' );
$params = $this->set_post_data( array(
'parent' => -1,
) );
$request->set_body_params( $params );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_post_invalid_id', $response, 400 );
}
public function test_update_item() {
}
public function test_delete_item() {
}
public function test_prepare_item() {
}
public function test_get_pages_params() {
$this->factory->post->create_many( 8, array(
'post_type' => 'page',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/pages' );
$request->set_query_params( array(
'page' => 2,
'per_page' => 4,
) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$headers = $response->get_headers();
$this->assertEquals( 8, $headers['X-WP-Total'] );
$this->assertEquals( 2, $headers['X-WP-TotalPages'] );
$all_data = $response->get_data();
$this->assertEquals( 4, count( $all_data ) );
foreach ( $all_data as $post ) {
$this->assertEquals( 'page', $post['type'] );
}
}
public function test_update_page_menu_order() {
$page_id = $this->factory->post->create( array(
'post_type' => 'page',
) );
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/pages/%d', $page_id ) );
$request->set_body_params( array(
'menu_order' => 1,
) );
$response = $this->server->dispatch( $request );
$new_data = $response->get_data();
$this->assertEquals( 1, $new_data['menu_order'] );
}
public function test_update_page_menu_order_to_zero() {
$page_id = $this->factory->post->create( array(
'post_type' => 'page',
'menu_order' => 1,
) );
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/pages/%d', $page_id ) );
$request->set_body_params(array(
'menu_order' => 0,
));
$response = $this->server->dispatch( $request );
$new_data = $response->get_data();
$this->assertEquals( 0, $new_data['menu_order'] );
}
public function test_get_item_schema() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/pages' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertEquals( 21, count( $properties ) );
$this->assertArrayHasKey( 'author', $properties );
$this->assertArrayHasKey( 'comment_status', $properties );
$this->assertArrayHasKey( 'content', $properties );
$this->assertArrayHasKey( 'date', $properties );
$this->assertArrayHasKey( 'date_gmt', $properties );
$this->assertArrayHasKey( 'guid', $properties );
$this->assertArrayHasKey( 'excerpt', $properties );
$this->assertArrayHasKey( 'featured_media', $properties );
$this->assertArrayHasKey( 'id', $properties );
$this->assertArrayHasKey( 'link', $properties );
$this->assertArrayHasKey( 'menu_order', $properties );
$this->assertArrayHasKey( 'meta', $properties );
$this->assertArrayHasKey( 'modified', $properties );
$this->assertArrayHasKey( 'modified_gmt', $properties );
$this->assertArrayHasKey( 'parent', $properties );
$this->assertArrayHasKey( 'ping_status', $properties );
$this->assertArrayHasKey( 'slug', $properties );
$this->assertArrayHasKey( 'status', $properties );
$this->assertArrayHasKey( 'template', $properties );
$this->assertArrayHasKey( 'title', $properties );
$this->assertArrayHasKey( 'type', $properties );
}
public function tearDown() {
parent::tearDown();
remove_filter( 'theme_page_templates', array( $this, 'filter_theme_page_templates' ) );
}
public function filter_theme_page_templates( $page_templates ) {
return array(
'page-my-test-template.php' => 'My Test Template',
);
return $page_templates;
}
protected function set_post_data( $args = array() ) {
$args = parent::set_post_data( $args );
$args['type'] = 'page';
return $args;
}
}
@@ -0,0 +1,636 @@
<?php
/**
* Unit tests covering WP_REST_Posts meta functionality.
*
* @package WordPress
* @subpackage REST API
*/
/**
* @group restapi
*/
class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase {
public function setUp() {
parent::setUp();
register_meta( 'post', 'test_single', array(
'show_in_rest' => true,
'single' => true,
));
register_meta( 'post', 'test_multi', array(
'show_in_rest' => true,
'single' => false,
));
register_meta( 'post', 'test_bad_auth', array(
'show_in_rest' => true,
'single' => true,
'auth_callback' => '__return_false',
));
register_meta( 'post', 'test_bad_auth_multi', array(
'show_in_rest' => true,
'single' => false,
'auth_callback' => '__return_false',
));
register_meta( 'post', 'test_no_rest', array() );
register_meta( 'post', 'test_rest_disabled', array(
'show_in_rest' => false,
));
register_meta( 'post', 'test_custom_schema', array(
'single' => true,
'type' => 'integer',
'show_in_rest' => array(
'schema' => array(
'type' => 'number',
),
),
));
register_meta( 'post', 'test_invalid_type', array(
'single' => true,
'type' => false,
'show_in_rest' => true,
));
/** @var WP_REST_Server $wp_rest_server */
global $wp_rest_server;
$this->server = $wp_rest_server = new Spy_REST_Server;
do_action( 'rest_api_init' );
$this->post_id = $this->factory->post->create();
}
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_post_meta( $this->post_id, 'test_single', 'testvalue' );
$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', $this->post_id ) );
$response = $this->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_post_meta( $this->post_id, 'test_multi', 'value1' );
$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', $this->post_id ) );
$response = $this->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_post_meta( $this->post_id, 'test_multi', 'value2' );
$response = $this->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_post_meta( $this->post_id, 'test_unregistered', 'value1' );
$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', $this->post_id ) );
$response = $this->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_post_meta( $this->post_id, 'test_no_rest', 'for_the_wicked' );
$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', $this->post_id ) );
$response = $this->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_post_meta( $this->post_id, 'test_rest_disabled', 'sleepless_nights' );
$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', $this->post_id ) );
$response = $this->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( 'post', 'test_string', array(
'show_in_rest' => true,
'single' => true,
'type' => 'string',
));
register_meta( 'post', 'test_number', array(
'show_in_rest' => true,
'single' => true,
'type' => 'number',
));
register_meta( 'post', 'test_bool', array(
'show_in_rest' => true,
'single' => true,
'type' => 'boolean',
));
/** @var WP_REST_Server $wp_rest_server */
global $wp_rest_server;
$this->server = $wp_rest_server = new Spy_REST_Server;
do_action( 'rest_api_init' );
add_post_meta( $this->post_id, 'test_string', 42 );
add_post_meta( $this->post_id, 'test_number', '42' );
add_post_meta( $this->post_id, 'test_bool', 1 );
$request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', $this->post_id ) );
$response = $this->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'] );
}
/**
* @depends test_get_value
*/
public function test_set_value() {
// Ensure no data exists currently.
$values = get_post_meta( $this->post_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/posts/%d', $this->post_id ) );
$request->set_body_params( $data );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$meta = get_post_meta( $this->post_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_post_meta( $this->post_id, 'test_single', 'test_value' );
$this->assertEquals( 'test_value', get_post_meta( $this->post_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/posts/%d', $this->post_id ) );
$request->set_body_params( $data );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$meta = get_post_meta( $this->post_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/posts/%d', $this->post_id ) );
$request->set_body_params( $data );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_edit', $response, 401 );
// Check that the value wasn't actually updated.
$this->assertEmpty( get_post_meta( $this->post_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/posts/%d', $this->post_id ) );
$request->set_body_params( $data );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
$this->assertEmpty( get_post_meta( $this->post_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/posts/%d', $this->post_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 = $this->server->dispatch( $request );
remove_filter( 'query', array( $this, 'error_insert_query' ) );
$wpdb->show_errors = true;
}
public function test_set_value_multiple() {
// Ensure no data exists currently.
$values = get_post_meta( $this->post_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/posts/%d', $this->post_id ) );
$request->set_body_params( $data );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$meta = get_post_meta( $this->post_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 = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$meta = get_post_meta( $this->post_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_post_meta( $this->post_id, 'test_multi', 'c' );
add_post_meta( $this->post_id, 'test_multi', 'n' );
add_post_meta( $this->post_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/posts/%d', $this->post_id ) );
$request->set_body_params( $data );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$meta = get_post_meta( $this->post_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_post_meta( $this->post_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/posts/%d', $this->post_id ) );
$request->set_body_params( $data );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_edit', $response, 401 );
$meta = get_post_meta( $this->post_id, 'test_multi', false );
$this->assertEmpty( $meta );
}
/**
* @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/posts/%d', $this->post_id ) );
$request->set_body_params( $data );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
$this->assertEmpty( get_post_meta( $this->post_id, 'test_bad_auth_multi', false ) );
}
public function test_add_multi_value_db_error() {
// Ensure no data exists currently.
$values = get_post_meta( $this->post_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/posts/%d', $this->post_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 = $this->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_remove_multi_value_db_error() {
add_post_meta( $this->post_id, 'test_multi', 'val1' );
$values = get_post_meta( $this->post_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/posts/%d', $this->post_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 = $this->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_post_meta( $this->post_id, 'test_single', 'val1' );
$current = get_post_meta( $this->post_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/posts/%d', $this->post_id ) );
$request->set_body_params( $data );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$meta = get_post_meta( $this->post_id, 'test_single', false );
$this->assertEmpty( $meta );
}
/**
* @depends test_delete_value
*/
public function test_delete_value_blocked() {
add_post_meta( $this->post_id, 'test_bad_auth', 'val1' );
$current = get_post_meta( $this->post_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/posts/%d', $this->post_id ) );
$request->set_body_params( $data );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_delete', $response, 403 );
$meta = get_post_meta( $this->post_id, 'test_bad_auth', true );
$this->assertEquals( 'val1', $meta );
}
/**
* @depends test_delete_value
*/
public function test_delete_value_db_error() {
add_post_meta( $this->post_id, 'test_single', 'val1' );
$current = get_post_meta( $this->post_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/posts/%d', $this->post_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 = $this->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_get_schema() {
$request = new WP_REST_Request( 'OPTIONS', sprintf( '/wp/v2/posts/%d', $this->post_id ) );
$response = $this->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 );
}
/**
* 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;
}
}
@@ -0,0 +1,194 @@
<?php
/**
* Unit tests covering WP_REST_Posts_Statuses_Controller functionality.
*
* @package WordPress
* @subpackage REST API
*/
/**
* @group restapi
*/
class WP_Test_REST_Post_Statuses_Controller extends WP_Test_REST_Controller_Testcase {
public function test_register_routes() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( '/wp/v2/statuses', $routes );
$this->assertArrayHasKey( '/wp/v2/statuses/(?P<status>[\w-]+)', $routes );
}
public function test_context_param() {
// Collection
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/statuses' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'embed', 'view', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
// Single
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/statuses/publish' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'embed', 'view', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
}
public function test_get_items() {
$request = new WP_REST_Request( 'GET', '/wp/v2/statuses' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$statuses = get_post_stati( array( 'public' => true ), 'objects' );
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( 'publish', $data['publish']['slug'] );
}
public function test_get_items_logged_in() {
$user_id = $this->factory->user->create( array( 'role' => 'author' ) );
wp_set_current_user( $user_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/statuses' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 6, count( $data ) );
$this->assertEqualSets( array(
'publish',
'private',
'pending',
'draft',
'trash',
'future',
), array_keys( $data ) );
}
public function test_get_items_unauthorized_context() {
$request = new WP_REST_Request( 'GET', '/wp/v2/statuses' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_view', $response, 401 );
}
public function test_get_item() {
$user_id = $this->factory->user->create( array( 'role' => 'author' ) );
wp_set_current_user( $user_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/statuses/publish' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->check_post_status_object_response( $response );
}
public function test_get_item_invalid_status() {
$request = new WP_REST_Request( 'GET', '/wp/v2/statuses/invalid' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_status_invalid', $response, 404 );
}
public function test_get_item_invalid_access() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/statuses/draft' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_read_status', $response, 401 );
}
public function test_get_item_invalid_internal() {
$user_id = $this->factory->user->create();
wp_set_current_user( $user_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/statuses/inherit' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_read_status', $response, 403 );
}
public function test_create_item() {
/** Post statuses can't be created **/
}
public function test_update_item() {
/** Post statuses can't be updated **/
}
public function test_delete_item() {
/** Post statuses can't be deleted **/
}
public function test_prepare_item() {
$obj = get_post_status_object( 'publish' );
$endpoint = new WP_REST_Post_Statuses_Controller;
$request = new WP_REST_Request;
$request->set_param( 'context', 'edit' );
$data = $endpoint->prepare_item_for_response( $obj, $request );
$this->check_post_status_obj( $obj, $data->get_data(), $data->get_links() );
}
public function test_get_item_schema() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/statuses' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertEquals( 7, count( $properties ) );
$this->assertArrayHasKey( 'name', $properties );
$this->assertArrayHasKey( 'private', $properties );
$this->assertArrayHasKey( 'protected', $properties );
$this->assertArrayHasKey( 'public', $properties );
$this->assertArrayHasKey( 'queryable', $properties );
$this->assertArrayHasKey( 'show_in_list', $properties );
$this->assertArrayHasKey( 'slug', $properties );
}
public function test_get_additional_field_registration() {
$schema = array(
'type' => 'integer',
'description' => 'Some integer of mine',
'enum' => array( 1, 2, 3, 4 ),
'context' => array( 'view', 'edit' ),
);
register_rest_field( 'status', 'my_custom_int', array(
'schema' => $schema,
'get_callback' => array( $this, 'additional_field_get_callback' ),
'update_callback' => array( $this, 'additional_field_update_callback' ),
) );
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/statuses' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertArrayHasKey( 'my_custom_int', $data['schema']['properties'] );
$this->assertEquals( $schema, $data['schema']['properties']['my_custom_int'] );
$request = new WP_REST_Request( 'GET', '/wp/v2/statuses/publish' );
$response = $this->server->dispatch( $request );
$this->assertArrayHasKey( 'my_custom_int', $response->data );
global $wp_rest_additional_fields;
$wp_rest_additional_fields = array();
}
public function additional_field_get_callback( $object ) {
return 123;
}
protected function check_post_status_obj( $status_obj, $data, $links ) {
$this->assertEquals( $status_obj->label, $data['name'] );
$this->assertEquals( $status_obj->private, $data['private'] );
$this->assertEquals( $status_obj->protected, $data['protected'] );
$this->assertEquals( $status_obj->public, $data['public'] );
$this->assertEquals( $status_obj->publicly_queryable, $data['queryable'] );
$this->assertEquals( $status_obj->show_in_admin_all_list, $data['show_in_list'] );
$this->assertEquals( $status_obj->name, $data['slug'] );
$this->assertEqualSets( array(
'archives',
), array_keys( $links ) );
}
protected function check_post_status_object_response( $response ) {
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$obj = get_post_status_object( 'publish' );
$this->check_post_status_obj( $obj, $data, $response->get_links() );
}
}
@@ -0,0 +1,182 @@
<?php
/**
* Unit tests covering WP_REST_Posts_Types_Controller functionality.
*
* @package WordPress
* @subpackage REST API
*/
/**
* @group restapi
*/
class WP_Test_REST_Post_Types_Controller extends WP_Test_REST_Controller_Testcase {
public function test_register_routes() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( '/wp/v2/types', $routes );
$this->assertArrayHasKey( '/wp/v2/types/(?P<type>[\w-]+)', $routes );
}
public function test_context_param() {
// Collection
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/types' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'view', 'edit', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] );
// Single
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/types/post' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'view', 'edit', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] );
}
public function test_get_items() {
$request = new WP_REST_Request( 'GET', '/wp/v2/types' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$post_types = get_post_types( array( 'show_in_rest' => true ), 'objects' );
$this->assertEquals( count( $post_types ), count( $data ) );
$this->assertEquals( $post_types['post']->name, $data['post']['slug'] );
$this->check_post_type_obj( 'view', $post_types['post'], $data['post'], $data['post']['_links'] );
$this->assertEquals( $post_types['page']->name, $data['page']['slug'] );
$this->check_post_type_obj( 'view', $post_types['page'], $data['page'], $data['page']['_links'] );
$this->assertFalse( isset( $data['revision'] ) );
}
public function test_get_items_invalid_permission_for_context() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/types' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_view', $response, 401 );
}
public function test_get_item() {
$request = new WP_REST_Request( 'GET', '/wp/v2/types/post' );
$response = $this->server->dispatch( $request );
$this->check_post_type_object_response( 'view', $response );
}
public function test_get_item_invalid_type() {
$request = new WP_REST_Request( 'GET', '/wp/v2/types/invalid' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_type_invalid', $response, 404 );
}
public function test_get_item_edit_context() {
$editor_id = $this->factory->user->create( array( 'role' => 'editor' ) );
wp_set_current_user( $editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/types/post' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->check_post_type_object_response( 'edit', $response );
}
public function test_get_item_invalid_permission_for_context() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/types/post' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_forbidden_context', $response, 401 );
}
public function test_create_item() {
/** Post types can't be created **/
}
public function test_update_item() {
/** Post types can't be updated **/
}
public function test_delete_item() {
/** Post types can't be deleted **/
}
public function test_prepare_item() {
$obj = get_post_type_object( 'post' );
$endpoint = new WP_REST_Post_Types_Controller;
$request = new WP_REST_Request;
$request->set_param( 'context', 'edit' );
$response = $endpoint->prepare_item_for_response( $obj, $request );
$this->check_post_type_obj( 'edit', $obj, $response->get_data(), $response->get_links() );
}
public function test_get_item_schema() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/types' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertEquals( 6, count( $properties ) );
$this->assertArrayHasKey( 'capabilities', $properties );
$this->assertArrayHasKey( 'description', $properties );
$this->assertArrayHasKey( 'hierarchical', $properties );
$this->assertArrayHasKey( 'labels', $properties );
$this->assertArrayHasKey( 'name', $properties );
$this->assertArrayHasKey( 'slug', $properties );
}
public function test_get_additional_field_registration() {
$schema = array(
'type' => 'integer',
'description' => 'Some integer of mine',
'enum' => array( 1, 2, 3, 4 ),
'context' => array( 'view', 'edit' ),
);
register_rest_field( 'type', 'my_custom_int', array(
'schema' => $schema,
'get_callback' => array( $this, 'additional_field_get_callback' ),
'update_callback' => array( $this, 'additional_field_update_callback' ),
) );
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/types/schema' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertArrayHasKey( 'my_custom_int', $data['schema']['properties'] );
$this->assertEquals( $schema, $data['schema']['properties']['my_custom_int'] );
$request = new WP_REST_Request( 'GET', '/wp/v2/types/post' );
$response = $this->server->dispatch( $request );
$this->assertArrayHasKey( 'my_custom_int', $response->data );
global $wp_rest_additional_fields;
$wp_rest_additional_fields = array();
}
public function additional_field_get_callback( $object ) {
return 123;
}
protected function check_post_type_obj( $context, $post_type_obj, $data, $links ) {
$this->assertEquals( $post_type_obj->label, $data['name'] );
$this->assertEquals( $post_type_obj->name, $data['slug'] );
$this->assertEquals( $post_type_obj->description, $data['description'] );
$this->assertEquals( $post_type_obj->hierarchical, $data['hierarchical'] );
$links = test_rest_expand_compact_links( $links );
$this->assertEquals( rest_url( 'wp/v2/types' ), $links['collection'][0]['href'] );
$this->assertArrayHasKey( 'https://api.w.org/items', $links );
if ( 'edit' === $context ) {
$this->assertEquals( $post_type_obj->cap, $data['capabilities'] );
$this->assertEquals( $post_type_obj->labels, $data['labels'] );
} else {
$this->assertFalse( isset( $data['capabilities'] ) );
$this->assertFalse( isset( $data['labels'] ) );
}
}
protected function check_post_type_object_response( $context, $response ) {
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$obj = get_post_type_object( 'post' );
$this->check_post_type_obj( $context, $obj, $data, $response->get_links() );
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,167 @@
<?php
class WP_Test_REST_Request_Validation extends WP_Test_REST_TestCase {
public function test_validate_within_min_max_range_inclusive() {
$request = new WP_REST_Request( 'GET', '/wp/v2/foo', array(
'args' => array(
'minmaxrange' => array(
'type' => 'integer',
'minimum' => 2,
'maximum' => 10,
),
),
) );
$ret = rest_validate_request_arg( 1, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (inclusive) and 10 (inclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 2, $request, 'minmaxrange' );
$this->assertTrue( $ret );
$ret = rest_validate_request_arg( 10, $request, 'minmaxrange' );
$this->assertTrue( $ret );
$ret = rest_validate_request_arg( 11, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (inclusive) and 10 (inclusive)', $ret->get_error_message() );
}
public function test_validate_within_min_max_range_min_exclusive() {
$request = new WP_REST_Request( 'GET', '/wp/v2/foo', array(
'args' => array(
'minmaxrange' => array(
'type' => 'integer',
'minimum' => 2,
'maximum' => 10,
'exclusiveMinimum' => true,
),
),
) );
$ret = rest_validate_request_arg( 1, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (exclusive) and 10 (inclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 2, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (exclusive) and 10 (inclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 3, $request, 'minmaxrange' );
$this->assertTrue( $ret );
$ret = rest_validate_request_arg( 9, $request, 'minmaxrange' );
$this->assertTrue( $ret );
$ret = rest_validate_request_arg( 10, $request, 'minmaxrange' );
$this->assertTrue( $ret );
$ret = rest_validate_request_arg( 11, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (exclusive) and 10 (inclusive)', $ret->get_error_message() );
}
public function test_validate_within_min_max_range_max_exclusive() {
$request = new WP_REST_Request( 'GET', '/wp/v2/foo', array(
'args' => array(
'minmaxrange' => array(
'type' => 'integer',
'minimum' => 2,
'maximum' => 10,
'exclusiveMaximum' => true,
),
),
) );
$ret = rest_validate_request_arg( 1, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (inclusive) and 10 (exclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 2, $request, 'minmaxrange' );
$this->assertTrue( $ret );
$ret = rest_validate_request_arg( 3, $request, 'minmaxrange' );
$this->assertTrue( $ret );
$ret = rest_validate_request_arg( 9, $request, 'minmaxrange' );
$this->assertTrue( $ret );
$ret = rest_validate_request_arg( 10, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (inclusive) and 10 (exclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 11, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (inclusive) and 10 (exclusive)', $ret->get_error_message() );
}
public function test_validate_within_min_max_range_both_exclusive() {
$request = new WP_REST_Request( 'GET', '/wp/v2/foo', array(
'args' => array(
'minmaxrange' => array(
'type' => 'integer',
'minimum' => 2,
'maximum' => 10,
'exclusiveMinimum' => true,
'exclusiveMaximum' => true,
),
),
) );
$ret = rest_validate_request_arg( 1, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (exclusive) and 10 (exclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 2, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (exclusive) and 10 (exclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 3, $request, 'minmaxrange' );
$this->assertTrue( $ret );
$ret = rest_validate_request_arg( 9, $request, 'minmaxrange' );
$this->assertTrue( $ret );
$ret = rest_validate_request_arg( 10, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (exclusive) and 10 (exclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 11, $request, 'minmaxrange' );
$this->assertEquals( 'minmaxrange must be between 2 (exclusive) and 10 (exclusive)', $ret->get_error_message() );
}
public function test_validate_greater_than_min_inclusive() {
$request = new WP_REST_Request( 'GET', '/wp/v2/foo', array(
'args' => array(
'greaterthanmin' => array(
'type' => 'integer',
'minimum' => 2,
),
),
) );
$ret = rest_validate_request_arg( 1, $request, 'greaterthanmin' );
$this->assertEquals( 'greaterthanmin must be greater than 2 (inclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 2, $request, 'greaterthanmin' );
$this->assertTrue( $ret );
}
public function test_validate_greater_than_min_exclusive() {
$request = new WP_REST_Request( 'GET', '/wp/v2/foo', array(
'args' => array(
'greaterthanmin' => array(
'type' => 'integer',
'minimum' => 2,
'exclusiveMinimum' => true,
),
),
) );
$ret = rest_validate_request_arg( 1, $request, 'greaterthanmin' );
$this->assertEquals( 'greaterthanmin must be greater than 2 (exclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 2, $request, 'greaterthanmin' );
$this->assertEquals( 'greaterthanmin must be greater than 2 (exclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 3, $request, 'greaterthanmin' );
$this->assertTrue( $ret );
}
public function test_validate_less_than_max_inclusive() {
$request = new WP_REST_Request( 'GET', '/wp/v2/foo', array(
'args' => array(
'lessthanmax' => array(
'type' => 'integer',
'maximum' => 10,
),
),
) );
$ret = rest_validate_request_arg( 11, $request, 'lessthanmax' );
$this->assertEquals( 'lessthanmax must be less than 10 (inclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 10, $request, 'lessthanmax' );
$this->assertTrue( $ret );
}
public function test_validate_less_than_max_exclusive() {
$request = new WP_REST_Request( 'GET', '/wp/v2/foo', array(
'args' => array(
'lessthanmax' => array(
'type' => 'integer',
'maximum' => 10,
'exclusiveMaximum' => true,
),
),
) );
$ret = rest_validate_request_arg( 11, $request, 'lessthanmax' );
$this->assertEquals( 'lessthanmax must be less than 10 (exclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 10, $request, 'lessthanmax' );
$this->assertEquals( 'lessthanmax must be less than 10 (exclusive)', $ret->get_error_message() );
$ret = rest_validate_request_arg( 9, $request, 'lessthanmax' );
$this->assertTrue( $ret );
}
}
@@ -0,0 +1,301 @@
<?php
/**
* Unit tests covering WP_REST_Revisions_Controller functionality.
*
* @package WordPress
* @subpackage REST API
*/
/**
* @group restapi
*/
class WP_Test_REST_Revisions_Controller extends WP_Test_REST_Controller_Testcase {
public function setUp() {
parent::setUp();
$this->post_id = $this->factory->post->create();
$this->page_id = $this->factory->post->create( array( 'post_type' => 'page' ) );
$this->editor_id = $this->factory->user->create( array(
'role' => 'editor',
) );
$this->contributor_id = $this->factory->user->create( array(
'role' => 'contributor',
) );
wp_update_post( array( 'post_content' => 'This content is better.', 'ID' => $this->post_id ) );
wp_update_post( array( 'post_content' => 'This content is marvelous.', 'ID' => $this->post_id ) );
$revisions = wp_get_post_revisions( $this->post_id );
$this->revision_1 = array_pop( $revisions );
$this->revision_id1 = $this->revision_1->ID;
$this->revision_2 = array_pop( $revisions );
$this->revision_id2 = $this->revision_2->ID;
}
public function test_register_routes() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( '/wp/v2/posts/(?P<parent>[\d]+)/revisions', $routes );
$this->assertArrayHasKey( '/wp/v2/posts/(?P<parent>[\d]+)/revisions/(?P<id>[\d]+)', $routes );
$this->assertArrayHasKey( '/wp/v2/pages/(?P<parent>[\d]+)/revisions', $routes );
$this->assertArrayHasKey( '/wp/v2/pages/(?P<parent>[\d]+)/revisions/(?P<id>[\d]+)', $routes );
}
public function test_context_param() {
// Collection
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . $this->post_id . '/revisions' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'view', 'edit', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] );
// Single
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . $this->post_id . '/revisions/' . $this->revision_1->ID );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'view', 'edit', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] );
}
public function test_get_items() {
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $this->post_id . '/revisions' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertCount( 2, $data );
// Reverse chron
$this->assertEquals( $this->revision_id2, $data[0]['id'] );
$this->check_get_revision_response( $data[0], $this->revision_2 );
$this->assertEquals( $this->revision_id1, $data[1]['id'] );
$this->check_get_revision_response( $data[1], $this->revision_1 );
}
public function test_get_items_no_permission() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $this->post_id . '/revisions' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_read', $response, 401 );
wp_set_current_user( $this->contributor_id );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_read', $response, 403 );
}
public function test_get_items_missing_parent() {
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/revisions' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
}
public function test_get_items_invalid_parent_post_type() {
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $this->page_id . '/revisions' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
}
public function test_get_item() {
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $this->post_id . '/revisions/' . $this->revision_id1 );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$this->check_get_revision_response( $response, $this->revision_1 );
$fields = array(
'author',
'date',
'date_gmt',
'modified',
'modified_gmt',
'guid',
'id',
'parent',
'slug',
'title',
'excerpt',
'content',
);
$data = $response->get_data();
$this->assertEqualSets( $fields, array_keys( $data ) );
}
public function test_get_item_embed_context() {
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $this->post_id . '/revisions/' . $this->revision_id1 );
$request->set_param( 'context', 'embed' );
$response = $this->server->dispatch( $request );
$fields = array(
'author',
'date',
'id',
'parent',
'slug',
'title',
'excerpt',
);
$data = $response->get_data();
$this->assertEqualSets( $fields, array_keys( $data ) );
}
public function test_get_item_no_permission() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $this->post_id . '/revisions/' . $this->revision_id1 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_read', $response, 401 );
wp_set_current_user( $this->contributor_id );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_read', $response, 403 );
}
public function test_get_item_missing_parent() {
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/revisions/' . $this->revision_id1 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
}
public function test_get_item_invalid_parent_post_type() {
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $this->page_id . '/revisions/' . $this->revision_id1 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
}
public function test_delete_item() {
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/posts/' . $this->post_id . '/revisions/' . $this->revision_id1 );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$this->assertNull( get_post( $this->revision_id1 ) );
}
public function test_delete_item_no_permission() {
wp_set_current_user( $this->contributor_id );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/posts/' . $this->post_id . '/revisions/' . $this->revision_id1 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_read', $response, 403 );
}
public function test_prepare_item() {
wp_set_current_user( $this->editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $this->post_id . '/revisions/' . $this->revision_id1 );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$this->check_get_revision_response( $response, $this->revision_1 );
}
public function test_get_item_schema() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . $this->post_id . '/revisions' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertEquals( 12, count( $properties ) );
$this->assertArrayHasKey( 'author', $properties );
$this->assertArrayHasKey( 'content', $properties );
$this->assertArrayHasKey( 'date', $properties );
$this->assertArrayHasKey( 'date_gmt', $properties );
$this->assertArrayHasKey( 'excerpt', $properties );
$this->assertArrayHasKey( 'guid', $properties );
$this->assertArrayHasKey( 'id', $properties );
$this->assertArrayHasKey( 'modified', $properties );
$this->assertArrayHasKey( 'modified_gmt', $properties );
$this->assertArrayHasKey( 'parent', $properties );
$this->assertArrayHasKey( 'slug', $properties );
$this->assertArrayHasKey( 'title', $properties );
}
public function test_create_item() {
$request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . $this->post_id . '/revisions' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_no_route', $response, 404 );
}
public function test_update_item() {
$request = new WP_REST_Request( 'POST', '/wp/v2/posts/' . $this->post_id . '/revisions/' . $this->revision_id1 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_no_route', $response, 404 );
}
public function test_get_additional_field_registration() {
$schema = array(
'type' => 'integer',
'description' => 'Some integer of mine',
'enum' => array( 1, 2, 3, 4 ),
'context' => array( 'view', 'edit' ),
);
register_rest_field( 'post-revision', 'my_custom_int', array(
'schema' => $schema,
'get_callback' => array( $this, 'additional_field_get_callback' ),
'update_callback' => array( $this, 'additional_field_update_callback' ),
) );
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/posts/' . $this->post_id . '/revisions' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertArrayHasKey( 'my_custom_int', $data['schema']['properties'] );
$this->assertEquals( $schema, $data['schema']['properties']['my_custom_int'] );
wp_set_current_user( 1 );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . $this->post_id . '/revisions/' . $this->revision_id1 );
$response = $this->server->dispatch( $request );
$this->assertArrayHasKey( 'my_custom_int', $response->data );
global $wp_rest_additional_fields;
$wp_rest_additional_fields = array();
}
public function additional_field_get_callback( $object ) {
return get_post_meta( $object['id'], 'my_custom_int', true );
}
public function additional_field_update_callback( $value, $post ) {
update_post_meta( $post->ID, 'my_custom_int', $value );
}
protected function check_get_revision_response( $response, $revision ) {
if ( $response instanceof WP_REST_Response ) {
$links = $response->get_links();
$response = $response->get_data();
} else {
$this->assertArrayHasKey( '_links', $response );
$links = $response['_links'];
}
$this->assertEquals( $revision->post_author, $response['author'] );
$rendered_content = apply_filters( 'the_content', $revision->post_content );
$this->assertEquals( $rendered_content, $response['content']['rendered'] );
$this->assertEquals( mysql_to_rfc3339( $revision->post_date ), $response['date'] );
$this->assertEquals( mysql_to_rfc3339( $revision->post_date_gmt ), $response['date_gmt'] );
$rendered_excerpt = apply_filters( 'the_excerpt', apply_filters( 'get_the_excerpt', $revision->post_excerpt, $revision ) );
$this->assertEquals( $rendered_excerpt, $response['excerpt']['rendered'] );
$rendered_guid = apply_filters( 'get_the_guid', $revision->guid );
$this->assertEquals( $rendered_guid, $response['guid']['rendered'] );
$this->assertEquals( $revision->ID, $response['id'] );
$this->assertEquals( mysql_to_rfc3339( $revision->post_modified ), $response['modified'] );
$this->assertEquals( mysql_to_rfc3339( $revision->post_modified_gmt ), $response['modified_gmt'] );
$this->assertEquals( $revision->post_name, $response['slug'] );
$rendered_title = get_the_title( $revision->ID );
$this->assertEquals( $rendered_title, $response['title']['rendered'] );
$parent = get_post( $revision->post_parent );
$parent_controller = new WP_REST_Posts_Controller( $parent->post_type );
$parent_object = get_post_type_object( $parent->post_type );
$parent_base = ! empty( $parent_object->rest_base ) ? $parent_object->rest_base : $parent_object->name;
$this->assertEquals( rest_url( '/wp/v2/' . $parent_base . '/' . $revision->post_parent ), $links['parent'][0]['href'] );
}
}
@@ -0,0 +1,239 @@
<?php
/**
* Unit tests covering WP_Test_REST_Settings_Controller functionality.
*
* @package WordPress
* @subpackage REST API
*/
/**
* @group restapi
*/
class WP_Test_REST_Settings_Controller extends WP_Test_REST_Controller_Testcase {
public function setUp() {
parent::setUp();
$this->administrator = $this->factory->user->create( array(
'role' => 'administrator',
) );
$this->endpoint = new WP_REST_Settings_Controller();
}
public function test_register_routes() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( '/wp/v2/settings', $routes );
}
public function test_get_items() {
}
public function test_context_param() {
}
public function test_get_item_is_not_public() {
$request = new WP_REST_Request( 'GET', '/wp/v2/settings' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 403, $response->get_status() );
}
public function test_get_item() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'GET', '/wp/v2/settings' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( array(
'title',
'description',
'url',
'email',
'timezone',
'date_format',
'time_format',
'start_of_week',
'language',
'use_smilies',
'default_category',
'default_post_format',
'posts_per_page',
), array_keys( $data ) );
}
public function test_get_item_value_is_cast_to_type() {
wp_set_current_user( $this->administrator );
update_option( 'posts_per_page', 'invalid_number' ); // this is cast to (int) 1
$request = new WP_REST_Request( 'GET', '/wp/v2/settings' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 1, $data['posts_per_page'] );
}
public function test_get_item_with_custom_setting() {
wp_set_current_user( $this->administrator );
register_setting( 'somegroup', 'mycustomsetting', array(
'show_in_rest' => array(
'name' => 'mycustomsettinginrest',
'schema' => array(
'enum' => array( 'validvalue1', 'validvalue2' ),
'default' => 'validvalue1',
),
),
'type' => 'string',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/settings' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertArrayHasKey( 'mycustomsettinginrest', $data );
$this->assertEquals( 'validvalue1', $data['mycustomsettinginrest'] );
update_option( 'mycustomsetting', 'validvalue2' );
$request = new WP_REST_Request( 'GET', '/wp/v2/settings' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'validvalue2', $data['mycustomsettinginrest'] );
unregister_setting( 'somegroup', 'mycustomsetting' );
}
public function get_setting_custom_callback( $result, $name, $args ) {
switch ( $name ) {
case 'mycustomsetting1':
return 'filtered1';
}
return $result;
}
public function test_get_item_with_filter() {
wp_set_current_user( $this->administrator );
add_filter( 'rest_pre_get_setting', array( $this, 'get_setting_custom_callback' ), 10, 3 );
register_setting( 'somegroup', 'mycustomsetting1', array(
'show_in_rest' => array(
'name' => 'mycustomsettinginrest1',
),
'type' => 'string',
) );
register_setting( 'somegroup', 'mycustomsetting2', array(
'show_in_rest' => array(
'name' => 'mycustomsettinginrest2',
),
'type' => 'string',
) );
update_option( 'mycustomsetting1', 'unfiltered1' );
update_option( 'mycustomsetting2', 'unfiltered2' );
$request = new WP_REST_Request( 'GET', '/wp/v2/settings' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertArrayHasKey( 'mycustomsettinginrest1', $data );
$this->assertEquals( 'unfiltered1', $data['mycustomsettinginrest1'] );
$this->assertArrayHasKey( 'mycustomsettinginrest2', $data );
$this->assertEquals( 'unfiltered2', $data['mycustomsettinginrest2'] );
unregister_setting( 'somegroup', 'mycustomsetting' );
remove_all_filters( 'rest_pre_get_setting' );
}
public function test_create_item() {
}
public function test_update_item() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'PUT', '/wp/v2/settings' );
$request->set_param( 'title', 'The new title!' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 'The new title!', $data['title'] );
$this->assertEquals( get_option( 'blogname' ), $data['title'] );
}
public function update_setting_custom_callback( $result, $name, $value, $args ) {
if ( 'title' === $name && 'The new title!' === $value ) {
// Do not allow changing the title in this case
return true;
}
return false;
}
public function test_update_item_with_filter() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'PUT', '/wp/v2/settings' );
$request->set_param( 'title', 'The old title!' );
$request->set_param( 'description', 'The old description!' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 'The old title!', $data['title'] );
$this->assertEquals( 'The old description!', $data['description'] );
$this->assertEquals( get_option( 'blogname' ), $data['title'] );
$this->assertEquals( get_option( 'blogdescription' ), $data['description'] );
add_filter( 'rest_pre_update_setting', array( $this, 'update_setting_custom_callback' ), 10, 4 );
$request = new WP_REST_Request( 'PUT', '/wp/v2/settings' );
$request->set_param( 'title', 'The new title!' );
$request->set_param( 'description', 'The new description!' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 'The old title!', $data['title'] );
$this->assertEquals( 'The new description!', $data['description'] );
$this->assertEquals( get_option( 'blogname' ), $data['title'] );
$this->assertEquals( get_option( 'blogdescription' ), $data['description'] );
remove_all_filters( 'rest_pre_update_setting' );
}
public function test_update_item_with_invalid_type() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'PUT', '/wp/v2/settings' );
$request->set_param( 'title', array( 'rendered' => 'This should fail.' ) );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
}
/**
* Setting an item to "null" will essentially restore it to it's default value.
*/
public function test_update_item_with_null() {
update_option( 'posts_per_page', 9 );
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'PUT', '/wp/v2/settings' );
$request->set_param( 'posts_per_page', null );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 10, $data['posts_per_page'] );
}
public function test_delete_item() {
}
public function test_prepare_item() {
}
public function test_get_item_schema() {
}
}
@@ -0,0 +1,738 @@
<?php
/**
* Unit tests covering WP_REST_Terms_Controller functionality, used for Tags.
*
* @package WordPress
* @subpackage REST API
*/
/**
* @group restapi
*/
class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase {
public function setUp() {
parent::setUp();
$this->administrator = $this->factory->user->create( array(
'role' => 'administrator',
) );
$this->subscriber = $this->factory->user->create( array(
'role' => 'subscriber',
) );
}
public function test_register_routes() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( '/wp/v2/tags', $routes );
$this->assertArrayHasKey( '/wp/v2/tags/(?P<id>[\d]+)', $routes );
}
public function test_context_param() {
// Collection
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/tags' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'view', 'embed', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
// Single
$tag1 = $this->factory->tag->create( array( 'name' => 'Season 5' ) );
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/tags/' . $tag1 );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'view', 'embed', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
}
public function test_registered_query_params() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/tags' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$keys = array_keys( $data['endpoints'][0]['args'] );
sort( $keys );
$this->assertEquals( array(
'context',
'exclude',
'hide_empty',
'include',
'offset',
'order',
'orderby',
'page',
'per_page',
'post',
'search',
'slug',
), $keys );
}
public function test_get_items() {
$this->factory->tag->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$response = $this->server->dispatch( $request );
$this->check_get_taxonomy_terms_response( $response );
}
public function test_get_items_invalid_permission_for_context() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_forbidden_context', $response, 401 );
}
public function test_get_items_hide_empty_arg() {
$post_id = $this->factory->post->create();
$tag1 = $this->factory->tag->create( array( 'name' => 'Season 5' ) );
$tag2 = $this->factory->tag->create( array( 'name' => 'The Be Sharps' ) );
wp_set_object_terms( $post_id, array( $tag1, $tag2 ), 'post_tag' );
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'hide_empty', true );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( 'Season 5', $data[0]['name'] );
$this->assertEquals( 'The Be Sharps', $data[1]['name'] );
}
public function test_get_items_include_query() {
$id1 = $this->factory->tag->create();
$id2 = $this->factory->tag->create();
$id3 = $this->factory->tag->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
// Orderby=>asc
$request->set_param( 'include', array( $id3, $id1 ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( $id1, $data[0]['id'] );
// Orderby=>include
$request->set_param( 'orderby', 'include' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( $id3, $data[0]['id'] );
}
public function test_get_items_exclude_query() {
$id1 = $this->factory->tag->create();
$id2 = $this->factory->tag->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertTrue( in_array( $id1, wp_list_pluck( $data, 'id' ), true ) );
$this->assertTrue( in_array( $id2, wp_list_pluck( $data, 'id' ), true ) );
$request->set_param( 'exclude', array( $id2 ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertTrue( in_array( $id1, wp_list_pluck( $data, 'id' ), true ) );
$this->assertFalse( in_array( $id2, wp_list_pluck( $data, 'id' ), true ) );
}
public function test_get_items_offset_query() {
$id1 = $this->factory->tag->create();
$id2 = $this->factory->tag->create();
$id3 = $this->factory->tag->create();
$id4 = $this->factory->tag->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'offset', 1 );
$response = $this->server->dispatch( $request );
$this->assertCount( 3, $response->get_data() );
// 'offset' works with 'per_page'
$request->set_param( 'per_page', 2 );
$response = $this->server->dispatch( $request );
$this->assertCount( 2, $response->get_data() );
// 'offset' takes priority over 'page'
$request->set_param( 'page', 3 );
$response = $this->server->dispatch( $request );
$this->assertCount( 2, $response->get_data() );
}
public function test_get_items_orderby_args() {
$tag1 = $this->factory->tag->create( array( 'name' => 'Apple' ) );
$tag2 = $this->factory->tag->create( array( 'name' => 'Banana' ) );
/*
* Tests:
* - orderby
* - order
* - per_page
*/
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'orderby', 'name' );
$request->set_param( 'order', 'desc' );
$request->set_param( 'per_page', 1 );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( 'Banana', $data[0]['name'] );
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'orderby', 'name' );
$request->set_param( 'order', 'asc' );
$request->set_param( 'per_page', 2 );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( 'Apple', $data[0]['name'] );
}
public function test_get_items_orderby_id() {
$tag0 = $this->factory->tag->create( array( 'name' => 'Cantaloupe' ) );
$tag1 = $this->factory->tag->create( array( 'name' => 'Apple' ) );
$tag2 = $this->factory->tag->create( array( 'name' => 'Banana' ) );
// defaults to orderby=name, order=asc
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 'Apple', $data[0]['name'] );
$this->assertEquals( 'Banana', $data[1]['name'] );
$this->assertEquals( 'Cantaloupe', $data[2]['name'] );
// orderby=id, with default order=asc
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'orderby', 'id' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 'Cantaloupe', $data[0]['name'] );
$this->assertEquals( 'Apple', $data[1]['name'] );
$this->assertEquals( 'Banana', $data[2]['name'] );
// orderby=id, order=desc
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'orderby', 'id' );
$request->set_param( 'order', 'desc' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 'Banana', $data[0]['name'] );
$this->assertEquals( 'Apple', $data[1]['name'] );
$this->assertEquals( 'Cantaloupe', $data[2]['name'] );
}
public function test_get_items_post_args() {
$post_id = $this->factory->post->create();
$tag1 = $this->factory->tag->create( array( 'name' => 'DC' ) );
$tag2 = $this->factory->tag->create( array( 'name' => 'Marvel' ) );
$this->factory->tag->create( array( 'name' => 'Dark Horse' ) );
wp_set_object_terms( $post_id, array( $tag1, $tag2 ), 'post_tag' );
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'post', $post_id );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( 'DC', $data[0]['name'] );
}
public function test_get_terms_post_args_paging() {
$post_id = $this->factory->post->create();
$tag_ids = array();
for ( $i = 0; $i < 30; $i++ ) {
$tag_ids[] = $this->factory->tag->create( array(
'name' => "Tag {$i}",
) );
}
wp_set_object_terms( $post_id, $tag_ids, 'post_tag' );
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'post', $post_id );
$request->set_param( 'page', 1 );
$request->set_param( 'per_page', 15 );
$request->set_param( 'orderby', 'id' );
$response = $this->server->dispatch( $request );
$tags = $response->get_data();
$i = 0;
foreach ( $tags as $tag ) {
$this->assertEquals( $tag['name'], "Tag {$i}" );
$i++;
}
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'post', $post_id );
$request->set_param( 'page', 2 );
$request->set_param( 'per_page', 15 );
$request->set_param( 'orderby', 'id' );
$response = $this->server->dispatch( $request );
$tags = $response->get_data();
foreach ( $tags as $tag ) {
$this->assertEquals( $tag['name'], "Tag {$i}" );
$i++;
}
}
public function test_get_items_post_empty() {
$post_id = $this->factory->post->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'post', $post_id );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertCount( 0, $data );
}
public function test_get_items_custom_tax_post_args() {
register_taxonomy( 'batman', 'post', array( 'show_in_rest' => true ) );
$controller = new WP_REST_Terms_Controller( 'batman' );
$controller->register_routes();
$term1 = $this->factory->term->create( array( 'name' => 'Cape', 'taxonomy' => 'batman' ) );
$term2 = $this->factory->term->create( array( 'name' => 'Mask', 'taxonomy' => 'batman' ) );
$this->factory->term->create( array( 'name' => 'Car', 'taxonomy' => 'batman' ) );
$post_id = $this->factory->post->create();
wp_set_object_terms( $post_id, array( $term1, $term2 ), 'batman' );
$request = new WP_REST_Request( 'GET', '/wp/v2/batman' );
$request->set_param( 'post', $post_id );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 2, count( $data ) );
$this->assertEquals( 'Cape', $data[0]['name'] );
}
public function test_get_items_search_args() {
$tag1 = $this->factory->tag->create( array( 'name' => 'Apple' ) );
$tag2 = $this->factory->tag->create( array( 'name' => 'Banana' ) );
/*
* Tests:
* - search
*/
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'search', 'App' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( 'Apple', $data[0]['name'] );
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'search', 'Garbage' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 0, count( $data ) );
}
public function test_get_items_slug_arg() {
$tag1 = $this->factory->tag->create( array( 'name' => 'Apple' ) );
$tag2 = $this->factory->tag->create( array( 'name' => 'Banana' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'slug', 'apple' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 1, count( $data ) );
$this->assertEquals( 'Apple', $data[0]['name'] );
}
public function test_get_terms_private_taxonomy() {
register_taxonomy( 'robin', 'post', array( 'public' => false ) );
$term1 = $this->factory->term->create( array( 'name' => 'Cape', 'taxonomy' => 'robin' ) );
$term2 = $this->factory->term->create( array( 'name' => 'Mask', 'taxonomy' => 'robin' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/terms/robin' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_no_route', $response, 404 );
}
public function test_get_terms_pagination_headers() {
// Start of the index
for ( $i = 0; $i < 50; $i++ ) {
$this->factory->tag->create( array(
'name' => "Tag {$i}",
) );
}
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$response = $this->server->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 50, $headers['X-WP-Total'] );
$this->assertEquals( 5, $headers['X-WP-TotalPages'] );
$next_link = add_query_arg( array(
'page' => 2,
), rest_url( 'wp/v2/tags' ) );
$this->assertFalse( stripos( $headers['Link'], 'rel="prev"' ) );
$this->assertContains( '<' . $next_link . '>; rel="next"', $headers['Link'] );
// 3rd page
$this->factory->tag->create( array(
'name' => 'Tag 51',
) );
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'page', 3 );
$response = $this->server->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 51, $headers['X-WP-Total'] );
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
$prev_link = add_query_arg( array(
'page' => 2,
), rest_url( 'wp/v2/tags' ) );
$this->assertContains( '<' . $prev_link . '>; rel="prev"', $headers['Link'] );
$next_link = add_query_arg( array(
'page' => 4,
), rest_url( 'wp/v2/tags' ) );
$this->assertContains( '<' . $next_link . '>; rel="next"', $headers['Link'] );
// Last page
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'page', 6 );
$response = $this->server->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 51, $headers['X-WP-Total'] );
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
$prev_link = add_query_arg( array(
'page' => 5,
), rest_url( 'wp/v2/tags' ) );
$this->assertContains( '<' . $prev_link . '>; rel="prev"', $headers['Link'] );
$this->assertFalse( stripos( $headers['Link'], 'rel="next"' ) );
// Out of bounds
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'page', 8 );
$response = $this->server->dispatch( $request );
$headers = $response->get_headers();
$this->assertEquals( 51, $headers['X-WP-Total'] );
$this->assertEquals( 6, $headers['X-WP-TotalPages'] );
$prev_link = add_query_arg( array(
'page' => 6,
), rest_url( 'wp/v2/tags' ) );
$this->assertContains( '<' . $prev_link . '>; rel="prev"', $headers['Link'] );
$this->assertFalse( stripos( $headers['Link'], 'rel="next"' ) );
}
public function test_get_items_invalid_context() {
$request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
$request->set_param( 'context', 'banana' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
}
public function test_get_item() {
$id = $this->factory->tag->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/tags/' . $id );
$response = $this->server->dispatch( $request );
$this->check_get_taxonomy_term_response( $response, $id );
}
public function test_get_term_invalid_term() {
$request = new WP_REST_Request( 'GET', '/wp/v2/tags/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_term_invalid', $response, 404 );
}
public function test_get_item_invalid_permission_for_context() {
$id = $this->factory->tag->create();
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/tags/' . $id );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_forbidden_context', $response, 401 );
}
public function test_get_term_private_taxonomy() {
register_taxonomy( 'robin', 'post', array( 'public' => false ) );
$term1 = $this->factory->term->create( array( 'name' => 'Cape', 'taxonomy' => 'robin' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/terms/robin/' . $term1 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_no_route', $response, 404 );
}
public function test_get_item_incorrect_taxonomy() {
register_taxonomy( 'robin', 'post' );
$term1 = $this->factory->term->create( array( 'name' => 'Cape', 'taxonomy' => 'robin' ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/tags/' . $term1 );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_term_invalid', $response, 404 );
}
public function test_create_item() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'POST', '/wp/v2/tags' );
$request->set_param( 'name', 'My Awesome Term' );
$request->set_param( 'description', 'This term is so awesome.' );
$request->set_param( 'slug', 'so-awesome' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 201, $response->get_status() );
$headers = $response->get_headers();
$data = $response->get_data();
$this->assertContains( '/wp/v2/tags/' . $data['id'], $headers['Location'] );
$this->assertEquals( 'My Awesome Term', $data['name'] );
$this->assertEquals( 'This term is so awesome.', $data['description'] );
$this->assertEquals( 'so-awesome', $data['slug'] );
}
public function test_create_item_incorrect_permissions() {
wp_set_current_user( $this->subscriber );
$request = new WP_REST_Request( 'POST', '/wp/v2/tags' );
$request->set_param( 'name', 'Incorrect permissions' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_create', $response, 403 );
}
public function test_create_item_missing_arguments() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'POST', '/wp/v2/tags' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_missing_callback_param', $response, 400 );
}
public function test_create_item_parent_non_hierarchical_taxonomy() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'POST', '/wp/v2/tags' );
$request->set_param( 'name', 'My Awesome Term' );
$request->set_param( 'parent', REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_taxonomy_not_hierarchical', $response, 400 );
}
public function test_update_item() {
wp_set_current_user( $this->administrator );
$orig_args = array(
'name' => 'Original Name',
'description' => 'Original Description',
'slug' => 'original-slug',
);
$term = get_term_by( 'id', $this->factory->tag->create( $orig_args ), 'post_tag' );
$request = new WP_REST_Request( 'POST', '/wp/v2/tags/' . $term->term_id );
$request->set_param( 'name', 'New Name' );
$request->set_param( 'description', 'New Description' );
$request->set_param( 'slug', 'new-slug' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 'New Name', $data['name'] );
$this->assertEquals( 'New Description', $data['description'] );
$this->assertEquals( 'new-slug', $data['slug'] );
}
public function test_update_item_invalid_term() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'POST', '/wp/v2/tags/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$request->set_param( 'name', 'Invalid Term' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_term_invalid', $response, 404 );
}
public function test_update_item_incorrect_permissions() {
wp_set_current_user( $this->subscriber );
$term = get_term_by( 'id', $this->factory->tag->create(), 'post_tag' );
$request = new WP_REST_Request( 'POST', '/wp/v2/tags/' . $term->term_id );
$request->set_param( 'name', 'Incorrect permissions' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
}
public function test_update_item_parent_non_hierarchical_taxonomy() {
wp_set_current_user( $this->administrator );
$term = get_term_by( 'id', $this->factory->tag->create(), 'post_tag' );
$request = new WP_REST_Request( 'POST', '/wp/v2/tags/' . $term->term_taxonomy_id );
$request->set_param( 'parent', REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_taxonomy_not_hierarchical', $response, 400 );
}
public function test_delete_item() {
wp_set_current_user( $this->administrator );
$term = get_term_by( 'id', $this->factory->tag->create( array( 'name' => 'Deleted Tag' ) ), 'post_tag' );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/tags/' . $term->term_id );
$request->set_param( 'force', true );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( 'Deleted Tag', $data['name'] );
}
public function test_delete_item_force_false() {
wp_set_current_user( $this->administrator );
$term = get_term_by( 'id', $this->factory->tag->create( array( 'name' => 'Deleted Tag' ) ), 'post_tag' );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/tags/' . $term->term_id );
// force defaults to false
$response = $this->server->dispatch( $request );
$this->assertEquals( 501, $response->get_status() );
}
public function test_delete_item_invalid_term() {
wp_set_current_user( $this->administrator );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/tags/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_term_invalid', $response, 404 );
}
public function test_delete_item_incorrect_permissions() {
wp_set_current_user( $this->subscriber );
$term = get_term_by( 'id', $this->factory->tag->create(), 'post_tag' );
$request = new WP_REST_Request( 'DELETE', '/wp/v2/tags/' . $term->term_id );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_delete', $response, 403 );
}
public function test_prepare_item() {
$term = get_term_by( 'id', $this->factory->tag->create(), 'post_tag' );
$request = new WP_REST_Request( 'GET', '/wp/v2/tags/' . $term->term_id );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->check_taxonomy_term( $term, $data, $response->get_links() );
}
public function test_get_item_schema() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/tags' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertEquals( 8, count( $properties ) );
$this->assertArrayHasKey( 'id', $properties );
$this->assertArrayHasKey( 'count', $properties );
$this->assertArrayHasKey( 'description', $properties );
$this->assertArrayHasKey( 'link', $properties );
$this->assertArrayHasKey( 'meta', $properties );
$this->assertArrayHasKey( 'name', $properties );
$this->assertArrayHasKey( 'slug', $properties );
$this->assertArrayHasKey( 'taxonomy', $properties );
$this->assertEquals( array_keys( get_taxonomies() ), $properties['taxonomy']['enum'] );
}
public function test_get_item_schema_non_hierarchical() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/tags' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertArrayHasKey( 'id', $properties );
$this->assertFalse( isset( $properties['parent'] ) );
}
public function test_get_additional_field_registration() {
$schema = array(
'type' => 'integer',
'description' => 'Some integer of mine',
'enum' => array( 1, 2, 3, 4 ),
'context' => array( 'view', 'edit' ),
);
register_rest_field( 'tag', 'my_custom_int', array(
'schema' => $schema,
'get_callback' => array( $this, 'additional_field_get_callback' ),
) );
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/tags' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertArrayHasKey( 'my_custom_int', $data['schema']['properties'] );
$this->assertEquals( $schema, $data['schema']['properties']['my_custom_int'] );
$tag_id = $this->factory->tag->create();
$request = new WP_REST_Request( 'GET', '/wp/v2/tags/' . $tag_id );
$response = $this->server->dispatch( $request );
$this->assertArrayHasKey( 'my_custom_int', $response->data );
global $wp_rest_additional_fields;
$wp_rest_additional_fields = array();
}
public function test_additional_field_update_errors() {
$schema = array(
'type' => 'integer',
'description' => 'Some integer of mine',
'enum' => array( 1, 2, 3, 4 ),
'context' => array( 'view', 'edit' ),
);
register_rest_field( 'tag', 'my_custom_int', array(
'schema' => $schema,
'get_callback' => array( $this, 'additional_field_get_callback' ),
'update_callback' => array( $this, 'additional_field_update_callback' ),
) );
wp_set_current_user( $this->administrator );
$tag_id = $this->factory->tag->create();
// Check for error on update.
$request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/tags/%d', $tag_id ) );
$request->set_body_params( array(
'my_custom_int' => 'returnError',
) );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
global $wp_rest_additional_fields;
$wp_rest_additional_fields = array();
}
public function additional_field_get_callback( $object, $request ) {
return 123;
}
public function additional_field_update_callback( $value, $tag ) {
if ( 'returnError' === $value ) {
return new WP_Error( 'rest_invalid_param', 'Testing an error.', array( 'status' => 400 ) );
}
}
public function tearDown() {
_unregister_taxonomy( 'batman' );
_unregister_taxonomy( 'robin' );
parent::tearDown();
}
protected function check_get_taxonomy_terms_response( $response ) {
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$args = array(
'hide_empty' => false,
);
$tags = get_terms( 'post_tag', $args );
$this->assertEquals( count( $tags ), count( $data ) );
$this->assertEquals( $tags[0]->term_id, $data[0]['id'] );
$this->assertEquals( $tags[0]->name, $data[0]['name'] );
$this->assertEquals( $tags[0]->slug, $data[0]['slug'] );
$this->assertEquals( $tags[0]->taxonomy, $data[0]['taxonomy'] );
$this->assertEquals( $tags[0]->description, $data[0]['description'] );
$this->assertEquals( $tags[0]->count, $data[0]['count'] );
}
protected function check_taxonomy_term( $term, $data, $links ) {
$this->assertEquals( $term->term_id, $data['id'] );
$this->assertEquals( $term->name, $data['name'] );
$this->assertEquals( $term->slug, $data['slug'] );
$this->assertEquals( $term->description, $data['description'] );
$this->assertEquals( get_term_link( $term ), $data['link'] );
$this->assertEquals( $term->count, $data['count'] );
$taxonomy = get_taxonomy( $term->taxonomy );
if ( $taxonomy->hierarchical ) {
$this->assertEquals( $term->parent, $data['parent'] );
} else {
$this->assertFalse( isset( $data['parent'] ) );
}
$expected_links = array(
'self',
'collection',
'about',
'https://api.w.org/post_type',
);
if ( $taxonomy->hierarchical && $term->parent ) {
$expected_links[] = 'up';
}
$this->assertEqualSets( $expected_links, array_keys( $links ) );
$this->assertContains( 'wp/v2/taxonomies/' . $term->taxonomy, $links['about'][0]['href'] );
$this->assertEquals( add_query_arg( 'tags', $term->term_id, rest_url( 'wp/v2/posts' ) ), $links['https://api.w.org/post_type'][0]['href'] );
}
protected function check_get_taxonomy_term_response( $response, $id ) {
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$tag = get_term( $id, 'post_tag' );
$this->check_taxonomy_term( $tag, $data, $response->get_links() );
}
}
@@ -0,0 +1,198 @@
<?php
/**
* Unit tests covering WP_REST_Taxonomies_Controller functionality.
*
* @package WordPress
* @subpackage REST API
*/
/**
* @group restapi
*/
class WP_Test_REST_Taxonomies_Controller extends WP_Test_REST_Controller_Testcase {
public function test_register_routes() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( '/wp/v2/taxonomies', $routes );
$this->assertArrayHasKey( '/wp/v2/taxonomies/(?P<taxonomy>[\w-]+)', $routes );
}
public function test_context_param() {
// Collection
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/taxonomies' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'view', 'edit', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] );
// Single
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/taxonomies/post_tag' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
$this->assertEqualSets( array( 'view', 'edit', 'embed' ), $data['endpoints'][0]['args']['context']['enum'] );
}
public function test_get_items() {
$request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$taxonomies = $this->get_public_taxonomies( get_taxonomies( '', 'objects' ) );
$this->assertEquals( count( $taxonomies ), count( $data ) );
$this->assertEquals( 'Categories', $data['category']['name'] );
$this->assertEquals( 'category', $data['category']['slug'] );
$this->assertEquals( true, $data['category']['hierarchical'] );
$this->assertEquals( 'Tags', $data['post_tag']['name'] );
$this->assertEquals( 'post_tag', $data['post_tag']['slug'] );
$this->assertEquals( false, $data['post_tag']['hierarchical'] );
}
public function test_get_items_invalid_permission_for_context() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_cannot_view', $response, 401 );
}
public function test_get_taxonomies_for_type() {
$request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies' );
$request->set_param( 'type', 'post' );
$response = $this->server->dispatch( $request );
$this->check_taxonomies_for_type_response( 'post', $response );
}
public function test_get_taxonomies_for_invalid_type() {
$request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies' );
$request->set_param( 'type', 'wingding' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertEquals( '{}', json_encode( $data ) );
}
public function test_get_item() {
$request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies/category' );
$response = $this->server->dispatch( $request );
$this->check_taxonomy_object_response( 'view', $response );
}
public function test_get_item_edit_context() {
$editor_id = $this->factory->user->create( array( 'role' => 'editor' ) );
wp_set_current_user( $editor_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies/category' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->check_taxonomy_object_response( 'edit', $response );
}
public function test_get_item_invalid_permission_for_context() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies/category' );
$request->set_param( 'context', 'edit' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_forbidden_context', $response, 401 );
}
public function test_get_invalid_taxonomy() {
$request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies/invalid' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_taxonomy_invalid', $response, 404 );
}
public function test_get_non_public_taxonomy() {
register_taxonomy( 'api-private', 'post', array( 'public' => false ) );
$request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies/api-private' );
$response = $this->server->dispatch( $request );
$this->assertErrorResponse( 'rest_forbidden', $response, 403 );
}
public function test_create_item() {
/** Taxonomies can't be created **/
}
public function test_update_item() {
/** Taxonomies can't be updated **/
}
public function test_delete_item() {
/** Taxonomies can't be deleted **/
}
public function test_prepare_item() {
$tax = get_taxonomy( 'category' );
$endpoint = new WP_REST_Taxonomies_Controller;
$request = new WP_REST_Request;
$request->set_param( 'context', 'edit' );
$response = $endpoint->prepare_item_for_response( $tax, $request );
$this->check_taxonomy_object( 'edit', $tax, $response->get_data(), $response->get_links() );
}
public function test_get_item_schema() {
$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/taxonomies' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertEquals( 8, count( $properties ) );
$this->assertArrayHasKey( 'capabilities', $properties );
$this->assertArrayHasKey( 'description', $properties );
$this->assertArrayHasKey( 'hierarchical', $properties );
$this->assertArrayHasKey( 'labels', $properties );
$this->assertArrayHasKey( 'name', $properties );
$this->assertArrayHasKey( 'slug', $properties );
$this->assertArrayHasKey( 'show_cloud', $properties );
$this->assertArrayHasKey( 'types', $properties );
}
public function tearDown() {
parent::tearDown();
}
/**
* Utility function for use in get_public_taxonomies
*/
private function is_public( $taxonomy ) {
return ! empty( $taxonomy->show_in_rest );
}
/**
* Utility function to filter down to only public taxonomies
*/
private function get_public_taxonomies( $taxonomies ) {
// Pass through array_values to re-index after filtering
return array_values( array_filter( $taxonomies, array( $this, 'is_public' ) ) );
}
protected function check_taxonomy_object( $context, $tax_obj, $data, $links ) {
$this->assertEquals( $tax_obj->label, $data['name'] );
$this->assertEquals( $tax_obj->name, $data['slug'] );
$this->assertEquals( $tax_obj->description, $data['description'] );
$this->assertEquals( $tax_obj->hierarchical, $data['hierarchical'] );
$this->assertEquals( rest_url( 'wp/v2/taxonomies' ), $links['collection'][0]['href'] );
$this->assertArrayHasKey( 'https://api.w.org/items', $links );
if ( 'edit' === $context ) {
$this->assertEquals( $tax_obj->cap, $data['capabilities'] );
$this->assertEquals( $tax_obj->labels, $data['labels'] );
$this->assertEquals( $tax_obj->show_tagcloud, $data['show_cloud'] );
} else {
$this->assertFalse( isset( $data['capabilities'] ) );
$this->assertFalse( isset( $data['labels'] ) );
$this->assertFalse( isset( $data['show_cloud'] ) );
}
}
protected function check_taxonomy_object_response( $context, $response ) {
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$category = get_taxonomy( 'category' );
$this->check_taxonomy_object( $context, $category, $data, $response->get_links() );
}
protected function check_taxonomies_for_type_response( $type, $response ) {
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$taxonomies = $this->get_public_taxonomies( get_object_taxonomies( $type, 'objects' ) );
$this->assertEquals( count( $taxonomies ), count( $data ) );
}
}
@@ -0,0 +1,78 @@
<?php
/**
* Unit tests covering WP_REST_Controller functionality
*
* @package WordPress
* @subpackage REST API
*/
/**
* @group restapi
*/
class WP_REST_Test_Controller extends WP_REST_Controller {
/**
* Get the Post type's schema, conforming to JSON Schema
*
* @return array
*/
public function get_item_schema() {
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'type',
'type' => 'object',
'properties' => array(
'somestring' => array(
'type' => 'string',
'description' => 'A pretty string.',
'context' => array( 'view' ),
),
'someinteger' => array(
'type' => 'integer',
'context' => array( 'view' ),
),
'someboolean' => array(
'type' => 'boolean',
'context' => array( 'view' ),
),
'someurl' => array(
'type' => 'string',
'format' => 'uri',
'context' => array( 'view' ),
),
'somedate' => array(
'type' => 'string',
'format' => 'date-time',
'context' => array( 'view' ),
),
'someemail' => array(
'type' => 'string',
'format' => 'email',
'context' => array( 'view' ),
),
'someenum' => array(
'type' => 'string',
'enum' => array( 'a', 'b', 'c' ),
'context' => array( 'view' ),
),
'someargoptions' => array(
'type' => 'integer',
'required' => true,
'arg_options' => array(
'required' => false,
'sanitize_callback' => '__return_true',
),
),
'somedefault' => array(
'type' => 'string',
'enum' => array( 'a', 'b', 'c' ),
'context' => array( 'view' ),
'default' => 'a',
),
),
);
return $schema;
}
}
File diff suppressed because it is too large Load Diff