Add unit tests [MAILPOET-743]
This commit is contained in:
@ -9,18 +9,23 @@ use MailPoet\Services\Bridge;
|
|||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Services extends APIEndpoint {
|
class Services extends APIEndpoint {
|
||||||
|
public $bridge;
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
$this->bridge = new Bridge();
|
||||||
|
}
|
||||||
|
|
||||||
function verifyMailPoetKey($data = array()) {
|
function verifyMailPoetKey($data = array()) {
|
||||||
$key = isset($data['key']) ? trim($data['key']) : null;
|
$key = isset($data['key']) ? trim($data['key']) : null;
|
||||||
|
|
||||||
if(!$key) {
|
if(!$key) {
|
||||||
return $this->badRequest(array(
|
return $this->badRequest(array(
|
||||||
APIError::BAD_REQUEST => __('You need to specify a key.', 'mailpoet')
|
APIError::BAD_REQUEST => __('Please specify a key.', 'mailpoet')
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$bridge = new Bridge($key);
|
$result = $this->bridge->checkKey($key);
|
||||||
$result = $bridge->checkKey();
|
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
return $this->errorResponse(array(
|
return $this->errorResponse(array(
|
||||||
$e->getCode() => $e->getMessage()
|
$e->getCode() => $e->getMessage()
|
||||||
|
@ -3,6 +3,7 @@ namespace MailPoet\API\Endpoints;
|
|||||||
use MailPoet\API\Endpoint as APIEndpoint;
|
use MailPoet\API\Endpoint as APIEndpoint;
|
||||||
use MailPoet\API\Error as APIError;
|
use MailPoet\API\Error as APIError;
|
||||||
use MailPoet\Models\Setting;
|
use MailPoet\Models\Setting;
|
||||||
|
use MailPoet\Services\Bridge;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
@ -21,6 +22,12 @@ class Settings extends APIEndpoint {
|
|||||||
foreach($settings as $name => $value) {
|
foreach($settings as $name => $value) {
|
||||||
Setting::setValue($name, $value);
|
Setting::setValue($name, $value);
|
||||||
}
|
}
|
||||||
|
if(!empty($settings['mta']['mailpoet_api_key'])
|
||||||
|
&& Bridge::isMPSendingServiceEnabled()
|
||||||
|
) {
|
||||||
|
$bridge = new Bridge();
|
||||||
|
$bridge->checkKey($settings['mta']['mailpoet_api_key']);
|
||||||
|
}
|
||||||
return $this->successResponse(Setting::getAll());
|
return $this->successResponse(Setting::getAll());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,12 +27,7 @@ class Menu {
|
|||||||
$this->assets_url = $assets_url;
|
$this->assets_url = $assets_url;
|
||||||
$subscribers_feature = new SubscribersFeature();
|
$subscribers_feature = new SubscribersFeature();
|
||||||
$this->subscribers_over_limit = $subscribers_feature->check();
|
$this->subscribers_over_limit = $subscribers_feature->check();
|
||||||
if(self::isOnMailPoetAdminPage()) {
|
$this->checkMailPoetAPIKey();
|
||||||
$show_notices = isset($_REQUEST['page'])
|
|
||||||
&& stripos($_REQUEST['page'], 'mailpoet-newsletters') === false;
|
|
||||||
$checker = new ServicesChecker();
|
|
||||||
$this->mp_api_key_valid = $checker->checkMailPoetAPIKeyValid($show_notices);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
@ -516,6 +511,15 @@ class Menu {
|
|||||||
return (stripos($screen_id, 'mailpoet-') !== false);
|
return (stripos($screen_id, 'mailpoet-') !== false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkMailPoetAPIKey(ServicesChecker $checker = null) {
|
||||||
|
if(self::isOnMailPoetAdminPage()) {
|
||||||
|
$show_notices = isset($_REQUEST['page'])
|
||||||
|
&& stripos($_REQUEST['page'], 'mailpoet-newsletters') === false;
|
||||||
|
$checker = $checker ?: new ServicesChecker();
|
||||||
|
$this->mp_api_key_valid = $checker->checkMailPoetAPIKeyValid($show_notices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function getLimitPerPage($model = null) {
|
private function getLimitPerPage($model = null) {
|
||||||
if($model === null) {
|
if($model === null) {
|
||||||
return Listing\Handler::DEFAULT_LIMIT_PER_PAGE;
|
return Listing\Handler::DEFAULT_LIMIT_PER_PAGE;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
|
|
||||||
use MailPoet\Mailer\Mailer;
|
|
||||||
use MailPoet\Models\Setting;
|
use MailPoet\Models\Setting;
|
||||||
use MailPoet\Models\Subscriber;
|
use MailPoet\Models\Subscriber;
|
||||||
use MailPoet\Services\Bridge;
|
use MailPoet\Services\Bridge;
|
||||||
@ -16,7 +15,7 @@ class ServicesChecker {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$state = Setting::getValue('mta.mailpoet_api_key_state');
|
$state = Setting::getValue(Bridge::API_KEY_STATE_SETTING_NAME);
|
||||||
if(empty($state['code']) || $state['code'] == Bridge::MAILPOET_KEY_VALID) {
|
if(empty($state['code']) || $state['code'] == Bridge::MAILPOET_KEY_VALID) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -30,7 +29,9 @@ class ServicesChecker {
|
|||||||
WPNotice::displayError($error);
|
WPNotice::displayError($error);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} elseif($state['code'] == Bridge::MAILPOET_KEY_EXPIRING) {
|
} elseif($state['code'] == Bridge::MAILPOET_KEY_EXPIRING
|
||||||
|
&& !empty($state['data']['expire_at'])
|
||||||
|
) {
|
||||||
$date = date('Y-m-d', strtotime($state['data']['expire_at']));
|
$date = date('Y-m-d', strtotime($state['data']['expire_at']));
|
||||||
$error = Helpers::replaceLinkTags(
|
$error = Helpers::replaceLinkTags(
|
||||||
__('Your newsletters are awesome! Don\'t forget to [link]upgrade your MailPoet email plan[/link] by %s to keep sending them to your subscribers.', 'mailpoet'),
|
__('Your newsletters are awesome! Don\'t forget to [link]upgrade your MailPoet email plan[/link] by %s to keep sending them to your subscribers.', 'mailpoet'),
|
||||||
|
@ -5,9 +5,7 @@ use Carbon\Carbon;
|
|||||||
use MailPoet\Cron\CronHelper;
|
use MailPoet\Cron\CronHelper;
|
||||||
use MailPoet\Mailer\Mailer;
|
use MailPoet\Mailer\Mailer;
|
||||||
use MailPoet\Models\SendingQueue;
|
use MailPoet\Models\SendingQueue;
|
||||||
use MailPoet\Models\Subscriber;
|
|
||||||
use MailPoet\Services\Bridge;
|
use MailPoet\Services\Bridge;
|
||||||
use MailPoet\Util\Helpers;
|
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
@ -26,8 +24,7 @@ class SendingServiceKeyCheck {
|
|||||||
|
|
||||||
function initApi() {
|
function initApi() {
|
||||||
if(!$this->bridge) {
|
if(!$this->bridge) {
|
||||||
$mailer_config = Mailer::getMailerConfig();
|
$this->bridge = new Bridge();
|
||||||
$this->bridge = new Bridge($mailer_config['mailpoet_api_key']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +85,12 @@ class SendingServiceKeyCheck {
|
|||||||
// abort if execution limit is reached
|
// abort if execution limit is reached
|
||||||
CronHelper::enforceExecutionLimit($this->timer);
|
CronHelper::enforceExecutionLimit($this->timer);
|
||||||
|
|
||||||
$result = $this->bridge->checkKey();
|
try {
|
||||||
|
$mailer_config = Mailer::getMailerConfig();
|
||||||
|
$result = $this->bridge->checkKey($mailer_config['mailpoet_api_key']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$result = array('code' => 503);
|
||||||
|
}
|
||||||
|
|
||||||
if(empty($result['code']) || $result['code'] == 503) {
|
if(empty($result['code']) || $result['code'] == 503) {
|
||||||
// reschedule the check
|
// reschedule the check
|
||||||
|
@ -22,7 +22,7 @@ class MailPoet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function send($newsletter, $subscriber, $extra_params = array()) {
|
function send($newsletter, $subscriber, $extra_params = array()) {
|
||||||
if(!$this->services_checker->checkMailPoetAPIKeyValid()) {
|
if($this->services_checker->checkMailPoetAPIKeyValid() === false) {
|
||||||
$response = __('MailPoet API key is invalid!', 'mailpoet');
|
$response = __('MailPoet API key is invalid!', 'mailpoet');
|
||||||
return Mailer::formatMailerSendErrorResult($response);
|
return Mailer::formatMailerSendErrorResult($response);
|
||||||
}
|
}
|
||||||
|
@ -7,23 +7,37 @@ use MailPoet\Models\Setting;
|
|||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Bridge {
|
class Bridge {
|
||||||
|
const API_KEY_STATE_SETTING_NAME = 'mta.mailpoet_api_key_state';
|
||||||
|
|
||||||
const MAILPOET_KEY_VALID = 200;
|
const MAILPOET_KEY_VALID = 200;
|
||||||
const MAILPOET_KEY_INVALID = 401;
|
const MAILPOET_KEY_INVALID = 401;
|
||||||
const MAILPOET_KEY_EXPIRING = 402;
|
const MAILPOET_KEY_EXPIRING = 402;
|
||||||
|
|
||||||
public $api;
|
public $api;
|
||||||
|
|
||||||
function __construct($api_key) {
|
function __construct() {
|
||||||
$this->api = new Bridge\API($api_key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static function isMPSendingServiceEnabled() {
|
static function isMPSendingServiceEnabled() {
|
||||||
|
try {
|
||||||
$mailer_config = Mailer::getMailerConfig();
|
$mailer_config = Mailer::getMailerConfig();
|
||||||
return !empty($mailer_config['method'])
|
return !empty($mailer_config['method'])
|
||||||
&& $mailer_config['method'] === Mailer::METHOD_MAILPOET;
|
&& $mailer_config['method'] === Mailer::METHOD_MAILPOET;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkKey() {
|
function initApi($api_key) {
|
||||||
|
if($this->api) {
|
||||||
|
$this->api->api_key = $api_key;
|
||||||
|
} else {
|
||||||
|
$this->api = new Bridge\API($api_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkKey($api_key) {
|
||||||
|
$this->initApi($api_key);
|
||||||
$result = $this->api->checkKey();
|
$result = $this->api->checkKey();
|
||||||
return $this->processResult($result);
|
return $this->processResult($result);
|
||||||
}
|
}
|
||||||
@ -33,7 +47,7 @@ class Bridge {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Setting::setValue(
|
Setting::setValue(
|
||||||
'mta.mailpoet_api_key_state',
|
self::API_KEY_STATE_SETTING_NAME,
|
||||||
array(
|
array(
|
||||||
'code' => (int)$result['code'],
|
'code' => (int)$result['code'],
|
||||||
'data' => !empty($result['data']) ? $result['data'] : null,
|
'data' => !empty($result['data']) ? $result['data'] : null,
|
||||||
@ -43,6 +57,6 @@ class Bridge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static function invalidateKey() {
|
static function invalidateKey() {
|
||||||
Setting::setValue('mta.mailpoet_api_key_state', array('code' => 401));
|
Setting::setValue(self::API_KEY_STATE_SETTING_NAME, array('code' => 401));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
tests/unit/API/Endpoints/ServicesTest.php
Normal file
65
tests/unit/API/Endpoints/ServicesTest.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Codeception\Util\Stub;
|
||||||
|
use MailPoet\API\Endpoints\Services;
|
||||||
|
use MailPoet\API\Response as APIResponse;
|
||||||
|
use MailPoet\Services\Bridge;
|
||||||
|
|
||||||
|
class ServicesTest extends MailPoetTest {
|
||||||
|
function _before() {
|
||||||
|
$this->services_endpoint = new Services();
|
||||||
|
$this->data = array('key' => '1234567890abcdef');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItRespondsWithErrorIfNoKeyIsGiven() {
|
||||||
|
$response = $this->services_endpoint->verifyMailPoetKey(array('key' => ''));
|
||||||
|
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
|
||||||
|
expect($response->errors[0]['message'])->equals('Please specify a key.');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItRespondsWithSuccessIfKeyIsValid() {
|
||||||
|
$this->services_endpoint->bridge = Stub::make(
|
||||||
|
new Bridge(),
|
||||||
|
array('checkKey' => array('code' => Bridge::MAILPOET_KEY_VALID)),
|
||||||
|
$this
|
||||||
|
);
|
||||||
|
$response = $this->services_endpoint->verifyMailPoetKey($this->data);
|
||||||
|
expect($response->status)->equals(APIResponse::STATUS_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItRespondsWithErrorIfKeyIsInvalid() {
|
||||||
|
$this->services_endpoint->bridge = Stub::make(
|
||||||
|
new Bridge(),
|
||||||
|
array('checkKey' => array('code' => Bridge::MAILPOET_KEY_INVALID)),
|
||||||
|
$this
|
||||||
|
);
|
||||||
|
$response = $this->services_endpoint->verifyMailPoetKey($this->data);
|
||||||
|
expect($response->status)->equals(APIResponse::STATUS_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItRespondsWithErrorIfKeyIsExpiring() {
|
||||||
|
$date = new DateTime;
|
||||||
|
$this->services_endpoint->bridge = Stub::make(
|
||||||
|
new Bridge(),
|
||||||
|
array('checkKey' => array(
|
||||||
|
'code' => Bridge::MAILPOET_KEY_EXPIRING,
|
||||||
|
'data' => array('expire_at' => $date->format('c'))
|
||||||
|
)),
|
||||||
|
$this
|
||||||
|
);
|
||||||
|
$response = $this->services_endpoint->verifyMailPoetKey($this->data);
|
||||||
|
expect($response->status)->equals(APIResponse::STATUS_NOT_FOUND);
|
||||||
|
expect($response->errors[0]['message'])->contains($date->format('Y-m-d'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItRespondsWithErrorIfServiceIsUnavailable() {
|
||||||
|
$this->services_endpoint->bridge = Stub::make(
|
||||||
|
new Bridge(),
|
||||||
|
array('checkKey' => array('code' => 503)),
|
||||||
|
$this
|
||||||
|
);
|
||||||
|
$response = $this->services_endpoint->verifyMailPoetKey($this->data);
|
||||||
|
expect($response->status)->equals(APIResponse::STATUS_NOT_FOUND);
|
||||||
|
expect($response->errors[0]['message'])->contains('503');
|
||||||
|
}
|
||||||
|
}
|
59
tests/unit/Config/MenuTest.php
Normal file
59
tests/unit/Config/MenuTest.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
use Codeception\Util\Stub;
|
||||||
|
use MailPoet\Config\Menu;
|
||||||
|
use MailPoet\Config\Renderer;
|
||||||
|
use MailPoet\Config\ServicesChecker;
|
||||||
|
|
||||||
|
class MenuTest extends MailPoetTest {
|
||||||
|
function testItReturnsTrueIfCurrentPageBelongsToMailpoet() {
|
||||||
|
$result = Menu::isOnMailPoetAdminPage(null, 'somepage');
|
||||||
|
expect($result)->false();
|
||||||
|
$result = Menu::isOnMailPoetAdminPage(null, 'mailpoet-newsletters');
|
||||||
|
expect($result)->true();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItRespectsExclusionsWhenCheckingMPPages() {
|
||||||
|
$exclude = array('mailpoet-welcome');
|
||||||
|
$result = Menu::isOnMailPoetAdminPage($exclude, 'mailpoet-welcome');
|
||||||
|
expect($result)->false();
|
||||||
|
$result = Menu::isOnMailPoetAdminPage($exclude, 'mailpoet-newsletters');
|
||||||
|
expect($result)->true();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItWorksWithRequestDataWhenCheckingMPPages() {
|
||||||
|
$_REQUEST['page'] = 'mailpoet-newsletters';
|
||||||
|
$result = Menu::isOnMailPoetAdminPage();
|
||||||
|
expect($result)->true();
|
||||||
|
|
||||||
|
$_REQUEST['page'] = 'blah';
|
||||||
|
$result = Menu::isOnMailPoetAdminPage();
|
||||||
|
expect($result)->false();
|
||||||
|
|
||||||
|
unset($_REQUEST['page']);
|
||||||
|
$result = Menu::isOnMailPoetAdminPage();
|
||||||
|
expect($result)->false();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItChecksMailpoetAPIKey() {
|
||||||
|
$renderer = Stub::make(new Renderer());
|
||||||
|
$assets_url = '';
|
||||||
|
$menu = new Menu($renderer, $assets_url);
|
||||||
|
|
||||||
|
$_REQUEST['page'] = 'mailpoet-newsletters';
|
||||||
|
$checker = Stub::make(
|
||||||
|
new ServicesChecker(),
|
||||||
|
array('checkMailPoetAPIKeyValid' => true),
|
||||||
|
$this
|
||||||
|
);
|
||||||
|
$menu->checkMailPoetAPIKey($checker);
|
||||||
|
expect($menu->mp_api_key_valid)->true();
|
||||||
|
|
||||||
|
$checker = Stub::make(
|
||||||
|
new ServicesChecker(),
|
||||||
|
array('checkMailPoetAPIKeyValid' => false),
|
||||||
|
$this
|
||||||
|
);
|
||||||
|
$menu->checkMailPoetAPIKey($checker);
|
||||||
|
expect($menu->mp_api_key_valid)->false();
|
||||||
|
}
|
||||||
|
}
|
70
tests/unit/Config/ServicesCheckerTest.php
Normal file
70
tests/unit/Config/ServicesCheckerTest.php
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use MailPoet\Config\ServicesChecker;
|
||||||
|
use MailPoet\Mailer\Mailer;
|
||||||
|
use MailPoet\Models\Setting;
|
||||||
|
use MailPoet\Services\Bridge;
|
||||||
|
|
||||||
|
class ServicesCheckerTest extends MailPoetTest {
|
||||||
|
function testItDoesNotCheckKeyIfMPSendingServiceIsDisabled() {
|
||||||
|
$this->disableMailPoetSendingMethod();
|
||||||
|
$result = ServicesChecker::checkMailPoetAPIKeyValid();
|
||||||
|
expect($result)->null();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItChecksKeyValidity() {
|
||||||
|
$this->setMailPoetSendingMethod();
|
||||||
|
Setting::setValue(
|
||||||
|
Bridge::API_KEY_STATE_SETTING_NAME,
|
||||||
|
array('code' => Bridge::MAILPOET_KEY_VALID)
|
||||||
|
);
|
||||||
|
$result = ServicesChecker::checkMailPoetAPIKeyValid();
|
||||||
|
expect($result)->true();
|
||||||
|
|
||||||
|
Setting::setValue(
|
||||||
|
Bridge::API_KEY_STATE_SETTING_NAME,
|
||||||
|
array('code' => Bridge::MAILPOET_KEY_INVALID)
|
||||||
|
);
|
||||||
|
$result = ServicesChecker::checkMailPoetAPIKeyValid();
|
||||||
|
expect($result)->false();
|
||||||
|
|
||||||
|
Setting::setValue(
|
||||||
|
Bridge::API_KEY_STATE_SETTING_NAME,
|
||||||
|
array(
|
||||||
|
'code' => Bridge::MAILPOET_KEY_EXPIRING,
|
||||||
|
'data' => array('expire_at' => date('c'))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$result = ServicesChecker::checkMailPoetAPIKeyValid();
|
||||||
|
expect($result)->true();
|
||||||
|
|
||||||
|
Setting::setValue(
|
||||||
|
Bridge::API_KEY_STATE_SETTING_NAME,
|
||||||
|
array(
|
||||||
|
'code' => 503
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$result = ServicesChecker::checkMailPoetAPIKeyValid();
|
||||||
|
expect($result)->true();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function setMailPoetSendingMethod() {
|
||||||
|
Setting::setValue(
|
||||||
|
Mailer::MAILER_CONFIG_SETTING_NAME,
|
||||||
|
array(
|
||||||
|
'method' => 'MailPoet',
|
||||||
|
'mailpoet_api_key' => 'some_key',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function disableMailPoetSendingMethod() {
|
||||||
|
Setting::setValue(
|
||||||
|
Mailer::MAILER_CONFIG_SETTING_NAME,
|
||||||
|
array(
|
||||||
|
'method' => 'PHPMail',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -29,8 +29,6 @@ class BounceTest extends MailPoetTest {
|
|||||||
|
|
||||||
$this->bounce = new Bounce(microtime(true));
|
$this->bounce = new Bounce(microtime(true));
|
||||||
|
|
||||||
$api =
|
|
||||||
|
|
||||||
$this->bounce->api = new MailPoet\Cron\Workers\Bounce\MockAPI('key');
|
$this->bounce->api = new MailPoet\Cron\Workers\Bounce\MockAPI('key');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,12 +40,6 @@ class BounceTest extends MailPoetTest {
|
|||||||
expect(Bounce::BATCH_SIZE)->equals(100);
|
expect(Bounce::BATCH_SIZE)->equals(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testItChecksIfCurrentSendingMethodIsMailpoet() {
|
|
||||||
expect(Bounce::checkBounceSyncAvailable())->false();
|
|
||||||
$this->setMailPoetSendingMethod();
|
|
||||||
expect(Bounce::checkBounceSyncAvailable())->true();
|
|
||||||
}
|
|
||||||
|
|
||||||
function testItThrowsExceptionWhenExecutionLimitIsReached() {
|
function testItThrowsExceptionWhenExecutionLimitIsReached() {
|
||||||
try {
|
try {
|
||||||
$bounce = new Bounce(microtime(true) - CronHelper::DAEMON_EXECUTION_LIMIT);
|
$bounce = new Bounce(microtime(true) - CronHelper::DAEMON_EXECUTION_LIMIT);
|
||||||
|
202
tests/unit/Cron/Workers/SendingServiceKeyCheckTest.php
Normal file
202
tests/unit/Cron/Workers/SendingServiceKeyCheckTest.php
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Codeception\Util\Stub;
|
||||||
|
use MailPoet\API\Endpoints\Cron;
|
||||||
|
use MailPoet\Cron\CronHelper;
|
||||||
|
use MailPoet\Cron\Workers\SendingServiceKeyCheck as SSKeyCheck;
|
||||||
|
use MailPoet\Cron\Workers\SendingServiceKeyCheck\API;
|
||||||
|
use MailPoet\Mailer\Mailer;
|
||||||
|
use MailPoet\Models\SendingQueue;
|
||||||
|
use MailPoet\Models\Setting;
|
||||||
|
use MailPoet\Services\Bridge;
|
||||||
|
use MailPoet\Util\Helpers;
|
||||||
|
|
||||||
|
class SendingServiceKeyCheckTest extends MailPoetTest {
|
||||||
|
function _before() {
|
||||||
|
$this->emails = array(
|
||||||
|
'soft_bounce@example.com',
|
||||||
|
'hard_bounce@example.com',
|
||||||
|
'good_address@example.com'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->sskeycheck = new SSKeyCheck(microtime(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItConstructs() {
|
||||||
|
expect($this->sskeycheck->timer)->notEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItThrowsExceptionWhenExecutionLimitIsReached() {
|
||||||
|
try {
|
||||||
|
$sskeycheck = new SSKeyCheck(microtime(true) - CronHelper::DAEMON_EXECUTION_LIMIT);
|
||||||
|
self::fail('Maximum execution time limit exception was not thrown.');
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
expect($e->getMessage())->equals('Maximum execution time has been reached.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItSchedulesSendingServiceKeyCheck() {
|
||||||
|
expect(SendingQueue::where('type', SSKeyCheck::TASK_TYPE)->findMany())->isEmpty();
|
||||||
|
SSKeyCheck::schedule();
|
||||||
|
expect(SendingQueue::where('type', SSKeyCheck::TASK_TYPE)->findMany())->notEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItDoesNotScheduleSendingServiceKeyCheckTwice() {
|
||||||
|
expect(count(SendingQueue::where('type', SSKeyCheck::TASK_TYPE)->findMany()))->equals(0);
|
||||||
|
SSKeyCheck::schedule();
|
||||||
|
expect(count(SendingQueue::where('type', SSKeyCheck::TASK_TYPE)->findMany()))->equals(1);
|
||||||
|
SSKeyCheck::schedule();
|
||||||
|
expect(count(SendingQueue::where('type', SSKeyCheck::TASK_TYPE)->findMany()))->equals(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItCanGetScheduledQueues() {
|
||||||
|
expect(SSKeyCheck::getScheduledQueues())->isEmpty();
|
||||||
|
$this->createScheduledQueue();
|
||||||
|
expect(SSKeyCheck::getScheduledQueues())->notEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItCanGetRunningQueues() {
|
||||||
|
expect(SSKeyCheck::getRunningQueues())->isEmpty();
|
||||||
|
$this->createRunningQueue();
|
||||||
|
expect(SSKeyCheck::getRunningQueues())->notEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItCanGetAllDueQueues() {
|
||||||
|
expect(SSKeyCheck::getAllDueQueues())->isEmpty();
|
||||||
|
|
||||||
|
// scheduled for now
|
||||||
|
$this->createScheduledQueue();
|
||||||
|
|
||||||
|
// running
|
||||||
|
$this->createRunningQueue();
|
||||||
|
|
||||||
|
// scheduled in the future (should not be retrieved)
|
||||||
|
$queue = $this->createScheduledQueue();
|
||||||
|
$queue->scheduled_at = Carbon::createFromTimestamp(current_time('timestamp'))->addDays(7);
|
||||||
|
$queue->save();
|
||||||
|
|
||||||
|
// completed (should not be retrieved)
|
||||||
|
$queue = $this->createRunningQueue();
|
||||||
|
$queue->status = SendingQueue::STATUS_COMPLETED;
|
||||||
|
$queue->save();
|
||||||
|
|
||||||
|
expect(count(SSKeyCheck::getAllDueQueues()))->equals(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItCanGetFutureQueues() {
|
||||||
|
expect(SSKeyCheck::getFutureQueues())->isEmpty();
|
||||||
|
$queue = $this->createScheduledQueue();
|
||||||
|
$queue->scheduled_at = Carbon::createFromTimestamp(current_time('timestamp'))->addDays(7);
|
||||||
|
$queue->save();
|
||||||
|
expect(count(SSKeyCheck::getFutureQueues()))->notEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItFailsToProcessWithoutMailPoetMethodSetUp() {
|
||||||
|
expect($this->sskeycheck->process())->false();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItFailsToProcessWithoutQueues() {
|
||||||
|
$this->setMailPoetSendingMethod();
|
||||||
|
expect($this->sskeycheck->process())->false();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItProcesses() {
|
||||||
|
$this->setMailPoetSendingMethod();
|
||||||
|
$this->createScheduledQueue();
|
||||||
|
$this->createRunningQueue();
|
||||||
|
expect($this->sskeycheck->process())->true();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItPreparesSendingServiceKeyCheckQueue() {
|
||||||
|
$queue = $this->createScheduledQueue();
|
||||||
|
$this->sskeycheck->prepareQueue($queue);
|
||||||
|
expect($queue->status)->null();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItProcessesSSKeyCheckQueue() {
|
||||||
|
$this->sskeycheck->bridge = Stub::make(
|
||||||
|
new Bridge,
|
||||||
|
array('checkKey' => array('code' => Bridge::MAILPOET_KEY_VALID)),
|
||||||
|
$this
|
||||||
|
);
|
||||||
|
$this->setMailPoetSendingMethod();
|
||||||
|
$queue = $this->createRunningQueue();
|
||||||
|
$this->sskeycheck->prepareQueue($queue);
|
||||||
|
$this->sskeycheck->processQueue($queue);
|
||||||
|
expect($queue->status)->equals(SendingQueue::STATUS_COMPLETED);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItReschedulesCheckOnException() {
|
||||||
|
$this->sskeycheck->bridge = Stub::make(
|
||||||
|
new Bridge,
|
||||||
|
array('checkKey' => function () { throw new \Exception(); }),
|
||||||
|
$this
|
||||||
|
);
|
||||||
|
$this->setMailPoetSendingMethod();
|
||||||
|
$queue = $this->createRunningQueue();
|
||||||
|
$scheduled_at = $queue->scheduled_at;
|
||||||
|
$this->sskeycheck->prepareQueue($queue);
|
||||||
|
$this->sskeycheck->processQueue($queue);
|
||||||
|
expect($scheduled_at < $queue->scheduled_at)->true();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItReschedulesCheckOnError() {
|
||||||
|
$this->sskeycheck->bridge = Stub::make(
|
||||||
|
new Bridge,
|
||||||
|
array('checkKey' => array('code' => 503)),
|
||||||
|
$this
|
||||||
|
);
|
||||||
|
$this->setMailPoetSendingMethod();
|
||||||
|
$queue = $this->createRunningQueue();
|
||||||
|
$scheduled_at = $queue->scheduled_at;
|
||||||
|
$this->sskeycheck->prepareQueue($queue);
|
||||||
|
$this->sskeycheck->processQueue($queue);
|
||||||
|
expect($scheduled_at < $queue->scheduled_at)->true();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItCalculatesNextRunDateWithinNextWeekBoundaries() {
|
||||||
|
$current_date = Carbon::createFromTimestamp(current_time('timestamp'));
|
||||||
|
$next_run_date = SSKeyCheck::getNextRunDate();
|
||||||
|
$difference = $next_run_date->diffInDays($current_date);
|
||||||
|
// Subtract days left in the current week
|
||||||
|
$difference -= (Carbon::DAYS_PER_WEEK - $current_date->format('N'));
|
||||||
|
expect($difference)->lessOrEquals(7);
|
||||||
|
expect($difference)->greaterOrEquals(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setMailPoetSendingMethod() {
|
||||||
|
Setting::setValue(
|
||||||
|
Mailer::MAILER_CONFIG_SETTING_NAME,
|
||||||
|
array(
|
||||||
|
'method' => 'MailPoet',
|
||||||
|
'mailpoet_api_key' => 'some_key',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createScheduledQueue() {
|
||||||
|
$queue = SendingQueue::create();
|
||||||
|
$queue->type = SSKeyCheck::TASK_TYPE;
|
||||||
|
$queue->status = SendingQueue::STATUS_SCHEDULED;
|
||||||
|
$queue->scheduled_at = Carbon::createFromTimestamp(current_time('timestamp'));
|
||||||
|
$queue->newsletter_id = 0;
|
||||||
|
$queue->save();
|
||||||
|
return $queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createRunningQueue() {
|
||||||
|
$queue = SendingQueue::create();
|
||||||
|
$queue->type = SSKeyCheck::TASK_TYPE;
|
||||||
|
$queue->status = null;
|
||||||
|
$queue->scheduled_at = Carbon::createFromTimestamp(current_time('timestamp'));
|
||||||
|
$queue->newsletter_id = 0;
|
||||||
|
$queue->save();
|
||||||
|
return $queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _after() {
|
||||||
|
ORM::raw_execute('TRUNCATE ' . Setting::$_table);
|
||||||
|
ORM::raw_execute('TRUNCATE ' . SendingQueue::$_table);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Codeception\Util\Stub;
|
||||||
use MailPoet\Mailer\Methods\MailPoet;
|
use MailPoet\Mailer\Methods\MailPoet;
|
||||||
|
use MailPoet\Config\ServicesChecker;
|
||||||
|
|
||||||
class MailPoetAPITest extends MailPoetTest {
|
class MailPoetAPITest extends MailPoetTest {
|
||||||
function _before() {
|
function _before() {
|
||||||
@ -103,6 +105,21 @@ class MailPoetAPITest extends MailPoetTest {
|
|||||||
->equals('Basic ' . base64_encode('api:' . $this->settings['api_key']));
|
->equals('Basic ' . base64_encode('api:' . $this->settings['api_key']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testItWillNotSendIfApiKeyIsMarkedInvalid() {
|
||||||
|
if(getenv('WP_TEST_MAILER_ENABLE_SENDING') !== 'true') return;
|
||||||
|
$this->mailer->api_key = 'someapi';
|
||||||
|
$this->mailer->services_checker = Stub::make(
|
||||||
|
new ServicesChecker(),
|
||||||
|
array('checkMailPoetAPIKeyValid' => false),
|
||||||
|
$this
|
||||||
|
);
|
||||||
|
$result = $this->mailer->send(
|
||||||
|
$this->newsletter,
|
||||||
|
$this->subscriber
|
||||||
|
);
|
||||||
|
expect($result['response'])->false();
|
||||||
|
}
|
||||||
|
|
||||||
function testItCannotSendWithoutProperApiKey() {
|
function testItCannotSendWithoutProperApiKey() {
|
||||||
if(getenv('WP_TEST_MAILER_ENABLE_SENDING') !== 'true') return;
|
if(getenv('WP_TEST_MAILER_ENABLE_SENDING') !== 'true') return;
|
||||||
$this->mailer->api_key = 'someapi';
|
$this->mailer->api_key = 'someapi';
|
||||||
|
82
tests/unit/Services/BridgeTest.php
Normal file
82
tests/unit/Services/BridgeTest.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Codeception\Util\Stub;
|
||||||
|
use MailPoet\Services\Bridge;
|
||||||
|
use MailPoet\Services\Bridge\API;
|
||||||
|
use MailPoet\Mailer\Mailer;
|
||||||
|
use MailPoet\Models\Setting;
|
||||||
|
|
||||||
|
require_once('BridgeTestMockAPI.php');
|
||||||
|
|
||||||
|
class BridgeTest extends MailPoetTest {
|
||||||
|
function _before() {
|
||||||
|
$this->valid_key = 'abcdefghijklmnopqrstuvwxyz';
|
||||||
|
$this->invalid_key = '401' . $this->valid_key;
|
||||||
|
$this->expiring_key = '402' . $this->valid_key;
|
||||||
|
$this->uncheckable_key = '503' . $this->valid_key;
|
||||||
|
|
||||||
|
$this->bridge = new Bridge();
|
||||||
|
|
||||||
|
$this->bridge->api = new MailPoet\Services\Bridge\MockAPI('key');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItChecksIfCurrentSendingMethodIsMailpoet() {
|
||||||
|
expect(Bridge::isMPSendingServiceEnabled())->false();
|
||||||
|
$this->setMailPoetSendingMethod();
|
||||||
|
expect(Bridge::isMPSendingServiceEnabled())->true();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testMPCheckReturnsFalseWhenMailerThrowsException() {
|
||||||
|
Setting::setValue(Mailer::MAILER_CONFIG_SETTING_NAME, '');
|
||||||
|
expect(Bridge::isMPSendingServiceEnabled())->false();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItInstantiatesDefaultAPI() {
|
||||||
|
$this->bridge->api = null;
|
||||||
|
$this->bridge->initApi(null);
|
||||||
|
expect($this->bridge->api instanceof API)->true();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItChecksValidKey() {
|
||||||
|
$result = $this->bridge->checkKey($this->valid_key);
|
||||||
|
expect($result)->notEmpty();
|
||||||
|
expect($result['code'])->equals(Bridge::MAILPOET_KEY_VALID);
|
||||||
|
|
||||||
|
$result = $this->bridge->checkKey($this->invalid_key);
|
||||||
|
expect($result)->notEmpty();
|
||||||
|
expect($result['code'])->equals(Bridge::MAILPOET_KEY_INVALID);
|
||||||
|
|
||||||
|
$result = $this->bridge->checkKey($this->expiring_key);
|
||||||
|
expect($result)->notEmpty();
|
||||||
|
expect($result['code'])->equals(Bridge::MAILPOET_KEY_EXPIRING);
|
||||||
|
expect($result['data']['expire_at'])->notEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItReturnsFalseOnEmptyAPIResponseCode() {
|
||||||
|
$api = Stub::make(new API(null), array('checkKey' => array()), $this);
|
||||||
|
$this->bridge->api = $api;
|
||||||
|
$result = $this->bridge->checkKey($this->valid_key);
|
||||||
|
expect($result)->false();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testItInvalidatesKey() {
|
||||||
|
Setting::setValue(Bridge::API_KEY_STATE_SETTING_NAME, array('code' => 200));
|
||||||
|
Bridge::invalidateKey();
|
||||||
|
$value = Setting::getValue(Bridge::API_KEY_STATE_SETTING_NAME);
|
||||||
|
expect($value)->equals(array('code' => 401));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setMailPoetSendingMethod() {
|
||||||
|
Setting::setValue(
|
||||||
|
Mailer::MAILER_CONFIG_SETTING_NAME,
|
||||||
|
array(
|
||||||
|
'method' => 'MailPoet',
|
||||||
|
'mailpoet_api_key' => 'some_key',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _after() {
|
||||||
|
ORM::raw_execute('TRUNCATE ' . Setting::$_table);
|
||||||
|
}
|
||||||
|
}
|
42
tests/unit/Services/BridgeTestMockAPI.php
Normal file
42
tests/unit/Services/BridgeTestMockAPI.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Services\Bridge;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class MockAPI {
|
||||||
|
public $api_key;
|
||||||
|
|
||||||
|
function __construct($api_key) {
|
||||||
|
$this->api_key = $api_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkKey() {
|
||||||
|
// if key begins with these codes, return them
|
||||||
|
$regex = '/^(401|402|503)/';
|
||||||
|
$code = preg_match($regex, $this->api_key, $m) ? $m[1] : 200;
|
||||||
|
return $this->processResponse($code);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processResponse($code) {
|
||||||
|
switch($code) {
|
||||||
|
case 200:
|
||||||
|
$body = array('subscriber_limit' => 10000);
|
||||||
|
break;
|
||||||
|
case 402:
|
||||||
|
$body = array(
|
||||||
|
'subscriber_limit' => 10000,
|
||||||
|
'expire_at' => Carbon::createFromTimestamp(current_time('timestamp'))
|
||||||
|
->addMonth()->format('c')
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 401:
|
||||||
|
default:
|
||||||
|
$body = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array('code' => $code, 'data' => $body);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user