Add unit tests for API endpoints injection [PREMIUM-4]

This commit is contained in:
Alexey Stoletniy
2017-02-22 18:02:58 +03:00
parent 6c7cc5de0d
commit bb80fc0860
3 changed files with 92 additions and 14 deletions

View File

@ -1,5 +1,7 @@
<?php <?php
namespace MailPoet\API; namespace MailPoet\API;
use MailPoet\Util\Helpers;
use MailPoet\Util\Security; use MailPoet\Util\Security;
if(!defined('ABSPATH')) exit; if(!defined('ABSPATH')) exit;
@ -40,7 +42,7 @@ class API {
function setupAjax() { function setupAjax() {
do_action('mailpoet_api_setup', array($this)); do_action('mailpoet_api_setup', array($this));
$this->getRequestData(); $this->getRequestData($_POST);
if($this->checkToken() === false) { if($this->checkToken() === false) {
$error_response = new ErrorResponse( $error_response = new ErrorResponse(
@ -53,18 +55,19 @@ class API {
$error_response->send(); $error_response->send();
} }
$this->processRoute(); $response = $this->processRoute();
$response->send();
} }
function getRequestData() { function getRequestData($data) {
$this->_endpoint = isset($_POST['endpoint']) $this->_endpoint = isset($data['endpoint'])
? trim($_POST['endpoint']) ? Helpers::underscoreToCamelCase(trim($data['endpoint']))
: null; : null;
$this->_method = isset($_POST['method']) $this->_method = isset($data['method'])
? trim($_POST['method']) ? Helpers::underscoreToCamelCase(trim($data['method']))
: null; : null;
$this->_token = isset($_POST['token']) $this->_token = isset($data['token'])
? trim($_POST['token']) ? trim($data['token'])
: null; : null;
if(!$this->_endpoint || !$this->_method) { if(!$this->_endpoint || !$this->_method) {
@ -85,8 +88,8 @@ class API {
} }
} }
$this->_data = isset($_POST['data']) $this->_data = isset($data['data'])
? stripslashes_deep($_POST['data']) ? stripslashes_deep($data['data'])
: array(); : array();
// remove reserved keywords from data // remove reserved keywords from data
@ -108,6 +111,10 @@ class API {
function processRoute() { function processRoute() {
try { try {
if(empty($this->_endpoint_class)) {
throw new \Exception('Invalid endpoint');
}
$endpoint = new $this->_endpoint_class(); $endpoint = new $this->_endpoint_class();
// check the accessibility of the requested endpoint's action // check the accessibility of the requested endpoint's action
@ -129,17 +136,17 @@ class API {
array(), array(),
Response::STATUS_FORBIDDEN Response::STATUS_FORBIDDEN
); );
$error_response->send(); return $error_response;
} }
} }
$response = $endpoint->{$this->_method}($this->_data); $response = $endpoint->{$this->_method}($this->_data);
$response->send(); return $response;
} catch(\Exception $e) { } catch(\Exception $e) {
$error_response = new ErrorResponse( $error_response = new ErrorResponse(
array($e->getCode() => $e->getMessage()) array($e->getCode() => $e->getMessage())
); );
$error_response->send(); return $error_response;
} }
} }
@ -163,4 +170,8 @@ class API {
function addEndpointNamespace($namespace) { function addEndpointNamespace($namespace) {
$this->_endpoint_namespaces[] = $namespace; $this->_endpoint_namespaces[] = $namespace;
} }
function getEndpointNamespaces() {
return $this->_endpoint_namespaces;
}
} }

View File

@ -1,8 +1,11 @@
<?php <?php
use Codeception\Util\Stub;
use MailPoet\API\API; use MailPoet\API\API;
use MailPoet\API\SuccessResponse;
// required to be able to use wp_delete_user() // required to be able to use wp_delete_user()
require_once(ABSPATH.'wp-admin/includes/user.php'); require_once(ABSPATH.'wp-admin/includes/user.php');
require_once('APITestNamespacedEndpointStub.php');
class APITest extends MailPoetTest { class APITest extends MailPoetTest {
function _before() { function _before() {
@ -32,6 +35,52 @@ class APITest extends MailPoetTest {
expect($this->api->checkPermissions())->true(); expect($this->api->checkPermissions())->true();
} }
function testItCallsAPISetupAction() {
$called = false;
add_action(
'mailpoet_api_setup',
function ($api) use (&$called) {
$called = true;
expect($api instanceof API)->true();
}
);
$api = Stub::makeEmptyExcept(
$this->api,
'setupAjax',
array(
'processRoute' => Stub::makeEmpty(new SuccessResponse)
)
);
$api->setupAjax();
expect($called)->true();
}
function testItCanAddEndpointNamespaces() {
expect($this->api->getEndpointNamespaces())->count(1);
$namespace = "MailPoet\\Dummy\\Name\\Space";
$this->api->addEndpointNamespace($namespace);
$namespaces = $this->api->getEndpointNamespaces();
expect($namespaces)->count(2);
expect($namespaces[1])->equals($namespace);
}
function testItCanCallAddedEndpoints() {
$namespace = "MailPoet\\Some\\Name\\Space\\Endpoints";
$this->api->addEndpointNamespace($namespace);
$data = array(
'endpoint' => 'namespaced_endpoint_stub',
'method' => 'test',
'data' => array('test' => 'data')
);
$this->api->getRequestData($data);
$response = $this->api->processRoute();
expect($response->getData()['data'])->equals($data['data']);
}
function _after() { function _after() {
wp_delete_user($this->wp_user_id); wp_delete_user($this->wp_user_id);
} }

View File

@ -0,0 +1,18 @@
<?php
namespace MailPoet\Some\Name\Space\Endpoints;
use MailPoet\API\Endpoint as APIEndpoint;
use MailPoet\API\Access as APIAccess;
if(!defined('ABSPATH')) exit;
class NamespacedEndpointStub extends APIEndpoint {
public $permissions = array(
'test' => APIAccess::ALL
);
function test($data) {
return $this->successResponse($data);
}
}