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->email = (new Newsletter())->withAutomationType()->create(); $this->step = new Step('step-id', Step::TYPE_ACTION, 'step-key', null, ['email_id' => $this->email->getId()]); $this->workflow = new Workflow('test-workflow', [], new \WP_User()); } public function testItKnowsWhenItHasAllRequiredSubjects() { expect($this->action->isValid([], $this->step, $this->workflow))->false(); expect($this->action->isValid($this->getSubjects(), $this->step, $this->workflow))->true(); } public function testItRequiresASubscriberSubject() { expect($this->action->isValid([$this->segmentSubject], $this->step, $this->workflow))->false(); } public function testItRequiresASegmentSubject() { expect($this->action->isValid([$this->subscriberSubject], $this->step, $this->workflow))->false(); } public function testItIsNotValidIfStepHasNoEmail(): void { $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', null, []); expect($this->action->isValid($this->getSubjects(), $step, $this->workflow))->false(); } public function testItRequiresAutomationEmailType(): void { $newsletter = (new Newsletter())->withPostNotificationsType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', null, ['email_id' => $newsletter->getId()]); expect($this->action->isValid($this->getSubjects(), $step, $this->workflow))->false(); } public function testHappyPath() { $segment = (new Segment())->create(); $subscriber = (new Subscriber()) ->withStatus(SubscriberEntity::STATUS_SUBSCRIBED) ->withSegments([$segment]) ->create(); $subjects = $this->getLoadedSubjects($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', null, ['email_id' => $email->getId()]); $workflow = new Workflow('some-workflow', [$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($workflow, $run, $step); $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->getLoadedSubjects($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', null, ['email_id' => $email->getId()]); $workflow = new Workflow('some-workflow', [$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($workflow, $run, $step); $scheduled = $this->scheduledTasksRepository->findByNewsletterAndSubscriberId($email, (int)$subscriber->getId()); expect($scheduled)->count(1); try { $action->run($workflow, $run, $step); } 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->getLoadedSubjects($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', null, ['email_id' => $email->getId()]); $workflow = new Workflow('some-workflow', [$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($workflow, $run, $step); } 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->getLoadedSubjects($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', null, ['email_id' => $email->getId()]); $workflow = new Workflow('some-workflow', [$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($workflow, $run, $step); } 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->getLoadedSubjects($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', null, ['email_id' => $email->getId()]); $workflow = new Workflow('some-workflow', [$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($workflow, $run, $step); } 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->getLoadedSubjects($subscriber, $segment); $email = (new Newsletter())->withAutomationType()->create(); $step = new Step('step-id', Step::TYPE_ACTION, 'step-key', null, ['email_id' => $email->getId()]); $workflow = new Workflow('some-workflow', [$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($workflow, $run, $step); } 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 getLoadedSubscriberSubject(SubscriberEntity $subscriber): SubscriberSubject { $subscriberSubject = $this->diContainer->get(SubscriberSubject::class); $subscriberSubject->load(['subscriber_id' => $subscriber->getId()]); return $subscriberSubject; } private function getLoadedSegmentSubject(SegmentEntity $segment): SegmentSubject { $segmentSubject = $this->diContainer->get(SegmentSubject::class); $segmentSubject->load(['segment_id' => $segment->getId()]); return $segmentSubject; } private function getSubjects(): array { return [ $this->segmentSubject, $this->subscriberSubject, ]; } private function getLoadedSubjects(SubscriberEntity $subscriber, SegmentEntity $segment): array { return [ $this->getLoadedSubscriberSubject($subscriber), $this->getLoadedSegmentSubject($segment), ]; } 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); } }