Make captcha session stateless
[MAILPOET-6038]
This commit is contained in:
@@ -65,12 +65,18 @@ class Subscription {
|
|||||||
public function captchaImage($data) {
|
public function captchaImage($data) {
|
||||||
$width = !empty($data['width']) ? (int)$data['width'] : null;
|
$width = !empty($data['width']) ? (int)$data['width'] : null;
|
||||||
$height = !empty($data['height']) ? (int)$data['height'] : null;
|
$height = !empty($data['height']) ? (int)$data['height'] : null;
|
||||||
$sessionId = !empty($data['captcha_session_id']) ? $data['captcha_session_id'] : null;
|
$sessionId = $data['captcha_session_id'] ?? null;
|
||||||
return $this->captchaRenderer->renderImage($width, $height, $sessionId);
|
if (!$sessionId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->captchaRenderer->renderImage($sessionId, $width, $height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function captchaAudio($data) {
|
public function captchaAudio($data) {
|
||||||
$sessionId = !empty($data['captcha_session_id']) ? $data['captcha_session_id'] : null;
|
$sessionId = $data['captcha_session_id'] ?? null;
|
||||||
|
if (!$sessionId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return $this->captchaRenderer->renderAudio($sessionId);
|
return $this->captchaRenderer->renderAudio($sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -153,9 +153,9 @@ class SubscriberSubscribeController {
|
|||||||
|
|
||||||
[$subscriber, $subscriptionMeta] = $this->subscriberActions->subscribe($data, $segmentIds);
|
[$subscriber, $subscriptionMeta] = $this->subscriberActions->subscribe($data, $segmentIds);
|
||||||
|
|
||||||
if (!empty($captchaSettings['type']) && $captchaSettings['type'] === CaptchaConstants::TYPE_BUILTIN) {
|
if (!empty($captchaSettings['type']) && $captchaSettings['type'] === CaptchaConstants::TYPE_BUILTIN && isset($data['captcha_session_id'])) {
|
||||||
// Captcha has been verified, invalidate the session vars
|
// Captcha has been verified, invalidate the session vars
|
||||||
$this->captchaSession->reset();
|
$this->captchaSession->reset($data['captcha_session_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// record form statistics
|
// record form statistics
|
||||||
@@ -213,14 +213,18 @@ class SubscriberSubscribeController {
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
$captchaSessionId = isset($data['captcha_session_id']) ? $data['captcha_session_id'] : null;
|
// When serving the built-in CAPTCHA for the first time, generate a new session ID.
|
||||||
$this->captchaSession->init($captchaSessionId);
|
if (!isset($data['captcha_session_id'])) {
|
||||||
|
$data['captcha_session_id'] = $this->captchaSession->generateSessionId();
|
||||||
|
}
|
||||||
|
$sessionId = $data['captcha_session_id'];
|
||||||
|
|
||||||
if (!isset($data['captcha'])) {
|
if (!isset($data['captcha'])) {
|
||||||
// Save form data to session
|
// Save form data to session
|
||||||
$this->captchaSession->setFormData(array_merge($data, ['form_id' => $form->getId()]));
|
$this->captchaSession->setFormData($sessionId, array_merge($data, ['form_id' => $form->getId()]));
|
||||||
} elseif ($this->captchaSession->getFormData()) {
|
} elseif ($this->captchaSession->getFormData($sessionId)) {
|
||||||
// Restore form data from session
|
// Restore form data from session
|
||||||
$data = array_merge($this->captchaSession->getFormData(), ['captcha' => $data['captcha']]);
|
$data = array_merge($this->captchaSession->getFormData($sessionId), ['captcha' => $data['captcha']]);
|
||||||
}
|
}
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
@@ -17,15 +17,13 @@ class CaptchaPhrase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function createPhrase(string $sessionId): string {
|
public function createPhrase(string $sessionId): string {
|
||||||
$this->session->init($sessionId);
|
|
||||||
$storage = ['phrase' => $this->phraseBuilder->build()];
|
$storage = ['phrase' => $this->phraseBuilder->build()];
|
||||||
$this->session->setCaptchaHash($storage);
|
$this->session->setCaptchaHash($sessionId, $storage);
|
||||||
return $storage['phrase'];
|
return $storage['phrase'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPhrase(string $sessionId): ?string {
|
public function getPhrase(string $sessionId): ?string {
|
||||||
$this->session->init($sessionId);
|
$storage = $this->session->getCaptchaHash($sessionId);
|
||||||
$storage = $this->session->getCaptchaHash();
|
|
||||||
return (isset($storage['phrase']) && is_string($storage['phrase'])) ? $storage['phrase'] : null;
|
return (isset($storage['phrase']) && is_string($storage['phrase'])) ? $storage['phrase'] : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
<?php declare(strict_types = 1);
|
||||||
|
|
||||||
namespace MailPoet\Subscription\Captcha;
|
namespace MailPoet\Subscription\Captcha;
|
||||||
|
|
||||||
@@ -6,11 +6,10 @@ use MailPoet\Config\Env;
|
|||||||
use MailPoetVendor\Gregwar\Captcha\CaptchaBuilder;
|
use MailPoetVendor\Gregwar\Captcha\CaptchaBuilder;
|
||||||
|
|
||||||
class CaptchaRenderer {
|
class CaptchaRenderer {
|
||||||
|
|
||||||
const DEFAULT_WIDTH = 220;
|
const DEFAULT_WIDTH = 220;
|
||||||
const DEFAULT_HEIGHT = 60;
|
const DEFAULT_HEIGHT = 60;
|
||||||
|
|
||||||
private $phrase;
|
private CaptchaPhrase $phrase;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
CaptchaPhrase $phrase
|
CaptchaPhrase $phrase
|
||||||
@@ -18,11 +17,11 @@ class CaptchaRenderer {
|
|||||||
$this->phrase = $phrase;
|
$this->phrase = $phrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isSupported() {
|
public function isSupported(): bool {
|
||||||
return extension_loaded('gd') && function_exists('imagettftext');
|
return extension_loaded('gd') && function_exists('imagettftext');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderAudio($sessionId, $return = false) {
|
public function renderAudio(string $sessionId, $return = false) {
|
||||||
if (!$this->isSupported()) {
|
if (!$this->isSupported()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -50,7 +49,7 @@ class CaptchaRenderer {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renderImage($width = null, $height = null, $sessionId = null, $return = false) {
|
public function renderImage(string $sessionId, $width = null, $height = null, $return = false) {
|
||||||
if (!$this->isSupported()) {
|
if (!$this->isSupported()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -89,8 +88,8 @@ class CaptchaRenderer {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getPhrase(string $sessionId = null): string {
|
private function getPhrase(string $sessionId): string {
|
||||||
$phrase = $sessionId ? $this->phrase->getPhrase($sessionId) : null;
|
$phrase = $this->phrase->getPhrase($sessionId);
|
||||||
if (!$phrase) {
|
if (!$phrase) {
|
||||||
throw new \RuntimeException("No CAPTCHA phrase was generated.");
|
throw new \RuntimeException("No CAPTCHA phrase was generated.");
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
<?php declare(strict_types = 1);
|
||||||
|
|
||||||
namespace MailPoet\Subscription\Captcha;
|
namespace MailPoet\Subscription\Captcha;
|
||||||
|
|
||||||
@@ -12,11 +12,7 @@ class CaptchaSession {
|
|||||||
const SESSION_HASH_KEY = 'hash';
|
const SESSION_HASH_KEY = 'hash';
|
||||||
const SESSION_FORM_KEY = 'form';
|
const SESSION_FORM_KEY = 'form';
|
||||||
|
|
||||||
/** @var WPFunctions */
|
private WPFunctions $wp;
|
||||||
private $wp;
|
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
private $id = '';
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
WPFunctions $wp
|
WPFunctions $wp
|
||||||
@@ -24,39 +20,38 @@ class CaptchaSession {
|
|||||||
$this->wp = $wp;
|
$this->wp = $wp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function init(string $id = null) {
|
public function generateSessionId(): string {
|
||||||
$this->id = $id ?: Security::generateRandomString(self::ID_LENGTH);
|
return Security::generateRandomString(self::ID_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): string {
|
public function reset(string $sessionId): void {
|
||||||
if (!$this->id) {
|
$formKey = $this->getKey($sessionId, self::SESSION_FORM_KEY);
|
||||||
$this->init();
|
$hashKey = $this->getKey($sessionId, self::SESSION_HASH_KEY);
|
||||||
}
|
$this->wp->deleteTransient($formKey);
|
||||||
return $this->id;
|
$this->wp->deleteTransient($hashKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reset() {
|
public function setFormData(string $sessionId, array $data): void {
|
||||||
$this->wp->deleteTransient($this->getKey(self::SESSION_FORM_KEY));
|
$key = $this->getKey($sessionId, self::SESSION_FORM_KEY);
|
||||||
$this->wp->deleteTransient($this->getKey(self::SESSION_HASH_KEY));
|
$this->wp->setTransient($key, $data, self::EXPIRATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setFormData(array $data) {
|
public function getFormData(string $sessionId) {
|
||||||
$this->wp->setTransient($this->getKey(self::SESSION_FORM_KEY), $data, self::EXPIRATION);
|
$key = $this->getKey($sessionId, self::SESSION_FORM_KEY);
|
||||||
|
return $this->wp->getTransient($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormData() {
|
public function setCaptchaHash(string $sessionId, $hash): void {
|
||||||
return $this->wp->getTransient($this->getKey(self::SESSION_FORM_KEY));
|
$key = $this->getKey($sessionId, self::SESSION_HASH_KEY);
|
||||||
|
$this->wp->setTransient($key, $hash, self::EXPIRATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCaptchaHash($hash) {
|
public function getCaptchaHash(string $sessionId) {
|
||||||
$this->wp->setTransient($this->getKey(self::SESSION_HASH_KEY), $hash, self::EXPIRATION);
|
$key = $this->getKey($sessionId, self::SESSION_HASH_KEY);
|
||||||
|
return $this->wp->getTransient($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCaptchaHash() {
|
private function getKey(string $sessionId, string $type): string {
|
||||||
return $this->wp->getTransient($this->getKey(self::SESSION_HASH_KEY));
|
return implode('_', ['MAILPOET', $sessionId, $type]);
|
||||||
}
|
|
||||||
|
|
||||||
private function getKey($type) {
|
|
||||||
return \implode('_', ['MAILPOET', $this->getId(), $type]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,23 +5,17 @@ namespace MailPoet\Subscription\Captcha\Validator;
|
|||||||
use MailPoet\Subscribers\SubscriberIPsRepository;
|
use MailPoet\Subscribers\SubscriberIPsRepository;
|
||||||
use MailPoet\Subscribers\SubscribersRepository;
|
use MailPoet\Subscribers\SubscribersRepository;
|
||||||
use MailPoet\Subscription\Captcha\CaptchaPhrase;
|
use MailPoet\Subscription\Captcha\CaptchaPhrase;
|
||||||
use MailPoet\Subscription\Captcha\CaptchaSession;
|
|
||||||
use MailPoet\Subscription\SubscriptionUrlFactory;
|
use MailPoet\Subscription\SubscriptionUrlFactory;
|
||||||
use MailPoet\Util\Helpers;
|
use MailPoet\Util\Helpers;
|
||||||
use MailPoet\WP\Functions as WPFunctions;
|
use MailPoet\WP\Functions as WPFunctions;
|
||||||
|
|
||||||
class BuiltInCaptchaValidator implements CaptchaValidator {
|
class BuiltInCaptchaValidator implements CaptchaValidator {
|
||||||
|
|
||||||
|
|
||||||
/** @var SubscriptionUrlFactory */
|
/** @var SubscriptionUrlFactory */
|
||||||
private $subscriptionUrlFactory;
|
private $subscriptionUrlFactory;
|
||||||
|
|
||||||
/** @var CaptchaPhrase */
|
/** @var CaptchaPhrase */
|
||||||
private $captchaPhrase;
|
private $captchaPhrase;
|
||||||
|
|
||||||
/** @var CaptchaSession */
|
|
||||||
private $captchaSession;
|
|
||||||
|
|
||||||
/** @var WPFunctions */
|
/** @var WPFunctions */
|
||||||
private $wp;
|
private $wp;
|
||||||
|
|
||||||
@@ -34,14 +28,12 @@ class BuiltInCaptchaValidator implements CaptchaValidator {
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
SubscriptionUrlFactory $subscriptionUrlFactory,
|
SubscriptionUrlFactory $subscriptionUrlFactory,
|
||||||
CaptchaPhrase $captchaPhrase,
|
CaptchaPhrase $captchaPhrase,
|
||||||
CaptchaSession $captchaSession,
|
|
||||||
WPFunctions $wp,
|
WPFunctions $wp,
|
||||||
SubscriberIPsRepository $subscriberIPsRepository,
|
SubscriberIPsRepository $subscriberIPsRepository,
|
||||||
SubscribersRepository $subscribersRepository
|
SubscribersRepository $subscribersRepository
|
||||||
) {
|
) {
|
||||||
$this->subscriptionUrlFactory = $subscriptionUrlFactory;
|
$this->subscriptionUrlFactory = $subscriptionUrlFactory;
|
||||||
$this->captchaPhrase = $captchaPhrase;
|
$this->captchaPhrase = $captchaPhrase;
|
||||||
$this->captchaSession = $captchaSession;
|
|
||||||
$this->wp = $wp;
|
$this->wp = $wp;
|
||||||
$this->subscriberIPsRepository = $subscriberIPsRepository;
|
$this->subscriberIPsRepository = $subscriberIPsRepository;
|
||||||
$this->subscribersRepository = $subscribersRepository;
|
$this->subscribersRepository = $subscribersRepository;
|
||||||
@@ -52,26 +44,34 @@ class BuiltInCaptchaValidator implements CaptchaValidator {
|
|||||||
if (!$isBuiltinCaptchaRequired) {
|
if (!$isBuiltinCaptchaRequired) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// session ID must be set at this point
|
||||||
|
$sessionId = $data['captcha_session_id'] ?? null;
|
||||||
|
if (!$sessionId) {
|
||||||
|
throw new ValidationError(__('CAPTCHA verification failed.', 'mailpoet'));
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($data['captcha'])) {
|
if (empty($data['captcha'])) {
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
__('Please fill in the CAPTCHA.', 'mailpoet'),
|
__('Please fill in the CAPTCHA.', 'mailpoet'),
|
||||||
[
|
[
|
||||||
'redirect_url' => $this->subscriptionUrlFactory->getCaptchaUrl($this->captchaSession->getId()),
|
'redirect_url' => $this->subscriptionUrlFactory->getCaptchaUrl($sessionId),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$captchaHash = $this->captchaPhrase->getPhrase($this->captchaSession->getId());
|
|
||||||
|
$captchaHash = $this->captchaPhrase->getPhrase($sessionId);
|
||||||
if (empty($captchaHash)) {
|
if (empty($captchaHash)) {
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
__('Please regenerate the CAPTCHA.', 'mailpoet'),
|
__('Please regenerate the CAPTCHA.', 'mailpoet'),
|
||||||
[
|
[
|
||||||
'redirect_url' => $this->subscriptionUrlFactory->getCaptchaUrl($this->captchaSession->getId()),
|
'redirect_url' => $this->subscriptionUrlFactory->getCaptchaUrl($sessionId),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hash_equals(strtolower($data['captcha']), strtolower($captchaHash))) {
|
if (!hash_equals(strtolower($data['captcha']), strtolower($captchaHash))) {
|
||||||
$this->captchaPhrase->createPhrase($this->captchaSession->getId());
|
$this->captchaPhrase->createPhrase($sessionId);
|
||||||
throw new ValidationError(
|
throw new ValidationError(
|
||||||
__('The characters entered do not match with the previous CAPTCHA.', 'mailpoet'),
|
__('The characters entered do not match with the previous CAPTCHA.', 'mailpoet'),
|
||||||
[
|
[
|
||||||
|
@@ -55,9 +55,9 @@ class CaptchaFormRenderer {
|
|||||||
return __("Confirm you’re not a robot", 'mailpoet');
|
return __("Confirm you’re not a robot", 'mailpoet');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCaptchaPageContent($sessionId) {
|
public function getCaptchaPageContent(string $sessionId) {
|
||||||
$this->captchaPhrase->createPhrase($sessionId);
|
$this->captchaPhrase->createPhrase($sessionId);
|
||||||
$captchaSessionForm = $this->captchaSession->getFormData();
|
$captchaSessionForm = $this->captchaSession->getFormData($sessionId);
|
||||||
$showSuccessMessage = !empty($_GET['mailpoet_success']);
|
$showSuccessMessage = !empty($_GET['mailpoet_success']);
|
||||||
$showErrorMessage = !empty($_GET['mailpoet_error']);
|
$showErrorMessage = !empty($_GET['mailpoet_error']);
|
||||||
$formId = 0;
|
$formId = 0;
|
||||||
@@ -112,7 +112,7 @@ class CaptchaFormRenderer {
|
|||||||
'id="mailpoet_captcha_form" ' .
|
'id="mailpoet_captcha_form" ' .
|
||||||
'novalidate>';
|
'novalidate>';
|
||||||
$formHtml .= '<input type="hidden" name="data[form_id]" value="' . $formId . '" />';
|
$formHtml .= '<input type="hidden" name="data[form_id]" value="' . $formId . '" />';
|
||||||
$formHtml .= '<input type="hidden" name="data[captcha_session_id]" value="' . htmlspecialchars((string)$this->captchaSession->getId()) . '" />';
|
$formHtml .= '<input type="hidden" name="data[captcha_session_id]" value="' . htmlspecialchars($sessionId) . '" />';
|
||||||
$formHtml .= '<input type="hidden" name="api_version" value="v1" />';
|
$formHtml .= '<input type="hidden" name="api_version" value="v1" />';
|
||||||
$formHtml .= '<input type="hidden" name="endpoint" value="subscribers" />';
|
$formHtml .= '<input type="hidden" name="endpoint" value="subscribers" />';
|
||||||
$formHtml .= '<input type="hidden" name="mailpoet_method" value="subscribe" />';
|
$formHtml .= '<input type="hidden" name="mailpoet_method" value="subscribe" />';
|
||||||
@@ -121,8 +121,8 @@ class CaptchaFormRenderer {
|
|||||||
|
|
||||||
$width = 220;
|
$width = 220;
|
||||||
$height = 60;
|
$height = 60;
|
||||||
$captchaUrl = $this->subscriptionUrlFactory->getCaptchaImageUrl($width, $height, $this->captchaSession->getId());
|
$captchaUrl = $this->subscriptionUrlFactory->getCaptchaImageUrl($width, $height, $sessionId);
|
||||||
$mp3CaptchaUrl = $this->subscriptionUrlFactory->getCaptchaAudioUrl($this->captchaSession->getId());
|
$mp3CaptchaUrl = $this->subscriptionUrlFactory->getCaptchaAudioUrl($sessionId);
|
||||||
|
|
||||||
$reloadIcon = Env::$assetsUrl . '/img/icons/image-rotate.svg';
|
$reloadIcon = Env::$assetsUrl . '/img/icons/image-rotate.svg';
|
||||||
$playIcon = Env::$assetsUrl . '/img/icons/controls-volumeon.svg';
|
$playIcon = Env::$assetsUrl . '/img/icons/controls-volumeon.svg';
|
||||||
|
@@ -328,8 +328,10 @@ class Pages {
|
|||||||
|
|
||||||
switch ($this->action) {
|
switch ($this->action) {
|
||||||
case self::ACTION_CAPTCHA:
|
case self::ACTION_CAPTCHA:
|
||||||
|
$captchaSessionId = $this->data['captcha_session_id'] ?? null;
|
||||||
$captchaSessionId = isset($this->data['captcha_session_id']) ? $this->data['captcha_session_id'] : null;
|
if (!$captchaSessionId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$content = $this->captchaRenderer->getCaptchaPageContent($captchaSessionId);
|
$content = $this->captchaRenderer->getCaptchaPageContent($captchaSessionId);
|
||||||
break;
|
break;
|
||||||
case self::ACTION_CONFIRM:
|
case self::ACTION_CONFIRM:
|
||||||
|
@@ -765,8 +765,7 @@ class SubscribersTest extends \MailPoetTest {
|
|||||||
->create();
|
->create();
|
||||||
$captchaValue = ['phrase' => 'ihG5W'];
|
$captchaValue = ['phrase' => 'ihG5W'];
|
||||||
$captchaSessionId = 'abcdfgh';
|
$captchaSessionId = 'abcdfgh';
|
||||||
$this->captchaSession->init($captchaSessionId);
|
$this->captchaSession->setCaptchaHash($captchaSessionId, $captchaValue);
|
||||||
$this->captchaSession->setCaptchaHash($captchaValue);
|
|
||||||
$response = $this->endpoint->subscribe([
|
$response = $this->endpoint->subscribe([
|
||||||
$this->obfuscatedEmail => $email,
|
$this->obfuscatedEmail => $email,
|
||||||
'form_id' => $this->form->getId(),
|
'form_id' => $this->form->getId(),
|
||||||
|
@@ -15,15 +15,15 @@ class CaptchaRendererTest extends \MailPoetTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function testItRendersImage(): void {
|
public function testItRendersImage(): void {
|
||||||
$sessionId = $this->session->getId();
|
$sessionId = '123';
|
||||||
$this->session->setCaptchaHash(['phrase' => 'a']);
|
$this->session->setCaptchaHash($sessionId, ['phrase' => 'a']);
|
||||||
$result = $this->testee->renderImage(null, null, $sessionId, true);
|
$result = $this->testee->renderImage($sessionId, null, null, true);
|
||||||
$this->assertStringContainsString('JPEG', $result);
|
$this->assertStringContainsString('JPEG', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItRendersAudio(): void {
|
public function testItRendersAudio(): void {
|
||||||
$sessionId = $this->session->getId();
|
$sessionId = '123';
|
||||||
$this->session->setCaptchaHash(['phrase' => 'a']);
|
$this->session->setCaptchaHash($sessionId, ['phrase' => 'a']);
|
||||||
$result = $this->testee->renderAudio($sessionId, true);
|
$result = $this->testee->renderAudio($sessionId, true);
|
||||||
$partOfAudio = '(-1166::BBKKQQVZZ^^bbggkkoosxx|';
|
$partOfAudio = '(-1166::BBKKQQVZZ^^bbggkkoosxx|';
|
||||||
$this->assertStringContainsString($partOfAudio, $result);
|
$this->assertStringContainsString($partOfAudio, $result);
|
||||||
|
@@ -8,41 +8,29 @@ use MailPoet\WP\Functions as WPFunctions;
|
|||||||
class CaptchaSessionTest extends \MailPoetTest {
|
class CaptchaSessionTest extends \MailPoetTest {
|
||||||
const SESSION_ID = 'ABCD';
|
const SESSION_ID = 'ABCD';
|
||||||
|
|
||||||
/** @var CaptchaSession */
|
private CaptchaSession $captchaSession;
|
||||||
private $captchaSession;
|
|
||||||
|
|
||||||
public function _before() {
|
public function _before() {
|
||||||
$this->captchaSession = new CaptchaSession(new WPFunctions);
|
$this->captchaSession = new CaptchaSession(new WPFunctions);
|
||||||
$this->captchaSession->init(self::SESSION_ID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItCanStoreAndRetrieveFormData() {
|
public function testItCanStoreAndRetrieveFormData() {
|
||||||
$formData = ['email' => 'email@example.com'];
|
$formData = ['email' => 'email@example.com'];
|
||||||
$this->captchaSession->setFormData($formData);
|
$this->captchaSession->setFormData(self::SESSION_ID, $formData);
|
||||||
verify($this->captchaSession->getFormData())->equals($formData);
|
verify($this->captchaSession->getFormData(self::SESSION_ID))->equals($formData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItCanStoreAndRetrieveCaptchaHash() {
|
public function testItCanStoreAndRetrieveCaptchaHash() {
|
||||||
$hash = '1234';
|
$hash = '1234';
|
||||||
$this->captchaSession->setCaptchaHash($hash);
|
$this->captchaSession->setCaptchaHash(self::SESSION_ID, $hash);
|
||||||
verify($this->captchaSession->getCaptchaHash())->equals($hash);
|
verify($this->captchaSession->getCaptchaHash(self::SESSION_ID))->equals($hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItCanResetSessionData() {
|
public function testItCanResetSessionData() {
|
||||||
$this->captchaSession->setFormData(['email' => 'email@example.com']);
|
$this->captchaSession->setFormData(self::SESSION_ID, ['email' => 'email@example.com']);
|
||||||
$this->captchaSession->setCaptchaHash('hash123');
|
$this->captchaSession->setCaptchaHash(self::SESSION_ID, 'hash123');
|
||||||
$this->captchaSession->reset();
|
$this->captchaSession->reset(self::SESSION_ID);
|
||||||
verify($this->captchaSession->getFormData())->false();
|
verify($this->captchaSession->getFormData(self::SESSION_ID))->false();
|
||||||
verify($this->captchaSession->getCaptchaHash())->false();
|
verify($this->captchaSession->getCaptchaHash(self::SESSION_ID))->false();
|
||||||
}
|
|
||||||
|
|
||||||
public function testItAssociatesDataWithSession() {
|
|
||||||
$hash = '1234';
|
|
||||||
$this->captchaSession->setCaptchaHash($hash);
|
|
||||||
verify($this->captchaSession->getCaptchaHash())->equals($hash);
|
|
||||||
$this->captchaSession->init();
|
|
||||||
verify($this->captchaSession->getCaptchaHash())->false();
|
|
||||||
$this->captchaSession->init(self::SESSION_ID);
|
|
||||||
verify($this->captchaSession->getCaptchaHash())->equals($hash);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,23 +11,26 @@ use MailPoet\WP\Functions as WPFunctions;
|
|||||||
use MailPoetVendor\Carbon\Carbon;
|
use MailPoetVendor\Carbon\Carbon;
|
||||||
|
|
||||||
class BuiltInCaptchaValidatorTest extends \MailPoetTest {
|
class BuiltInCaptchaValidatorTest extends \MailPoetTest {
|
||||||
|
private BuiltInCaptchaValidator $testee;
|
||||||
|
private CaptchaSession $session;
|
||||||
/** @var BuiltInCaptchaValidator */
|
|
||||||
private $testee;
|
|
||||||
|
|
||||||
/** @var CaptchaSession */
|
|
||||||
private $session;
|
|
||||||
|
|
||||||
public function _before() {
|
public function _before() {
|
||||||
$this->testee = $this->diContainer->get(BuiltInCaptchaValidator::class);
|
$this->testee = $this->diContainer->get(BuiltInCaptchaValidator::class);
|
||||||
$this->session = $this->diContainer->get(CaptchaSession::class);
|
$this->session = $this->diContainer->get(CaptchaSession::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testEmptyCaptchaThrowsError() {
|
public function testMissingCaptchaSessionIdThrowsError() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->testee->validate([]);
|
$this->testee->validate([]);
|
||||||
|
} catch (ValidationError $error) {
|
||||||
|
$meta = $error->getMeta();
|
||||||
|
$this->assertEquals('CAPTCHA verification failed.', $meta['error']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmptyCaptchaThrowsError() {
|
||||||
|
try {
|
||||||
|
$this->testee->validate(['captcha_session_id' => '123']);
|
||||||
} catch (ValidationError $error) {
|
} catch (ValidationError $error) {
|
||||||
$meta = $error->getMeta();
|
$meta = $error->getMeta();
|
||||||
$this->assertEquals('Please fill in the CAPTCHA.', $meta['error']);
|
$this->assertEquals('Please fill in the CAPTCHA.', $meta['error']);
|
||||||
@@ -36,11 +39,10 @@ class BuiltInCaptchaValidatorTest extends \MailPoetTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function testWrongCaptchaThrowsError() {
|
public function testWrongCaptchaThrowsError() {
|
||||||
|
$sessionId = '123';
|
||||||
$this->session->init();
|
$this->session->setCaptchaHash($sessionId, ['phrase' => 'abc']);
|
||||||
$this->session->setCaptchaHash(['phrase' => 'abc']);
|
|
||||||
try {
|
try {
|
||||||
$this->testee->validate(['captcha' => '123']);
|
$this->testee->validate(['captcha' => 'xyz', 'captcha_session_id' => $sessionId]);
|
||||||
} catch (ValidationError $error) {
|
} catch (ValidationError $error) {
|
||||||
$meta = $error->getMeta();
|
$meta = $error->getMeta();
|
||||||
$this->assertEquals('The characters entered do not match with the previous CAPTCHA.', $meta['error']);
|
$this->assertEquals('The characters entered do not match with the previous CAPTCHA.', $meta['error']);
|
||||||
@@ -48,11 +50,10 @@ class BuiltInCaptchaValidatorTest extends \MailPoetTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function testThrowsErrorWhenCaptchaHasTimedOut() {
|
public function testThrowsErrorWhenCaptchaHasTimedOut() {
|
||||||
|
$sessionId = '123';
|
||||||
$this->session->init();
|
$this->session->setCaptchaHash($sessionId, ['phrase' => null]);
|
||||||
$this->session->setCaptchaHash(['phrase' => null]);
|
|
||||||
try {
|
try {
|
||||||
$this->testee->validate(['captcha' => '123']);
|
$this->testee->validate(['captcha' => 'xyz', 'captcha_session_id' => $sessionId]);
|
||||||
} catch (ValidationError $error) {
|
} catch (ValidationError $error) {
|
||||||
$meta = $error->getMeta();
|
$meta = $error->getMeta();
|
||||||
$this->assertEquals('Please regenerate the CAPTCHA.', $meta['error']);
|
$this->assertEquals('Please regenerate the CAPTCHA.', $meta['error']);
|
||||||
@@ -61,10 +62,9 @@ class BuiltInCaptchaValidatorTest extends \MailPoetTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function testReturnsTrueWhenCaptchaIsSolved() {
|
public function testReturnsTrueWhenCaptchaIsSolved() {
|
||||||
|
$sessionId = '123';
|
||||||
$this->session->init();
|
$this->session->setCaptchaHash($sessionId, ['phrase' => 'abc']);
|
||||||
$this->session->setCaptchaHash(['phrase' => 'abc']);
|
$this->assertTrue($this->testee->validate(['captcha' => 'abc', 'captcha_session_id' => $sessionId]));
|
||||||
$this->assertTrue($this->testee->validate(['captcha' => 'abc']));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItRequiresCaptchaForFirstSubscription() {
|
public function testItRequiresCaptchaForFirstSubscription() {
|
||||||
|
@@ -9,7 +9,6 @@ use MailPoet\Subscription\CaptchaFormRenderer;
|
|||||||
|
|
||||||
class CaptchaFormRendererTest extends \MailPoetTest {
|
class CaptchaFormRendererTest extends \MailPoetTest {
|
||||||
public function testCaptchaSubmitTextIsConfigurable() {
|
public function testCaptchaSubmitTextIsConfigurable() {
|
||||||
|
|
||||||
$expectedLabel = 'EXPECTED_LABEL';
|
$expectedLabel = 'EXPECTED_LABEL';
|
||||||
$formRepository = $this->diContainer->get(FormsRepository::class);
|
$formRepository = $this->diContainer->get(FormsRepository::class);
|
||||||
$form = new FormEntity('captcha-render-test-form');
|
$form = new FormEntity('captcha-render-test-form');
|
||||||
@@ -31,17 +30,17 @@ class CaptchaFormRendererTest extends \MailPoetTest {
|
|||||||
$form->setId(1);
|
$form->setId(1);
|
||||||
$formRepository->persist($form);
|
$formRepository->persist($form);
|
||||||
$formRepository->flush();
|
$formRepository->flush();
|
||||||
|
|
||||||
|
$sessionId = '123';
|
||||||
$captchaSession = $this->diContainer->get(CaptchaSession::class);
|
$captchaSession = $this->diContainer->get(CaptchaSession::class);
|
||||||
$captchaSession->init();
|
$captchaSession->setFormData($sessionId, ['form_id' => $form->getId()]);
|
||||||
$captchaSession->setFormData(['form_id' => $form->getId()]);
|
|
||||||
|
|
||||||
$testee = $this->diContainer->get(CaptchaFormRenderer::class);
|
$testee = $this->diContainer->get(CaptchaFormRenderer::class);
|
||||||
$result = $testee->getCaptchaPageContent($captchaSession->getId());
|
$result = $testee->getCaptchaPageContent($sessionId);
|
||||||
$this->assertStringContainsString('value="' . $expectedLabel . '"', $result);
|
$this->assertStringContainsString('value="' . $expectedLabel . '"', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCaptchaSubmitTextHasDefault() {
|
public function testCaptchaSubmitTextHasDefault() {
|
||||||
|
|
||||||
$formRepository = $this->diContainer->get(FormsRepository::class);
|
$formRepository = $this->diContainer->get(FormsRepository::class);
|
||||||
$form = new FormEntity('captcha-render-test-form');
|
$form = new FormEntity('captcha-render-test-form');
|
||||||
$form->setBody([
|
$form->setBody([
|
||||||
@@ -62,12 +61,13 @@ class CaptchaFormRendererTest extends \MailPoetTest {
|
|||||||
$form->setId(1);
|
$form->setId(1);
|
||||||
$formRepository->persist($form);
|
$formRepository->persist($form);
|
||||||
$formRepository->flush();
|
$formRepository->flush();
|
||||||
|
|
||||||
|
$sessionId = '123';
|
||||||
$captchaSession = $this->diContainer->get(CaptchaSession::class);
|
$captchaSession = $this->diContainer->get(CaptchaSession::class);
|
||||||
$captchaSession->init();
|
$captchaSession->setFormData($sessionId, ['form_id' => $form->getId()]);
|
||||||
$captchaSession->setFormData(['form_id' => $form->getId()]);
|
|
||||||
|
|
||||||
$testee = $this->diContainer->get(CaptchaFormRenderer::class);
|
$testee = $this->diContainer->get(CaptchaFormRenderer::class);
|
||||||
$result = $testee->getCaptchaPageContent($captchaSession->getId());
|
$result = $testee->getCaptchaPageContent($sessionId);
|
||||||
$this->assertStringContainsString('value="Subscribe"', $result);
|
$this->assertStringContainsString('value="Subscribe"', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,32 +7,36 @@ use MailPoetVendor\Gregwar\Captcha\PhraseBuilder;
|
|||||||
|
|
||||||
class CaptchaPhraseTest extends \MailPoetUnitTest {
|
class CaptchaPhraseTest extends \MailPoetUnitTest {
|
||||||
public function testItCreatesPhrase(): void {
|
public function testItCreatesPhrase(): void {
|
||||||
|
$expectedSessionId = '123';
|
||||||
$expectedPhrase = 'abc';
|
$expectedPhrase = 'abc';
|
||||||
|
|
||||||
$session = $this->make(CaptchaSession::class, [
|
$session = $this->make(CaptchaSession::class, [
|
||||||
'setCaptchaHash' => Stub\Expected::once(function ($data) use ($expectedPhrase) {
|
'setCaptchaHash' => Stub\Expected::once(function ($sessionId, $data) use ($expectedSessionId, $expectedPhrase) {
|
||||||
|
$this->assertSame($expectedSessionId, $sessionId);
|
||||||
$this->assertSame($expectedPhrase, $data['phrase']);
|
$this->assertSame($expectedPhrase, $data['phrase']);
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
$phraseBuilder = $this->make(PhraseBuilder::class, ['build' => $expectedPhrase]);
|
$phraseBuilder = $this->make(PhraseBuilder::class, ['build' => $expectedPhrase]);
|
||||||
|
|
||||||
$captchaPhrase = new CaptchaPhrase($session, $phraseBuilder);
|
$captchaPhrase = new CaptchaPhrase($session, $phraseBuilder);
|
||||||
$phrase = $captchaPhrase->createPhrase('123');
|
$phrase = $captchaPhrase->createPhrase($expectedSessionId);
|
||||||
$this->assertSame($expectedPhrase, $phrase);
|
$this->assertSame($expectedPhrase, $phrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItReturnsPhrase(): void {
|
public function testItReturnsPhrase(): void {
|
||||||
|
$expectedSessionId = '123';
|
||||||
$expectedPhrase = 'abc';
|
$expectedPhrase = 'abc';
|
||||||
|
|
||||||
$session = $this->make(CaptchaSession::class, [
|
$session = $this->make(CaptchaSession::class, [
|
||||||
'getCaptchaHash' => Stub\Expected::once(function () use ($expectedPhrase) {
|
'getCaptchaHash' => Stub\Expected::once(function ($sessionId) use ($expectedSessionId, $expectedPhrase) {
|
||||||
|
$this->assertSame($expectedSessionId, $sessionId);
|
||||||
return ['phrase' => $expectedPhrase];
|
return ['phrase' => $expectedPhrase];
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
$phraseBuilder = $this->make(PhraseBuilder::class, ['build' => $expectedPhrase]);
|
$phraseBuilder = $this->make(PhraseBuilder::class, ['build' => $expectedPhrase]);
|
||||||
|
|
||||||
$captchaPhrase = new CaptchaPhrase($session, $phraseBuilder);
|
$captchaPhrase = new CaptchaPhrase($session, $phraseBuilder);
|
||||||
$phrase = $captchaPhrase->getPhrase('123');
|
$phrase = $captchaPhrase->getPhrase($expectedSessionId);
|
||||||
$this->assertSame($expectedPhrase, $phrase);
|
$this->assertSame($expectedPhrase, $phrase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,13 +44,11 @@ class BuiltInCaptchaValidatorTest extends \MailPoetUnitTest {
|
|||||||
],
|
],
|
||||||
$this
|
$this
|
||||||
);
|
);
|
||||||
$captchaSession = Stub::makeEmpty(CaptchaSession::class);
|
|
||||||
$subscriberIpRepository = Stub::makeEmpty(SubscriberIPsRepository::class);
|
$subscriberIpRepository = Stub::makeEmpty(SubscriberIPsRepository::class);
|
||||||
$subscriberRepository = Stub::makeEmpty(SubscribersRepository::class);
|
$subscriberRepository = Stub::makeEmpty(SubscribersRepository::class);
|
||||||
$testee = new BuiltInCaptchaValidator(
|
$testee = new BuiltInCaptchaValidator(
|
||||||
$subscriptionUrlFactory,
|
$subscriptionUrlFactory,
|
||||||
$captchaPhrase,
|
$captchaPhrase,
|
||||||
$captchaSession,
|
|
||||||
$this->wp,
|
$this->wp,
|
||||||
$subscriberIpRepository,
|
$subscriberIpRepository,
|
||||||
$subscriberRepository
|
$subscriberRepository
|
||||||
@@ -58,6 +56,7 @@ class BuiltInCaptchaValidatorTest extends \MailPoetUnitTest {
|
|||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'captcha' => $phrase,
|
'captcha' => $phrase,
|
||||||
|
'captcha_session_id' => '123',
|
||||||
];
|
];
|
||||||
verify($testee->validate($data))->true();
|
verify($testee->validate($data))->true();
|
||||||
|
|
||||||
@@ -76,14 +75,12 @@ class BuiltInCaptchaValidatorTest extends \MailPoetUnitTest {
|
|||||||
],
|
],
|
||||||
$this
|
$this
|
||||||
);
|
);
|
||||||
$captchaSession = Stub::makeEmpty(CaptchaSession::class);
|
|
||||||
|
|
||||||
$subscriberIpRepository = Stub::makeEmpty(SubscriberIPsRepository::class);
|
$subscriberIpRepository = Stub::makeEmpty(SubscriberIPsRepository::class);
|
||||||
$subscriberRepository = Stub::makeEmpty(SubscribersRepository::class);
|
$subscriberRepository = Stub::makeEmpty(SubscribersRepository::class);
|
||||||
$testee = new BuiltInCaptchaValidator(
|
$testee = new BuiltInCaptchaValidator(
|
||||||
$subscriptionUrlFactory,
|
$subscriptionUrlFactory,
|
||||||
$captchaPhrase,
|
$captchaPhrase,
|
||||||
$captchaSession,
|
|
||||||
$wp,
|
$wp,
|
||||||
$subscriberIpRepository,
|
$subscriberIpRepository,
|
||||||
$subscriberRepository
|
$subscriberRepository
|
||||||
@@ -91,6 +88,7 @@ class BuiltInCaptchaValidatorTest extends \MailPoetUnitTest {
|
|||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'captcha' => $phrase,
|
'captcha' => $phrase,
|
||||||
|
'captcha_session_id' => '123',
|
||||||
];
|
];
|
||||||
verify($testee->validate($data))->true();
|
verify($testee->validate($data))->true();
|
||||||
}
|
}
|
||||||
@@ -186,14 +184,14 @@ class BuiltInCaptchaValidatorTest extends \MailPoetUnitTest {
|
|||||||
$testee = new BuiltInCaptchaValidator(
|
$testee = new BuiltInCaptchaValidator(
|
||||||
$subscriptionUrlFactory,
|
$subscriptionUrlFactory,
|
||||||
$captchaPhrase,
|
$captchaPhrase,
|
||||||
$captchaSession,
|
|
||||||
$wp,
|
$wp,
|
||||||
$subscriberIpRepository,
|
$subscriberIpRepository,
|
||||||
$subscriberRepository
|
$subscriberRepository
|
||||||
);
|
);
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'captcha' => $phrase,
|
'captcha' => $phrase,
|
||||||
|
'captcha_session_id' => '123',
|
||||||
];
|
];
|
||||||
verify($testee->validate($data))->true();
|
verify($testee->validate($data))->true();
|
||||||
|
|
||||||
@@ -223,7 +221,6 @@ class BuiltInCaptchaValidatorTest extends \MailPoetUnitTest {
|
|||||||
$testee = new BuiltInCaptchaValidator(
|
$testee = new BuiltInCaptchaValidator(
|
||||||
$subscriptionUrlFactory,
|
$subscriptionUrlFactory,
|
||||||
$captchaPhrase,
|
$captchaPhrase,
|
||||||
$captchaSession,
|
|
||||||
$this->wp,
|
$this->wp,
|
||||||
$subscriberIpRepository,
|
$subscriberIpRepository,
|
||||||
$subscriberRepository
|
$subscriberRepository
|
||||||
@@ -231,6 +228,7 @@ class BuiltInCaptchaValidatorTest extends \MailPoetUnitTest {
|
|||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'captcha' => $phrase,
|
'captcha' => $phrase,
|
||||||
|
'captcha_session_id' => '123',
|
||||||
];
|
];
|
||||||
$error = null;
|
$error = null;
|
||||||
try {
|
try {
|
||||||
@@ -254,13 +252,11 @@ class BuiltInCaptchaValidatorTest extends \MailPoetUnitTest {
|
|||||||
],
|
],
|
||||||
$this
|
$this
|
||||||
);
|
);
|
||||||
$captchaSession = Stub::makeEmpty(CaptchaSession::class);
|
|
||||||
$subscriberIpRepository = Stub::makeEmpty(SubscriberIPsRepository::class);
|
$subscriberIpRepository = Stub::makeEmpty(SubscriberIPsRepository::class);
|
||||||
$subscriberRepository = Stub::makeEmpty(SubscribersRepository::class);
|
$subscriberRepository = Stub::makeEmpty(SubscribersRepository::class);
|
||||||
$testee = new BuiltInCaptchaValidator(
|
$testee = new BuiltInCaptchaValidator(
|
||||||
$subscriptionUrlFactory,
|
$subscriptionUrlFactory,
|
||||||
$captchaPhrase,
|
$captchaPhrase,
|
||||||
$captchaSession,
|
|
||||||
$this->wp,
|
$this->wp,
|
||||||
$subscriberIpRepository,
|
$subscriberIpRepository,
|
||||||
$subscriberRepository
|
$subscriberRepository
|
||||||
@@ -268,6 +264,7 @@ class BuiltInCaptchaValidatorTest extends \MailPoetUnitTest {
|
|||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'captcha' => $phrase,
|
'captcha' => $phrase,
|
||||||
|
'captcha_session_id' => '123',
|
||||||
];
|
];
|
||||||
$error = null;
|
$error = null;
|
||||||
try {
|
try {
|
||||||
@@ -297,13 +294,11 @@ class BuiltInCaptchaValidatorTest extends \MailPoetUnitTest {
|
|||||||
],
|
],
|
||||||
$this
|
$this
|
||||||
);
|
);
|
||||||
$captchaSession = Stub::makeEmpty(CaptchaSession::class);
|
|
||||||
$subscriberIpRepository = Stub::makeEmpty(SubscriberIPsRepository::class);
|
$subscriberIpRepository = Stub::makeEmpty(SubscriberIPsRepository::class);
|
||||||
$subscriberRepository = Stub::makeEmpty(SubscribersRepository::class);
|
$subscriberRepository = Stub::makeEmpty(SubscribersRepository::class);
|
||||||
$testee = new BuiltInCaptchaValidator(
|
$testee = new BuiltInCaptchaValidator(
|
||||||
$subscriptionUrlFactory,
|
$subscriptionUrlFactory,
|
||||||
$captchaPhrase,
|
$captchaPhrase,
|
||||||
$captchaSession,
|
|
||||||
$this->wp,
|
$this->wp,
|
||||||
$subscriberIpRepository,
|
$subscriberIpRepository,
|
||||||
$subscriberRepository
|
$subscriberRepository
|
||||||
@@ -311,6 +306,7 @@ class BuiltInCaptchaValidatorTest extends \MailPoetUnitTest {
|
|||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'captcha' => '',
|
'captcha' => '',
|
||||||
|
'captcha_session_id' => '123',
|
||||||
];
|
];
|
||||||
$error = null;
|
$error = null;
|
||||||
try {
|
try {
|
||||||
|
Reference in New Issue
Block a user