From ddc47eaed4cd9eaff94802ab5f09cb01f9955142 Mon Sep 17 00:00:00 2001 From: Sergey Mitroshin Date: Thu, 26 Mar 2020 13:56:13 -0500 Subject: [PATCH] =?UTF-8?q?Post=20by=20Email:=20Unit=20tests=20for=20?= =?UTF-8?q?=E2=80=9Cregenerate=E2=80=9D=20and=20=E2=80=9Cdelete=E2=80=9D?= =?UTF-8?q?=20API=20endpoints?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The commit adds two unit tests for the “post-by-email” module: - `jetpack.regeneratePostByEmailAddress` - `jetpack.deletePostByEmailAddress` I also made some minor refactoring in the test class `WP_Test_Post_By_Email_API`. --- .../test-class.post-by-email-api.php | 183 +++++++++++++----- 1 file changed, 139 insertions(+), 44 deletions(-) diff --git a/tests/php/modules/post-by-email/test-class.post-by-email-api.php b/tests/php/modules/post-by-email/test-class.post-by-email-api.php index a0e03cfd0946b..6a87484dc8d2b 100644 --- a/tests/php/modules/post-by-email/test-class.post-by-email-api.php +++ b/tests/php/modules/post-by-email/test-class.post-by-email-api.php @@ -50,10 +50,12 @@ class WP_Test_Post_By_Email_API extends WP_Test_Jetpack_REST_Testcase { * * @var bool */ - private $request_validated = false; + private $request_validated; const SAMPLE_EMAIL = 'sample.email@post.wordpress.com'; + const PBE_API_ENDPOINT = '/jetpack/v4/settings'; + /** * Initialize the test class. * @@ -84,16 +86,29 @@ public function setUp() { $_GET['_for'] = 'jetpack'; add_filter( 'rest_pre_dispatch', array( $this, 'rest_pre_dispatch' ), 100, 2 ); + add_filter( 'pre_option_jetpack_private_options', array( $this, 'mock_jetpack_private_options' ), 10 ); + + $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json'; + + $this->request = new WP_REST_Request( 'POST', self::PBE_API_ENDPOINT ); + $this->request->set_header( 'Content-Type', $_SERVER['HTTP_CONTENT_TYPE'] ); + + $_GET['token'] = 'pretend_this_is_valid:1:' . self::$admin_id; + $_GET['timestamp'] = (string) time(); + $_GET['nonce'] = 'testing123'; + + $this->request_validated = false; } /** * Reset the environment to its original state after the test. */ public function tearDown() { - parent::tearDown(); - + remove_filter( 'pre_option_jetpack_private_options', array( $this, 'mock_jetpack_private_options' ), 10 ); remove_filter( 'rest_pre_dispatch', array( $this, 'rest_pre_dispatch' ), 100 ); + parent::tearDown(); + unset( $_SERVER['HTTP_CONTENT_TYPE'], $_GET['_for'], $_GET['token'], $_GET['timestamp'], $_GET['nonce'], $_GET['body-hash'], $_GET['signature'] ); // phpcs:ignore foreach ( self::$save_server_keys as $key ) { @@ -114,56 +129,47 @@ public function tearDown() { * Test the endpoint `post_by_email_address => create`. */ public function test_create() { - $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json'; + add_filter( 'pre_http_request', array( $this, 'mock_jetpack_api_response_create' ), 10, 3 ); - $body = wp_json_encode( array( 'post_by_email_address' => 'create' ) ); - $route = '/jetpack/v4/settings'; + $response = $this->rest_dispatch( 'create' ); - add_filter( 'pre_option_jetpack_private_options', array( $this, 'mock_jetpack_private_options' ), 10 ); - add_filter( 'pre_http_request', array( $this, 'mock_jetpack_api_response' ), 10, 3 ); - - $this->request = new WP_REST_Request( 'POST', $route ); - $this->request->set_body( $body ); - $this->request->set_header( 'Content-Type', $_SERVER['HTTP_CONTENT_TYPE'] ); - - $_GET['token'] = 'pretend_this_is_valid:1:' . self::$admin_id; - $_GET['timestamp'] = (string) time(); - $_GET['nonce'] = 'testing123'; - $_GET['body-hash'] = Jetpack::connection()->sha1_base64( $body ); + $this->assertEquals( 'success', $response->data['code'] ); + $this->assertEquals( self::SAMPLE_EMAIL, $response->data['post_by_email_address'] ); + $this->assertEquals( 200, $response->status ); + $this->assertTrue( $this->request_validated, "Method 'mock_jetpack_api_response_create' was skipped, failed to validate the request" ); - // @codingStandardsIgnoreStart - $dataset = array( - $_GET['token'], - $_GET['timestamp'], - $_GET['nonce'], - $_GET['body-hash'], - 'POST', - 'example.org', - '80', - $route, - 'qstest=yep', - ); - // @codingStandardsIgnoreEnd + remove_filter( 'pre_http_request', array( $this, 'mock_jetpack_api_response_create' ), 10 ); + } - $_GET['signature'] = base64_encode( // phpcs:ignore - hash_hmac( - 'sha1', - implode( "\n", $dataset ) . "\n", - 'secret', - true - ) - ); + /** + * Test the endpoint `post_by_email_address => regenerate`. + */ + public function test_regenerate() { + add_filter( 'pre_http_request', array( $this, 'mock_jetpack_api_response_regenerate' ), 10, 3 ); - $response = $this->server->dispatch( $this->request ); + $response = $this->rest_dispatch( 'regenerate' ); $this->assertEquals( 'success', $response->data['code'] ); $this->assertEquals( self::SAMPLE_EMAIL, $response->data['post_by_email_address'] ); $this->assertEquals( 200, $response->status ); + $this->assertTrue( $this->request_validated, "Method 'mock_jetpack_api_response_regenerate' was skipped, failed to validate the request" ); - remove_filter( 'pre_option_jetpack_private_options', array( $this, 'mock_jetpack_private_options' ), 10 ); - remove_filter( 'pre_http_request', array( $this, 'mock_jetpack_api_response' ), 10 ); + remove_filter( 'pre_http_request', array( $this, 'mock_jetpack_api_response_regenerate' ), 10 ); + } + + /** + * Test the endpoint `post_by_email_address => delete`. + */ + public function test_delete() { + add_filter( 'pre_http_request', array( $this, 'mock_jetpack_api_response_delete' ), 10, 3 ); + + $response = $this->rest_dispatch( 'delete' ); + + $this->assertEquals( 'success', $response->data['code'] ); + $this->assertEquals( 200, $response->status ); + $this->assertTrue( $this->request_validated, "Method 'mock_jetpack_api_response_delete' was skipped, failed to validate the request" ); - $this->assertTrue( $this->request_validated, "Method 'mock_jetpack_api_response' was skipped, failed to validate the request" ); + remove_filter( 'pre_http_request', array( $this, 'mock_jetpack_api_response_delete' ), 10 ); } /** @@ -216,7 +222,7 @@ public function rest_pre_dispatch( $result, $server ) { } /** - * Validate the Jetpack API request and mock the response. + * Validate the "Create" Jetpack API request and mock the response. * * @param false|array|WP_Error $response Whether to preempt an HTTP request's return value. Default false. * @param array $args HTTP request arguments. @@ -224,7 +230,7 @@ public function rest_pre_dispatch( $result, $server ) { * * @return array */ - public function mock_jetpack_api_response( $response, $args, $url ) { + public function mock_jetpack_api_response_create( $response, $args, $url ) { $this->assertEquals( 'POST', $args['method'] ); $this->assertStringContainsStringIgnoringCase( 'jetpack.createPostByEmailAddress', $args['body'] ); $this->assertStringStartsWith( 'https://jetpack.wordpress.com/xmlrpc.php', $url ); @@ -240,4 +246,93 @@ public function mock_jetpack_api_response( $response, $args, $url ) { ); } + /** + * Validate the "Regenerate" Jetpack API request and mock the response. + * + * @param false|array|WP_Error $response Whether to preempt an HTTP request's return value. Default false. + * @param array $args HTTP request arguments. + * @param string $url The request URL. + * + * @return array + */ + public function mock_jetpack_api_response_regenerate( $response, $args, $url ) { + $this->assertEquals( 'POST', $args['method'] ); + $this->assertStringContainsStringIgnoringCase( 'jetpack.regeneratePostByEmailAddress', $args['body'] ); + $this->assertStringStartsWith( 'https://jetpack.wordpress.com/xmlrpc.php', $url ); + $this->request_validated = true; + + return array( + 'headers' => array(), + 'body' => '' . self::SAMPLE_EMAIL . '', + 'response' => array( + 'code' => 200, + 'message' => 'OK', + ), + ); + } + + /** + * Validate the "Delete" Jetpack API request and mock the response. + * + * @param false|array|WP_Error $response Whether to preempt an HTTP request's return value. Default false. + * @param array $args HTTP request arguments. + * @param string $url The request URL. + * + * @return array + */ + public function mock_jetpack_api_response_delete( $response, $args, $url ) { + $this->assertEquals( 'POST', $args['method'] ); + $this->assertStringContainsStringIgnoringCase( 'jetpack.deletePostByEmailAddress', $args['body'] ); + $this->assertStringStartsWith( 'https://jetpack.wordpress.com/xmlrpc.php', $url ); + $this->request_validated = true; + + return array( + 'headers' => array(), + 'body' => '1', + 'response' => array( + 'code' => 200, + 'message' => 'OK', + ), + ); + } + + /** + * Prepare and send the API request. + * + * @param string $action API action to be sent. + * + * @return WP_REST_Response + */ + private function rest_dispatch( $action ) { + $body = wp_json_encode( array( 'post_by_email_address' => $action ) ); + $this->request->set_body( $body ); + $_GET['body-hash'] = Jetpack::connection()->sha1_base64( $body ); + + // phpcs:disable WordPress.Security.NonceVerification + $dataset = array( + $_GET['token'], + $_GET['timestamp'], + $_GET['nonce'], + $_GET['body-hash'], + 'POST', + 'example.org', + '80', + self::PBE_API_ENDPOINT, + 'qstest=yep', + ); + // phpcs:enable + + //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions + $_GET['signature'] = base64_encode( + hash_hmac( + 'sha1', + implode( "\n", $dataset ) . "\n", + 'secret', + true + ) + ); + + return $this->server->dispatch( $this->request ); + } + }