WordPress.org

Make WordPress Core


Ignore:
Timestamp:
02/15/2017 05:58:14 PM (3 years ago)
Author:
adamsilverstein
Message:

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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/rest-api/rest-schema-setup.php

    r40058 r40061  
    7575
    7676    public function test_build_wp_api_client_fixtures() {
    77         // Set up for testing the individual endpoints.
    78         // Set a current admin user.
    79         $administrator = $this->factory->user->create( array(
    80             'role' => 'administrator',
    81         ) );
    82         wp_set_current_user( $administrator );
    83 
    84         // Set up data for endpoints.
    85         $post_id  = $this->factory->post->create();
    86         $page_id  = $this->factory->post->create( array( 'post_type' => 'page' ) );
    87         $tag_id   = $this->factory->tag->create( array( 'name' => 'test' ) );
     77        // Set up data for individual endpoint responses.  We need to specify
     78        // lots of different fields on these objects, otherwise the generated
     79        // fixture file will be different between runs of PHPUnit tests, which
     80        // is not desirable.
     81
     82        $administrator_id = $this->factory->user->create( array(
     83            'role'          => 'administrator',
     84            'display_name'  => 'REST API Client Fixture: User',
     85            'user_nicename' => 'restapiclientfixtureuser',
     86            'user_email'    => 'administrator@example.org',
     87        ) );
     88        wp_set_current_user( $administrator_id );
     89
     90        $post_id = $this->factory->post->create( array(
     91            'post_name'      => 'restapi-client-fixture-post',
     92            'post_title'     => 'REST API Client Fixture: Post',
     93            'post_content'   => 'REST API Client Fixture: Post',
     94            'post_excerpt'   => 'REST API Client Fixture: Post',
     95            'post_author'    => 0,
     96        ) );
     97        wp_update_post( array(
     98            'ID'           => $post_id,
     99            'post_content' => 'Updated post content.',
     100        ) );
     101
     102        $page_id = $this->factory->post->create( array(
     103            'post_type'      => 'page',
     104            'post_name'      => 'restapi-client-fixture-page',
     105            'post_title'     => 'REST API Client Fixture: Page',
     106            'post_content'   => 'REST API Client Fixture: Page',
     107            'post_excerpt'   => 'REST API Client Fixture: Page',
     108            'post_date'      => '2017-02-14 00:00:00',
     109            'post_date_gmt'  => '2017-02-14 00:00:00',
     110            'post_author'    => 0,
     111        ) );
     112        wp_update_post( array(
     113            'ID'           => $page_id,
     114            'post_content' => 'Updated page content.',
     115        ) );
     116
     117        $tag_id = $this->factory->tag->create( array(
     118            'name'        => 'REST API Client Fixture: Tag',
     119            'slug'        => 'restapi-client-fixture-tag',
     120            'description' => 'REST API Client Fixture: Tag',
     121        ) );
     122
    88123        $media_id = $this->factory->attachment->create_object( '/tmp/canola.jpg', 0, array(
    89124            'post_mime_type' => 'image/jpeg',
    90125            'post_excerpt'   => 'A sample caption',
    91         ) );
    92         wp_update_post( array( 'post_content' => 'Updated content.', 'ID' => $post_id ) );
    93         wp_update_post( array( 'post_content' => 'Updated content.', 'ID' => $page_id ) );
     126            'post_name'      => 'restapi-client-fixture-attachment',
     127            'post_title'     => 'REST API Client Fixture: Attachment',
     128            'post_date'      => '2017-02-14 00:00:00',
     129            'post_date_gmt'  => '2017-02-14 00:00:00',
     130            'post_author'    => 0,
     131        ) );
     132
    94133        $comment_id = $this->factory->comment->create( array(
    95             'comment_approved' => 1,
    96             'comment_post_ID'  => $post_id,
    97             'user_id'          => 0,
     134            'comment_approved'     => 1,
     135            'comment_post_ID'      => $post_id,
     136            'user_id'              => 0,
     137            'comment_date'         => '2017-02-14 00:00:00',
     138            'comment_date_gmt'     => '2017-02-14 00:00:00',
     139            'comment_author'       => 'Internet of something or other',
     140            'comment_author_email' => 'lights@example.org',
     141            'comment_author_url'   => 'http://lights.example.org/',
    98142        ) );
    99143
     
    197241            ),
    198242            array(
    199                 'route' => '/wp/v2/users/1',
     243                'route' => '/wp/v2/users/' . $administrator_id,
    200244                'name'  => 'UserModel',
    201245            ),
     
    218262        );
    219263
    220         // Set up the mocked response and tell jshint to ignore the single quote json objects
    221         $mocked_responses = "/*jshint -W109 */\n\nvar mockedApiResponse = {};\n\n";
    222         $mocked_responses .= "/**\n";
     264        $mocked_responses = "/**\n";
    223265        $mocked_responses .= " * DO NOT EDIT\n";
    224266        $mocked_responses .= " * Auto-generated by test_build_wp_api_client_fixtures\n";
    225267        $mocked_responses .= " */\n";
     268        $mocked_responses .= "var mockedApiResponse = {};\n";
     269        $mocked_responses .= "/* jshint -W109 */\n";
    226270
    227271        foreach ( $routes_to_generate_data as $route ) {
     
    232276            $this->assertTrue( ! empty( $data ), $route['name'] . ' route should return data.' );
    233277
    234             $mocked_responses .= 'mockedApiResponse.' . $route['name'] . ' = ' . wp_json_encode( $data ) . ";\n\n";
     278            $fixture = $this->normalize_fixture( $data, $route['name'] );
     279            $mocked_responses .= "\nmockedApiResponse." . $route['name'] . ' = '
     280                . json_encode( $fixture, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES )
     281                . ";\n";
    235282        }
    236283
     
    246293        wp_delete_comment( $comment_id );
    247294    }
     295
     296    /**
     297     * This array contains normalized versions of object IDs and other values
     298     * that can change depending on how PHPUnit is executed.  For details on
     299     * how they were generated, see #39264.
     300     */
     301    private static $fixture_replacements = array(
     302        'PostsCollection.0.id' => 3,
     303        'PostsCollection.0.guid.rendered' => 'http://example.org/?p=3',
     304        'PostsCollection.0.link' => 'http://example.org/?p=3',
     305        'PostsCollection.0._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/posts/3',
     306        'PostsCollection.0._links.replies.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fcomments&post=3',
     307        'PostsCollection.0._links.version-history.0.href' => 'http://example.org/?rest_route=/wp/v2/posts/3/revisions',
     308        'PostsCollection.0._links.wp:attachment.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3',
     309        'PostsCollection.0._links.wp:term.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fcategories&post=3',
     310        'PostsCollection.0._links.wp:term.1.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Ftags&post=3',
     311        'PostModel.id' => 3,
     312        'PostModel.guid.rendered' => 'http://example.org/?p=3',
     313        'PostModel.link' => 'http://example.org/?p=3',
     314        'postRevisions.0.author' => '2',
     315        'postRevisions.0.id' => 4,
     316        'postRevisions.0.parent' => 3,
     317        'postRevisions.0.slug' => '3-revision-v1',
     318        'postRevisions.0.guid.rendered' => 'http://example.org/?p=4',
     319        'postRevisions.0._links.parent.0.href' => 'http://example.org/?rest_route=/wp/v2/posts/3',
     320        'PagesCollection.0.id' => 5,
     321        'PagesCollection.0.guid.rendered' => 'http://example.org/?page_id=5',
     322        'PagesCollection.0.link' => 'http://example.org/?page_id=5',
     323        'PagesCollection.0._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/pages/5',
     324        'PagesCollection.0._links.replies.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fcomments&post=5',
     325        'PagesCollection.0._links.version-history.0.href' => 'http://example.org/?rest_route=/wp/v2/pages/5/revisions',
     326        'PagesCollection.0._links.wp:attachment.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5',
     327        'PageModel.id' => 5,
     328        'PageModel.guid.rendered' => 'http://example.org/?page_id=5',
     329        'PageModel.link' => 'http://example.org/?page_id=5',
     330        'pageRevisions.0.author' => '2',
     331        'pageRevisions.0.id' => 6,
     332        'pageRevisions.0.parent' => 5,
     333        'pageRevisions.0.slug' => '5-revision-v1',
     334        'pageRevisions.0.guid.rendered' => 'http://example.org/?p=6',
     335        'pageRevisions.0._links.parent.0.href' => 'http://example.org/?rest_route=/wp/v2/pages/5',
     336        'MediaCollection.0.id' => 7,
     337        'MediaCollection.0.guid.rendered' => 'http://example.org/?attachment_id=7',
     338        'MediaCollection.0.link' => 'http://example.org/?attachment_id=7',
     339        'MediaCollection.0._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/media/7',
     340        'MediaCollection.0._links.replies.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fcomments&post=7',
     341        'MediaModel.id' => 7,
     342        'MediaModel.guid.rendered' => 'http://example.org/?attachment_id=7',
     343        'MediaModel.link' => 'http://example.org/?attachment_id=7',
     344        'TagsCollection.0.id' => 2,
     345        'TagsCollection.0._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/tags/2',
     346        'TagsCollection.0._links.wp:post_type.0.href' => 'http://example.org/?rest_route=%2Fwp%2Fv2%2Fposts&tags=2',
     347        'TagModel.id' => 2,
     348        'UsersCollection.1.id' => 2,
     349        'UsersCollection.1.link' => 'http://example.org/?author=2',
     350        'UsersCollection.1._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/users/2',
     351        'UserModel.id' => 2,
     352        'UserModel.link' => 'http://example.org/?author=2',
     353        'me.id' => 2,
     354        'me.link' => 'http://example.org/?author=2',
     355        'CommentsCollection.0.id' => 2,
     356        'CommentsCollection.0.post' => 3,
     357        'CommentsCollection.0.link' => 'http://example.org/?p=3#comment-2',
     358        'CommentsCollection.0._links.self.0.href' => 'http://example.org/?rest_route=/wp/v2/comments/2',
     359        'CommentsCollection.0._links.up.0.href' => 'http://example.org/?rest_route=/wp/v2/posts/3',
     360    );
     361
     362    private function normalize_fixture( $data, $path ) {
     363        if ( isset( self::$fixture_replacements[ $path ] ) ) {
     364            return self::$fixture_replacements[ $path ];
     365        }
     366
     367        if ( ! is_array( $data ) ) {
     368            return $data;
     369        }
     370
     371        foreach ( $data as $key => $value ) {
     372            if ( is_string( $value ) && (
     373                'date' === $key ||
     374                'date_gmt' === $key ||
     375                'modified' === $key ||
     376                'modified_gmt' === $key
     377            ) ) {
     378                $data[ $key ] = '2017-02-14T00:00:00';
     379            } else {
     380                $data[ $key ] = $this->normalize_fixture( $value, "$path.$key" );
     381            }
     382        }
     383
     384        return $data;
     385    }
    248386}
Note: See TracChangeset for help on using the changeset viewer.