cleanup(); $this->scheduledTasksRepository = $this->diContainer->get(ScheduledTasksRepository::class); $this->segmentsRepository = $this->diContainer->get(SegmentsRepository::class); $this->subscribersRepository = $this->diContainer->get(SubscribersRepository::class); $this->action = $this->diContainer->get(SendEmailAction::class); $this->subscriberSubject = $this->diContainer->get(SubscriberSubject::class); $this->segmentSubject = $this->diContainer->get(SegmentSubject::class); $this->workflow = new Workflow('test-workflow', [], new \WP_User()); } public function testItReturnsRequiredSubjects() { $this->assertSame(['mailpoet:segment', 'mailpoet:subscriber'], $this->action->getSubjectKeys()); } public function testItIsNotValidIfStepHasNoEmail(): void { $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', [], []); $this->expectException(ValidationException::class); $this->expectExceptionMessage("Automation email with ID '' not found."); $this->action->validate(new StepValidationArgs($this->workflow, $step, [])); } public function testItRequiresAutomationEmailType(): void { $newsletter = (new Newsletter())->withPostNotificationsType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', ['email_id' => $newsletter->getId()], []); $this->expectExceptionMessage("Automation email with ID '{$newsletter->getId()}' not found."); $this->action->validate(new StepValidationArgs($this->workflow, $step, [])); $this->action->validate(new StepValidationArgs($this->workflow, $step, [])); } public function testHappyPath() { $segment = (new Segment())->create(); $subscriber = (new Subscriber()) ->withStatus(SubscriberEntity::STATUS_SUBSCRIBED) ->withSegments([$segment]) ->create(); $subjects = $this->getSubjectData($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', ['email_id' => $email->getId()], []); $workflow = new Workflow('some-workflow', [$step->getId() => $step], new \WP_User()); $run = new WorkflowRun(1, 1, 'trigger-key', $subjects); $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(0); $this->action->run(new StepRunArgs($workflow, $run, $step, $this->getSubjectEntries($subjects))); $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(1); } public function testItDoesNotScheduleDuplicates(): void { $segment = (new Segment())->create(); $subscriber = (new Subscriber()) ->withStatus(SubscriberEntity::STATUS_SUBSCRIBED) ->withSegments([$segment]) ->create(); $subjects = $this->getSubjectData($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', ['email_id' => $email->getId()], []); $workflow = new Workflow('some-workflow', [$step->getId() => $step], new \WP_User()); $run = new WorkflowRun(1, 1, 'trigger-key', $subjects); $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(0); $action = ContainerWrapper::getInstance()->get(SendEmailAction::class); $action->run(new StepRunArgs($workflow, $run, $step, $this->getSubjectEntries($subjects))); $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(1); try { $action->run(new StepRunArgs($workflow, $run, $step, $this->getSubjectEntries($subjects))); } catch (InvalidStateException $exception) { // The exception itself isn't as important as the outcome } $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(1); } public function testNothingScheduledIfSegmentDeleted(): void { $segment = (new Segment())->create(); $subscriber = (new Subscriber()) ->withStatus(SubscriberEntity::STATUS_SUBSCRIBED) ->withSegments([$segment]) ->create(); $subjects = $this->getSubjectData($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', ['email_id' => $email->getId()], []); $workflow = new Workflow('some-workflow', [$step->getId() => $step], new \WP_User()); $run = new WorkflowRun(1, 1, 'trigger-key', $subjects); $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(0); $this->segmentsRepository->bulkDelete([$segment->getId()]); $action = ContainerWrapper::getInstance()->get(SendEmailAction::class); try { $action->run(new StepRunArgs($workflow, $run, $step, $this->getSubjectEntries($subjects))); } catch (Exception $exception) { // The exception itself isn't as important as the outcome } $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(0); } public function testNothingScheduledIfSubscriberDeleted(): void { $segment = (new Segment())->create(); $subscriber = (new Subscriber()) ->withStatus(SubscriberEntity::STATUS_SUBSCRIBED) ->withSegments([$segment]) ->create(); $subjects = $this->getSubjectData($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', ['email_id' => $email->getId()], []); $workflow = new Workflow('some-workflow', [$step->getId() => $step], new \WP_User()); $run = new WorkflowRun(1, 1, 'trigger-key', $subjects); $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(0); $this->subscribersRepository->bulkDelete([$subscriber->getId()]); $action = ContainerWrapper::getInstance()->get(SendEmailAction::class); try { $action->run(new StepRunArgs($workflow, $run, $step, $this->getSubjectEntries($subjects))); } catch (Exception $exception) { // The exception itself isn't as important as the outcome } $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(0); } public function testNothingScheduledIfSubscriberIsNotGloballySubscribed(): void { $segment = (new Segment())->create(); $otherStatuses = [ SubscriberEntity::STATUS_UNCONFIRMED, SubscriberEntity::STATUS_INACTIVE, SubscriberEntity::STATUS_BOUNCED, SubscriberEntity::STATUS_UNSUBSCRIBED, ]; foreach ($otherStatuses as $status) { $subscriber = (new Subscriber()) ->withStatus($status) ->withSegments([$segment]) ->create(); $subjects = $this->getSubjectData($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', ['email_id' => $email->getId()], []); $workflow = new Workflow('some-workflow', [$step->getId() => $step], new \WP_User()); $run = new WorkflowRun(1, 1, 'trigger-key', $subjects); $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(0); $this->subscribersRepository->bulkDelete([$subscriber->getId()]); $action = ContainerWrapper::getInstance()->get(SendEmailAction::class); try { $action->run(new StepRunArgs($workflow, $run, $step, $this->getSubjectEntries($subjects))); } catch (Exception $exception) { // The exception itself isn't as important as the outcome } $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(0); } } public function testNothingScheduledIfSubscriberNotSubscribedToSegment(): void { $segment = (new Segment())->create(); $subscriber = (new Subscriber()) ->withStatus(SubscriberEntity::STATUS_SUBSCRIBED) ->create(); $subjects = $this->getSubjectData($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', ['email_id' => $email->getId()], []); $workflow = new Workflow('some-workflow', [$step->getId() => $step], new \WP_User()); $run = new WorkflowRun(1, 1, 'trigger-key', $subjects); $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(0); $action = ContainerWrapper::getInstance()->get(SendEmailAction::class); try { $action->run(new StepRunArgs($workflow, $run, $step, $this->getSubjectEntries($subjects))); } catch (Exception $exception) { // The exception itself isn't as important as the outcome } $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(0); } private function getSubjects(): array { return [ $this->segmentSubject, $this->subscriberSubject, ]; } private function getSubjectData(SubscriberEntity $subscriber, SegmentEntity $segment): array { return [ new Subject('mailpoet:segment', ['segment_id' => $segment->getId()]), new Subject('mailpoet:subscriber', ['subscriber_id'=> $subscriber->getId()]), ]; } private function getSubjectEntries(array $subjects): array { $segmentData = array_filter($subjects, function (Subject $subject) { return $subject->getKey() === 'mailpoet:segment'; }); $subscriberData = array_filter($subjects, function (Subject $subject) { return $subject->getKey() === 'mailpoet:subscriber'; }); return [ new SubjectEntry($this->segmentSubject, reset($segmentData)), new SubjectEntry($this->subscriberSubject, reset($subscriberData)), ]; } public function _after() { parent::_after(); $this->cleanup(); } private function cleanup() { $this->truncateEntity(NewsletterEntity::class); $this->truncateEntity(SubscriberEntity::class); $this->truncateEntity(SegmentEntity::class); $this->truncateEntity(SubscriberSegmentEntity::class); $this->truncateEntity(ScheduledTaskEntity::class); $this->truncateEntity(ScheduledTaskSubscriberEntity::class); $this->truncateEntity(SendingQueueEntity::class); } }