REST API: improve test fixture generation, normalizing data.

Add a data normalization pass when generating data fixtures for the REST API endpoints. Ensures that the `wp-api-generated.js` fixture won't change between test runs. Set more default properties and use fixed values for any properties that can't be easily controlled (object IDs and derivatives like link). Generate the fixture file with JSON_PRETTY_PRINT so that future diffs are easier to follow.

Props jnylen0, netweb.
Fixes #39264.


git-svn-id: https://develop.svn.wordpress.org/trunk@40061 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Adam Silverstein 2017-02-15 17:58:14 +00:00
parent 2e0f576156
commit e3d5e1c6c8
4 changed files with 4430 additions and 54 deletions

View File

@ -678,7 +678,7 @@ module.exports = function(grunt) {
grunt.registerTask( 'restapi-jsclient', [
'phpunit:restapi-jsclient',
'qunit'
'qunit:compiled'
] );
grunt.renameTask( 'watch', '_watch' );

View File

@ -10,13 +10,16 @@
* @group restapi
*/
class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase {
protected static $wp_meta_keys_saved;
protected static $post_id;
public static function wpSetUpBeforeClass( $factory ) {
self::$wp_meta_keys_saved = $GLOBALS['wp_meta_keys'];
self::$post_id = $factory->post->create();
}
public static function wpTearDownAfterClass() {
$GLOBALS['wp_meta_keys'] = self::$wp_meta_keys_saved;
wp_delete_post( self::$post_id, true );
}

View File

@ -74,27 +74,71 @@ class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase {
}
public function test_build_wp_api_client_fixtures() {
// Set up for testing the individual endpoints.
// Set a current admin user.
$administrator = $this->factory->user->create( array(
'role' => 'administrator',
) );
wp_set_current_user( $administrator );
// Set up data for individual endpoint responses. We need to specify
// lots of different fields on these objects, otherwise the generated
// fixture file will be different between runs of PHPUnit tests, which
// is not desirable.
$administrator_id = $this->factory->user->create( array(
'role' => 'administrator',
'display_name' => 'REST API Client Fixture: User',
'user_nicename' => 'restapiclientfixtureuser',
'user_email' => 'administrator@example.org',
) );
wp_set_current_user( $administrator_id );
$post_id = $this->factory->post->create( array(
'post_name' => 'restapi-client-fixture-post',
'post_title' => 'REST API Client Fixture: Post',
'post_content' => 'REST API Client Fixture: Post',
'post_excerpt' => 'REST API Client Fixture: Post',
'post_author' => 0,
) );
wp_update_post( array(
'ID' => $post_id,
'post_content' => 'Updated post content.',
) );
$page_id = $this->factory->post->create( array(
'post_type' => 'page',
'post_name' => 'restapi-client-fixture-page',
'post_title' => 'REST API Client Fixture: Page',
'post_content' => 'REST API Client Fixture: Page',
'post_excerpt' => 'REST API Client Fixture: Page',
'post_date' => '2017-02-14 00:00:00',
'post_date_gmt' => '2017-02-14 00:00:00',
'post_author' => 0,
) );
wp_update_post( array(
'ID' => $page_id,
'post_content' => 'Updated page content.',
) );
$tag_id = $this->factory->tag->create( array(
'name' => 'REST API Client Fixture: Tag',
'slug' => 'restapi-client-fixture-tag',
'description' => 'REST API Client Fixture: Tag',
) );
// Set up data for endpoints.
$post_id = $this->factory->post->create();
$page_id = $this->factory->post->create( array( 'post_type' => 'page' ) );
$tag_id = $this->factory->tag->create( array( 'name' => 'test' ) );
$media_id = $this->factory->attachment->create_object( '/tmp/canola.jpg', 0, array(
'post_mime_type' => 'image/jpeg',
'post_excerpt' => 'A sample caption',
'post_name' => 'restapi-client-fixture-attachment',
'post_title' => 'REST API Client Fixture: Attachment',
'post_date' => '2017-02-14 00:00:00',
'post_date_gmt' => '2017-02-14 00:00:00',
'post_author' => 0,
) );
wp_update_post( array( 'post_content' => 'Updated content.', 'ID' => $post_id ) );
wp_update_post( array( 'post_content' => 'Updated content.', 'ID' => $page_id ) );
$comment_id = $this->factory->comment->create( array(
'comment_approved' => 1,
'comment_post_ID' => $post_id,
'user_id' => 0,
'comment_approved' => 1,
'comment_post_ID' => $post_id,
'user_id' => 0,
'comment_date' => '2017-02-14 00:00:00',
'comment_date_gmt' => '2017-02-14 00:00:00',
'comment_author' => 'Internet of something or other',
'comment_author_email' => 'lights@example.org',
'comment_author_url' => 'http://lights.example.org/',
) );
// Generate route data for subsequent QUnit tests.
@ -196,7 +240,7 @@ class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase {
'name' => 'UsersCollection',
),
array(
'route' => '/wp/v2/users/1',
'route' => '/wp/v2/users/' . $administrator_id,
'name' => 'UserModel',
),
array(
@ -217,12 +261,12 @@ class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase {
),
);
// Set up the mocked response and tell jshint to ignore the single quote json objects
$mocked_responses = "/*jshint -W109 */\n\nvar mockedApiResponse = {};\n\n";
$mocked_responses .= "/**\n";
$mocked_responses = "/**\n";
$mocked_responses .= " * DO NOT EDIT\n";
$mocked_responses .= " * Auto-generated by test_build_wp_api_client_fixtures\n";
$mocked_responses .= " */\n";
$mocked_responses .= "var mockedApiResponse = {};\n";
$mocked_responses .= "/* jshint -W109 */\n";
foreach ( $routes_to_generate_data as $route ) {
$request = new WP_REST_Request( 'GET', $route['route'] );
@ -231,7 +275,10 @@ class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase {
$this->assertTrue( ! empty( $data ), $route['name'] . ' route should return data.' );
$mocked_responses .= 'mockedApiResponse.' . $route['name'] . ' = ' . wp_json_encode( $data ) . ";\n\n";
$fixture = $this->normalize_fixture( $data, $route['name'] );
$mocked_responses .= "\nmockedApiResponse." . $route['name'] . ' = '
. json_encode( $fixture, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES )
. ";\n";
}
// Save the route object for QUnit tests.
@ -245,4 +292,95 @@ class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase {
wp_delete_attachment( $media_id );
wp_delete_comment( $comment_id );
}
/**
* This array contains normalized versions of object IDs and other values
* that can change depending on how PHPUnit is executed. For details on
* how they were generated, see #39264.
*/
private static $fixture_replacements = array(
'PostsCollection.0.id' => 3,
'PostsCollection.0.guid.rendered' => 'http://example.org/?p=3',
'PostsCollection.0.link' => 'http://example.org/?p=3',
'PostsCollection.0._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/posts/3',
'PostsCollection.0._links.replies.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fcomments&post=3',
'PostsCollection.0._links.version-history.0.href' => 'http://example.org/?rest_route=/wp/v2/posts/3/revisions',
'PostsCollection.0._links.wp:attachment.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3',
'PostsCollection.0._links.wp:term.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fcategories&post=3',
'PostsCollection.0._links.wp:term.1.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Ftags&post=3',
'PostModel.id' => 3,
'PostModel.guid.rendered' => 'http://example.org/?p=3',
'PostModel.link' => 'http://example.org/?p=3',
'postRevisions.0.author' => '2',
'postRevisions.0.id' => 4,
'postRevisions.0.parent' => 3,
'postRevisions.0.slug' => '3-revision-v1',
'postRevisions.0.guid.rendered' => 'http://example.org/?p=4',
'postRevisions.0._links.parent.0.href' => 'http://example.org/?rest_route=/wp/v2/posts/3',
'PagesCollection.0.id' => 5,
'PagesCollection.0.guid.rendered' => 'http://example.org/?page_id=5',
'PagesCollection.0.link' => 'http://example.org/?page_id=5',
'PagesCollection.0._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/pages/5',
'PagesCollection.0._links.replies.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fcomments&post=5',
'PagesCollection.0._links.version-history.0.href' => 'http://example.org/?rest_route=/wp/v2/pages/5/revisions',
'PagesCollection.0._links.wp:attachment.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5',
'PageModel.id' => 5,
'PageModel.guid.rendered' => 'http://example.org/?page_id=5',
'PageModel.link' => 'http://example.org/?page_id=5',
'pageRevisions.0.author' => '2',
'pageRevisions.0.id' => 6,
'pageRevisions.0.parent' => 5,
'pageRevisions.0.slug' => '5-revision-v1',
'pageRevisions.0.guid.rendered' => 'http://example.org/?p=6',
'pageRevisions.0._links.parent.0.href' => 'http://example.org/?rest_route=/wp/v2/pages/5',
'MediaCollection.0.id' => 7,
'MediaCollection.0.guid.rendered' => 'http://example.org/?attachment_id=7',
'MediaCollection.0.link' => 'http://example.org/?attachment_id=7',
'MediaCollection.0._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/media/7',
'MediaCollection.0._links.replies.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fcomments&post=7',
'MediaModel.id' => 7,
'MediaModel.guid.rendered' => 'http://example.org/?attachment_id=7',
'MediaModel.link' => 'http://example.org/?attachment_id=7',
'TagsCollection.0.id' => 2,
'TagsCollection.0._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/tags/2',
'TagsCollection.0._links.wp:post_type.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fposts&tags=2',
'TagModel.id' => 2,
'UsersCollection.1.id' => 2,
'UsersCollection.1.link' => 'http://example.org/?author=2',
'UsersCollection.1._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/users/2',
'UserModel.id' => 2,
'UserModel.link' => 'http://example.org/?author=2',
'me.id' => 2,
'me.link' => 'http://example.org/?author=2',
'CommentsCollection.0.id' => 2,
'CommentsCollection.0.post' => 3,
'CommentsCollection.0.link' => 'http://example.org/?p=3#comment-2',
'CommentsCollection.0._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/comments/2',
'CommentsCollection.0._links.up.0.href' => 'http://example.org/?rest_route=/wp/v2/posts/3',
);
private function normalize_fixture( $data, $path ) {
if ( isset( self::$fixture_replacements[ $path ] ) ) {
return self::$fixture_replacements[ $path ];
}
if ( ! is_array( $data ) ) {
return $data;
}
foreach ( $data as $key => $value ) {
if ( is_string( $value ) && (
'date' === $key ||
'date_gmt' === $key ||
'modified' === $key ||
'modified_gmt' === $key
) ) {
$data[ $key ] = '2017-02-14T00:00:00';
} else {
$data[ $key ] = $this->normalize_fixture( $value, "$path.$key" );
}
}
return $data;
}
}

File diff suppressed because one or more lines are too long