Files
piratepoet/tests/integration/Cron/Workers/SendingQueue/SendingQueueTest.php
2020-01-14 15:22:42 +01:00

848 lines
32 KiB
PHP

<?php
namespace MailPoet\Test\Cron\Workers\SendingQueue;
use Codeception\Stub;
use Codeception\Stub\Expected;
use Codeception\Util\Fixtures;
use MailPoet\Config\Populator;
use MailPoet\Cron\CronHelper;
use MailPoet\Cron\Workers\SendingQueue\SendingErrorHandler;
use MailPoet\Cron\Workers\SendingQueue\SendingQueue as SendingQueueWorker;
use MailPoet\Cron\Workers\SendingQueue\Tasks\Mailer as MailerTask;
use MailPoet\Cron\Workers\SendingQueue\Tasks\Newsletter as NewsletterTask;
use MailPoet\Cron\Workers\StatsNotifications\Scheduler as StatsNotificationsScheduler;
use MailPoet\DI\ContainerWrapper;
use MailPoet\Entities\NewsletterEntity;
use MailPoet\Features\FeaturesController;
use MailPoet\Logging\LoggerFactory;
use MailPoet\Mailer\MailerLog;
use MailPoet\Models\Newsletter;
use MailPoet\Models\NewsletterLink;
use MailPoet\Models\NewsletterPost;
use MailPoet\Models\NewsletterSegment;
use MailPoet\Models\ScheduledTask;
use MailPoet\Models\ScheduledTaskSubscriber;
use MailPoet\Models\Segment;
use MailPoet\Models\SendingQueue;
use MailPoet\Models\StatisticsNewsletters;
use MailPoet\Models\Subscriber;
use MailPoet\Models\SubscriberSegment;
use MailPoet\Newsletter\Links\Links;
use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\Referrals\ReferralDetector;
use MailPoet\Router\Endpoints\Track;
use MailPoet\Router\Router;
use MailPoet\Settings\SettingsController;
use MailPoet\Settings\SettingsRepository;
use MailPoet\Subscribers\LinkTokens;
use MailPoet\Subscription\Captcha;
use MailPoet\Subscription\SubscriptionUrlFactory;
use MailPoet\Tasks\Sending as SendingTask;
use MailPoet\WP\Functions as WPFunctions;
use MailPoetVendor\Carbon\Carbon;
use MailPoetVendor\Doctrine\ORM\EntityManager;
use MailPoetVendor\Idiorm\ORM;
class SendingQueueTest extends \MailPoetTest {
public $sendingQueueWorker;
public $cronHelper;
public $newsletterLink;
public $queue;
public $newsletterSegment;
public $newsletter;
public $subscriberSegment;
public $segment;
public $subscriber;
/** @var SendingErrorHandler */
private $sendingErrorHandler;
/** @var SettingsController */
private $settings;
/** @var StatsNotificationsScheduler */
private $statsNotificationsWorker;
/** @var LoggerFactory */
private $loggerFactory;
public function _before() {
parent::_before();
$wpUsers = get_users();
wp_set_current_user($wpUsers[0]->ID);
$this->settings = SettingsController::getInstance();
$referralDetector = new ReferralDetector(WPFunctions::get(), $this->settings);
$featuresController = Stub::makeEmpty(FeaturesController::class);
$populator = new Populator($this->settings, WPFunctions::get(), new Captcha, $referralDetector, $featuresController);
$populator->up();
$this->subscriber = Subscriber::create();
$this->subscriber->email = 'john@doe.com';
$this->subscriber->first_name = 'John';
$this->subscriber->last_name = 'Doe';
$this->subscriber->status = Subscriber::STATUS_SUBSCRIBED;
$this->subscriber->source = 'administrator';
$this->subscriber->save();
$this->segment = Segment::create();
$this->segment->name = 'segment';
$this->segment->save();
$this->subscriberSegment = SubscriberSegment::create();
$this->subscriberSegment->subscriber_id = $this->subscriber->id;
$this->subscriberSegment->segment_id = (int)$this->segment->id;
$this->subscriberSegment->save();
$this->newsletter = Newsletter::create();
$this->newsletter->type = Newsletter::TYPE_STANDARD;
$this->newsletter->status = Newsletter::STATUS_ACTIVE;
$this->newsletter->subject = Fixtures::get('newsletter_subject_template');
$this->newsletter->body = Fixtures::get('newsletter_body_template');
$this->newsletter->save();
$this->newsletterSegment = NewsletterSegment::create();
$this->newsletterSegment->newsletter_id = $this->newsletter->id;
$this->newsletterSegment->segment_id = (int)$this->segment->id;
$this->newsletterSegment->save();
$this->queue = SendingTask::create();
$this->queue->newsletter_id = $this->newsletter->id;
$this->queue->setSubscribers([$this->subscriber->id]);
$this->queue->count_total = 1;
$this->queue->save();
$this->newsletterLink = NewsletterLink::create();
$this->newsletterLink->newsletter_id = $this->newsletter->id;
$this->newsletterLink->queue_id = $this->queue->id;
$this->newsletterLink->url = '[link:subscription_unsubscribe_url]';
$this->newsletterLink->hash = 'abcde';
$this->newsletterLink->save();
$this->sendingErrorHandler = new SendingErrorHandler();
$this->statsNotificationsWorker = Stub::makeEmpty(StatsNotificationsScheduler::class);
$this->loggerFactory = LoggerFactory::getInstance();
$this->cronHelper = ContainerWrapper::getInstance()->get(CronHelper::class);
$this->sendingQueueWorker = new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class, ['findOneById' => new NewsletterEntity()]),
$this->cronHelper
);
}
private function getDirectUnsubscribeURL() {
return SubscriptionUrlFactory::getInstance()->getUnsubscribeUrl($this->subscriber);
}
private function getTrackedUnsubscribeURL() {
$linkTokens = new LinkTokens;
$data = Links::createUrlDataObject(
$this->subscriber->id,
$linkTokens->getToken($this->subscriber),
$this->queue->id,
$this->newsletterLink->hash,
false
);
return Router::buildRequest(
Track::ENDPOINT,
Track::ACTION_CLICK,
$data
);
}
public function testItConstructs() {
expect($this->sendingQueueWorker->batch_size)->equals(SendingQueueWorker::BATCH_SIZE);
expect($this->sendingQueueWorker->mailer_task instanceof MailerTask);
expect($this->sendingQueueWorker->newsletter_task instanceof NewsletterTask);
}
public function testItEnforcesExecutionLimitsBeforeQueueProcessing() {
$sendingQueueWorker = Stub::make(
new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class),
$this->cronHelper
),
[
'processQueue' => Expected::never(),
'enforceSendingAndExecutionLimits' => Expected::exactly(1, function() {
throw new \Exception();
}),
], $this);
$sendingQueueWorker->__construct($this->sendingErrorHandler, $this->statsNotificationsWorker, $this->loggerFactory, Stub::makeEmpty(NewslettersRepository::class), $this->cronHelper);
try {
$sendingQueueWorker->process();
self::fail('Execution limits function was not called.');
} catch (\Exception $e) {
// No exception handling needed
}
}
public function testItEnforcesExecutionLimitsAfterSendingWhenQueueStatusIsNotSetToComplete() {
$sendingQueueWorker = Stub::make(
new SendingQueueWorker($this->sendingErrorHandler, $this->statsNotificationsWorker, $this->loggerFactory, Stub::makeEmpty(NewslettersRepository::class), $this->cronHelper),
[
'enforceSendingAndExecutionLimits' => Expected::exactly(1),
], $this);
$sendingQueueWorker->__construct(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class),
$this->cronHelper,
Stub::make(
new MailerTask(),
[
'sendBulk' => null,
]
)
);
$sendingQueueWorker->sendNewsletters(
$this->queue,
$preparedSubscribers = [],
$preparedNewsletters = [],
$preparedSubscribers = [],
$statistics[] = [
'newsletter_id' => 1,
'subscriber_id' => 1,
'queue_id' => $this->queue->id,
],
microtime(true)
);
}
public function testItDoesNotEnforceExecutionLimitsAfterSendingWhenQueueStatusIsSetToComplete() {
// when sending is done and there are no more subscribers to process, continue
// without enforcing execution limits. this allows the newsletter to be marked as sent
// in the process() method and after that execution limits will be enforced
$queue = $this->queue;
$queue->status = SendingQueue::STATUS_COMPLETED;
$sendingQueueWorker = Stub::make(
new SendingQueueWorker($this->sendingErrorHandler, $this->statsNotificationsWorker, $this->loggerFactory, Stub::makeEmpty(NewslettersRepository::class), $this->cronHelper),
[
'enforceSendingAndExecutionLimits' => Expected::never(),
], $this);
$sendingQueueWorker->__construct(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class),
$this->cronHelper,
Stub::make(
new MailerTask(),
[
'sendBulk' => null,
]
)
);
$sendingQueueWorker->sendNewsletters(
$queue,
$preparedSubscribers = [],
$preparedNewsletters = [],
$preparedSubscribers = [],
$statistics[] = [
'newsletter_id' => 1,
'subscriber_id' => 1,
'queue_id' => $queue->id,
],
microtime(true)
);
}
public function testItEnforcesExecutionLimitsAfterQueueProcessing() {
$sendingQueueWorker = Stub::make(
new SendingQueueWorker($this->sendingErrorHandler, $this->statsNotificationsWorker, $this->loggerFactory, Stub::makeEmpty(NewslettersRepository::class), $this->cronHelper),
[
'processQueue' => function() {
// this function returns a queue object
return (object)['status' => null, 'task_id' => 0];
},
'enforceSendingAndExecutionLimits' => Expected::exactly(2),
], $this);
$sendingQueueWorker->__construct($this->sendingErrorHandler, $this->statsNotificationsWorker, $this->loggerFactory, Stub::makeEmpty(NewslettersRepository::class), $this->cronHelper);
$sendingQueueWorker->process();
}
public function testItDeletesQueueWhenNewsletterIsNotFound() {
// queue exists
$queue = SendingQueue::findOne($this->queue->id);
expect($queue)->notEquals(false);
// delete newsletter
Newsletter::findOne($this->newsletter->id)
->delete();
// queue no longer exists
$this->sendingQueueWorker->process();
$queue = SendingQueue::findOne($this->queue->id);
expect($queue)->false();
}
public function testItPassesExtraParametersToMailerWhenTrackingIsDisabled() {
$this->settings->set('tracking.enabled', false);
$directUnsubscribeURL = $this->getDirectUnsubscribeURL();
$sendingQueueWorker = new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class, ['findOneById' => new NewsletterEntity()]),
$this->cronHelper,
Stub::make(
new MailerTask(),
[
'send' => Expected::exactly(1, function($newsletter, $subscriber, $extraParams) use ($directUnsubscribeURL) {
expect(isset($extraParams['unsubscribe_url']))->true();
expect($extraParams['unsubscribe_url'])->equals($directUnsubscribeURL);
expect(isset($extraParams['meta']))->true();
expect($extraParams['meta'])->equals([
'email_type' => 'newsletter',
'subscriber_status' => 'subscribed',
'subscriber_source' => 'administrator',
]);
return true;
}),
],
$this
)
);
$sendingQueueWorker->process();
}
public function testItPassesExtraParametersToMailerWhenTrackingIsEnabled() {
$this->settings->set('tracking.enabled', true);
$trackedUnsubscribeURL = $this->getTrackedUnsubscribeURL();
$sendingQueueWorker = new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class, ['findOneById' => new NewsletterEntity()]),
$this->cronHelper,
Stub::make(
new MailerTask(),
[
'send' => Expected::exactly(1, function($newsletter, $subscriber, $extraParams) use ($trackedUnsubscribeURL) {
expect(isset($extraParams['unsubscribe_url']))->true();
expect($extraParams['unsubscribe_url'])->equals($trackedUnsubscribeURL);
expect(isset($extraParams['meta']))->true();
expect($extraParams['meta'])->equals([
'email_type' => 'newsletter',
'subscriber_status' => 'subscribed',
'subscriber_source' => 'administrator',
]);
return true;
}),
],
$this
)
);
$sendingQueueWorker->process();
}
public function testItCanProcessSubscribersOneByOne() {
$sendingQueueWorker = new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class, ['findOneById' => new NewsletterEntity()]),
$this->cronHelper,
Stub::make(
new MailerTask(),
[
'send' => Expected::exactly(1, function($newsletter, $subscriber, $extraParams) {
// newsletter body should not be empty
expect(!empty($newsletter['body']['html']))->true();
expect(!empty($newsletter['body']['text']))->true();
return true;
}),
],
$this
)
);
$sendingQueueWorker->process();
// newsletter status is set to sent
$updatedNewsletter = Newsletter::findOne($this->newsletter->id);
expect($updatedNewsletter->status)->equals(Newsletter::STATUS_SENT);
// queue status is set to completed
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($this->queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
expect($updatedQueue->status)->equals(SendingQueue::STATUS_COMPLETED);
// queue subscriber processed/to process count is updated
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_UNPROCESSED))
->equals([]);
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_PROCESSED))
->equals([$this->subscriber->id]);
expect($updatedQueue->countTotal)->equals(1);
expect($updatedQueue->countProcessed)->equals(1);
expect($updatedQueue->countToProcess)->equals(0);
// statistics entry should be created
$statistics = StatisticsNewsletters::where('newsletter_id', $this->newsletter->id)
->where('subscriber_id', $this->subscriber->id)
->where('queue_id', $this->queue->id)
->findOne();
expect($statistics)->notEquals(false);
}
public function testItCanProcessSubscribersInBulk() {
$sendingQueueWorker = new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class, ['findOneById' => new NewsletterEntity()]),
$this->cronHelper,
Stub::make(
new MailerTask(),
[
'sendBulk' => Expected::exactly(1, function($newsletter, $subscriber) {
// newsletter body should not be empty
expect(!empty($newsletter[0]['body']['html']))->true();
expect(!empty($newsletter[0]['body']['text']))->true();
return true;
}),
'getProcessingMethod' => Expected::exactly(1, function() {
return 'bulk';
}),
],
$this
)
);
$sendingQueueWorker->process();
// newsletter status is set to sent
$updatedNewsletter = Newsletter::findOne($this->newsletter->id);
expect($updatedNewsletter->status)->equals(Newsletter::STATUS_SENT);
// queue status is set to completed
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($this->queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
expect($updatedQueue->status)->equals(SendingQueue::STATUS_COMPLETED);
// queue subscriber processed/to process count is updated
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_UNPROCESSED))
->equals([]);
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_PROCESSED))
->equals([$this->subscriber->id]);
expect($updatedQueue->countTotal)->equals(1);
expect($updatedQueue->countProcessed)->equals(1);
expect($updatedQueue->countToProcess)->equals(0);
// statistics entry should be created
$statistics = StatisticsNewsletters::where('newsletter_id', $this->newsletter->id)
->where('subscriber_id', $this->subscriber->id)
->where('queue_id', $this->queue->id)
->findOne();
expect($statistics)->notEquals(false);
}
public function testItProcessesStandardNewsletters() {
$sendingQueueWorker = new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class, ['findOneById' => new NewsletterEntity()]),
$this->cronHelper,
Stub::make(
new MailerTask(),
[
'send' => Expected::exactly(1, function($newsletter, $subscriber) {
// newsletter body should not be empty
expect(!empty($newsletter['body']['html']))->true();
expect(!empty($newsletter['body']['text']))->true();
return true;
}),
],
$this
)
);
$sendingQueueWorker->process();
// queue status is set to completed
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($this->queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
expect($updatedQueue->status)->equals(SendingQueue::STATUS_COMPLETED);
// newsletter status is set to sent and sent_at date is populated
$updatedNewsletter = Newsletter::findOne($this->newsletter->id);
expect($updatedNewsletter->status)->equals(Newsletter::STATUS_SENT);
expect($updatedNewsletter->sentAt)->equals($updatedQueue->processedAt);
// queue subscriber processed/to process count is updated
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_UNPROCESSED))
->equals([]);
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_PROCESSED))
->equals([$this->subscriber->id]);
expect($updatedQueue->countTotal)->equals(1);
expect($updatedQueue->countProcessed)->equals(1);
expect($updatedQueue->countToProcess)->equals(0);
// statistics entry should be created
$statistics = StatisticsNewsletters::where('newsletter_id', $this->newsletter->id)
->where('subscriber_id', $this->subscriber->id)
->where('queue_id', $this->queue->id)
->findOne();
expect($statistics)->notEquals(false);
}
public function testItUpdatesUpdateTime() {
$originalUpdated = Carbon::createFromTimestamp(WPFunctions::get()->currentTime('timestamp'))->subHours(5)->toDateTimeString();
$this->queue->scheduled_at = Carbon::createFromTimestamp(WPFunctions::get()->currentTime('timestamp'));
$this->queue->updated_at = $originalUpdated;
$this->queue->save();
$this->newsletter->type = Newsletter::TYPE_WELCOME;
$this->newsletterSegment->delete();
$sendingQueueWorker = new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class),
$this->cronHelper,
Stub::makeEmpty(new MailerTask(), [], $this)
);
$sendingQueueWorker->process();
$newQueue = ScheduledTask::findOne($this->queue->task_id);
expect($newQueue->updatedAt)->notEquals($originalUpdated);
}
public function testItCanProcessWelcomeNewsletters() {
$this->newsletter->type = Newsletter::TYPE_WELCOME;
$this->newsletterSegment->delete();
$sendingQueueWorker = new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class, ['findOneById' => new NewsletterEntity()]),
$this->cronHelper,
Stub::make(
new MailerTask(),
[
'send' => Expected::exactly(1, function($newsletter, $subscriber) {
// newsletter body should not be empty
expect(!empty($newsletter['body']['html']))->true();
expect(!empty($newsletter['body']['text']))->true();
return true;
}),
],
$this
)
);
$sendingQueueWorker->process();
// newsletter status is set to sent
$updatedNewsletter = Newsletter::findOne($this->newsletter->id);
expect($updatedNewsletter->status)->equals(Newsletter::STATUS_SENT);
// queue status is set to completed
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($this->queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
expect($updatedQueue->status)->equals(SendingQueue::STATUS_COMPLETED);
// queue subscriber processed/to process count is updated
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_UNPROCESSED))
->equals([]);
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_PROCESSED))
->equals([$this->subscriber->id]);
expect($updatedQueue->countTotal)->equals(1);
expect($updatedQueue->countProcessed)->equals(1);
expect($updatedQueue->countToProcess)->equals(0);
// statistics entry should be created
$statistics = StatisticsNewsletters::where('newsletter_id', $this->newsletter->id)
->where('subscriber_id', $this->subscriber->id)
->where('queue_id', $this->queue->id)
->findOne();
expect($statistics)->notEquals(false);
}
public function testItPreventsSendingWelcomeEmailWhenSubscriberIsUnsubscribed() {
$this->newsletter->type = Newsletter::TYPE_WELCOME;
$this->subscriber->status = Subscriber::STATUS_UNSUBSCRIBED;
$this->subscriber->save();
$this->newsletterSegment->delete();
$sendingQueueWorker = new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class),
$this->cronHelper,
Stub::make(
new MailerTask(),
[
'send' => Expected::exactly(0),
],
$this
)
);
$sendingQueueWorker->process();
// queue status is set to completed
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($this->queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_PROCESSED))
->equals([]);
expect($updatedQueue->countTotal)->equals(0);
expect($updatedQueue->countProcessed)->equals(0);
expect($updatedQueue->countToProcess)->equals(0);
}
public function testItRemovesNonexistentSubscribersFromProcessingList() {
$queue = $this->queue;
$queue->setSubscribers([
$this->subscriber->id(),
12345645454,
]);
$queue->countTotal = 2;
$queue->save();
$sendingQueueWorker = $this->sendingQueueWorker;
$sendingQueueWorker->mailerTask = Stub::make(
new MailerTask(),
[
'send' => Expected::exactly(1, function() {
return true;
}),
],
$this
);
$sendingQueueWorker->process();
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
// queue subscriber processed/to process count is updated
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_UNPROCESSED))
->equals([]);
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_PROCESSED))
->equals([$this->subscriber->id]);
expect($updatedQueue->countTotal)->equals(1);
expect($updatedQueue->countProcessed)->equals(1);
expect($updatedQueue->countToProcess)->equals(0);
// statistics entry should be created only for 1 subscriber
$statistics = StatisticsNewsletters::findMany();
expect(count($statistics))->equals(1);
}
public function testItUpdatesQueueSubscriberCountWhenNoneOfSubscribersExist() {
$queue = $this->queue;
$queue->setSubscribers([
123,
456,
]);
$queue->countTotal = 2;
$queue->save();
$sendingQueueWorker = $this->sendingQueueWorker;
$sendingQueueWorker->mailerTask = Stub::make(
new MailerTask(),
['send' => true]
);
$sendingQueueWorker->process();
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
// queue subscriber processed/to process count is updated
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_UNPROCESSED))
->equals([]);
expect($updatedQueue->getSubscribers(ScheduledTaskSubscriber::STATUS_PROCESSED))
->equals([]);
expect($updatedQueue->countTotal)->equals(0);
expect($updatedQueue->countProcessed)->equals(0);
expect($updatedQueue->countToProcess)->equals(0);
}
public function testItDoesNotSendToTrashedSubscribers() {
$sendingQueueWorker = $this->sendingQueueWorker;
$sendingQueueWorker->mailerTask = Stub::make(
new MailerTask(),
['send' => true]
);
// newsletter is sent to existing subscriber
$sendingQueueWorker->process();
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($this->queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
expect((int)$updatedQueue->countTotal)->equals(1);
// newsletter is not sent to trashed subscriber
$this->_after();
$this->_before();
$subscriber = $this->subscriber;
$subscriber->deletedAt = Carbon::now();
$subscriber->save();
$sendingQueueWorker->process();
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($this->queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
expect((int)$updatedQueue->countTotal)->equals(0);
}
public function testItDoesNotSendToGloballyUnsubscribedSubscribers() {
$sendingQueueWorker = $this->sendingQueueWorker;
$sendingQueueWorker->mailerTask = Stub::make(
new MailerTask(),
['send' => true]
);
// newsletter is not sent to globally unsubscribed subscriber
$subscriber = $this->subscriber;
$subscriber->status = Subscriber::STATUS_UNSUBSCRIBED;
$subscriber->save();
$sendingQueueWorker->process();
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($this->queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
expect((int)$updatedQueue->countTotal)->equals(0);
}
public function testItDoesNotSendToSubscribersUnsubscribedFromSegments() {
$sendingQueueWorker = $this->sendingQueueWorker;
$sendingQueueWorker->mailerTask = Stub::make(
new MailerTask(),
['send' => true]
);
// newsletter is not sent to subscriber unsubscribed from segment
$subscriberSegment = $this->subscriberSegment;
$subscriberSegment->status = Subscriber::STATUS_UNSUBSCRIBED;
$subscriberSegment->save();
$sendingQueueWorker->process();
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($this->queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
expect((int)$updatedQueue->countTotal)->equals(0);
}
public function testItDoesNotSendToInactiveSubscribers() {
$sendingQueueWorker = $this->sendingQueueWorker;
$sendingQueueWorker->mailerTask = Stub::make(
new MailerTask(),
['send' => true]
);
// newsletter is not sent to inactive subscriber
$subscriber = $this->subscriber;
$subscriber->status = Subscriber::STATUS_INACTIVE;
$subscriber->save();
$sendingQueueWorker->process();
/** @var SendingQueue $updatedQueue */
$updatedQueue = SendingQueue::findOne($this->queue->id);
$updatedQueue = SendingTask::createFromQueue($updatedQueue);
expect((int)$updatedQueue->countTotal)->equals(0);
}
public function testItPausesSendingWhenProcessedSubscriberListCannotBeUpdated() {
$sendingTask = $this->createMock(SendingTask::class);
$sendingTask
->method('updateProcessedSubscribers')
->will($this->returnValue(false));
$sendingTask
->method('__get')
->with('id')
->will($this->returnValue(100));
$sendingQueueWorker = Stub::make(new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class),
$this->cronHelper
));
$sendingQueueWorker->__construct(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class),
$this->cronHelper,
Stub::make(
new MailerTask(),
[
'sendBulk' => true,
]
)
);
try {
$sendingQueueWorker->sendNewsletters(
$sendingTask,
$preparedSubscribers = [],
$preparedNewsletters = [],
$preparedSubscribers = [],
$statistics = [],
microtime(true)
);
$this->fail('Paused sending exception was not thrown.');
} catch (\Exception $e) {
expect($e->getMessage())->equals('Sending has been paused.');
}
$mailerLog = MailerLog::getMailerLog();
expect($mailerLog['status'])->equals(MailerLog::STATUS_PAUSED);
expect($mailerLog['error'])->equals(
[
'operation' => 'processed_list_update',
'error_message' => 'QUEUE-100-PROCESSED-LIST-UPDATE',
]
);
}
public function testItDoesNotUpdateNewsletterHashDuringSending() {
$sendingQueueWorker = new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class, ['findOneById' => new NewsletterEntity()]),
$this->cronHelper,
Stub::make(
new MailerTask(),
[
'send' => Expected::once(),
],
$this
)
);
$sendingQueueWorker->process();
// newsletter is sent and hash remains intact
$updatedNewsletter = Newsletter::findOne($this->newsletter->id);
expect($updatedNewsletter->status)->equals(Newsletter::STATUS_SENT);
expect($updatedNewsletter->hash)->equals($this->newsletter->hash);
}
public function testItAllowsSettingCustomBatchSize() {
$customBatchSizeValue = 10;
$filter = function() use ($customBatchSizeValue) {
return $customBatchSizeValue;
};
$wp = new WPFunctions;
$wp->addFilter('mailpoet_cron_worker_sending_queue_batch_size', $filter);
$sendingQueueWorker = new SendingQueueWorker(
$this->sendingErrorHandler,
$this->statsNotificationsWorker,
$this->loggerFactory,
Stub::makeEmpty(NewslettersRepository::class),
$this->cronHelper
);
expect($sendingQueueWorker->batchSize)->equals($customBatchSizeValue);
$wp->removeFilter('mailpoet_cron_worker_sending_queue_batch_size', $filter);
}
public function _after() {
ORM::raw_execute('TRUNCATE ' . Subscriber::$_table);
ORM::raw_execute('TRUNCATE ' . SubscriberSegment::$_table);
ORM::raw_execute('TRUNCATE ' . ScheduledTask::$_table);
ORM::raw_execute('TRUNCATE ' . ScheduledTaskSubscriber::$_table);
ORM::raw_execute('TRUNCATE ' . Segment::$_table);
ORM::raw_execute('TRUNCATE ' . SendingQueue::$_table);
$this->diContainer->get(SettingsRepository::class)->truncate();
ORM::raw_execute('TRUNCATE ' . Newsletter::$_table);
ORM::raw_execute('TRUNCATE ' . NewsletterLink::$_table);
ORM::raw_execute('TRUNCATE ' . NewsletterPost::$_table);
ORM::raw_execute('TRUNCATE ' . NewsletterSegment::$_table);
ORM::raw_execute('TRUNCATE ' . StatisticsNewsletters::$_table);
}
}