Skip to content

Commit

Permalink
Post by Email: Unit tests for “regenerate” and “delete” API endpoints
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
sergeymitr committed Mar 27, 2020
1 parent 949cb01 commit ddc47ea
Showing 1 changed file with 139 additions and 44 deletions.
183 changes: 139 additions & 44 deletions tests/php/modules/post-by-email/test-class.post-by-email-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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 ) {
Expand All @@ -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 );
}

/**
Expand Down Expand Up @@ -216,15 +222,15 @@ 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.
* @param string $url The request URL.
*
* @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( '<methodName>jetpack.createPostByEmailAddress</methodName>', $args['body'] );
$this->assertStringStartsWith( 'https://jetpack.wordpress.com/xmlrpc.php', $url );
Expand All @@ -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( '<methodName>jetpack.regeneratePostByEmailAddress</methodName>', $args['body'] );
$this->assertStringStartsWith( 'https://jetpack.wordpress.com/xmlrpc.php', $url );
$this->request_validated = true;

return array(
'headers' => array(),
'body' => '<?xml version="1.0" encoding="UTF-8"?><methodResponse><params><param><value><string>' . self::SAMPLE_EMAIL . '</string></value></param></params></methodResponse>',
'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( '<methodName>jetpack.deletePostByEmailAddress</methodName>', $args['body'] );
$this->assertStringStartsWith( 'https://jetpack.wordpress.com/xmlrpc.php', $url );
$this->request_validated = true;

return array(
'headers' => array(),
'body' => '<?xml version="1.0" encoding="UTF-8"?><methodResponse><params><param><value><boolean>1</boolean></value></param></params></methodResponse>',
'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 );
}

}

0 comments on commit ddc47ea

Please sign in to comment.