newsletterFactory = new NewsletterFactory(); $this->newsletterOptionFactory = new NewsletterOptionFactory(); $this->scheduledTasksRepository = $this->diContainer->get(ScheduledTasksRepository::class); $this->segmentsRepository = $this->diContainer->get(SegmentsRepository::class); $this->sendingQueueRepository = $this->diContainer->get(SendingQueuesRepository::class); $this->wooCommerceHelper = $this->diContainer->get(Helper::class); WPFunctions::get()->removeAllFilters('mailpoet_newsletter_shortcode'); } public function testItGetsEventDetails() { $event = new FirstPurchase(); $result = $event->getEventDetails(); verify($result)->notEmpty(); verify($result['slug'])->equals(FirstPurchase::SLUG); } public function testDateShortcodeHandlerReturnsShortcodeWhenItCannotDetectProperShortcode() { $event = new FirstPurchase(); $shortcode = 'wrong shortcode'; $result = $event->handleOrderDateShortcode($shortcode, true, true, true); verify($result)->equals($shortcode); } public function testDateShortcodeHandlerReturnsShortcodeWhenQueueIsMissing() { $event = new FirstPurchase(); $shortcode = FirstPurchase::ORDER_DATE_SHORTCODE; WPFunctions::set(Stub::make(new WPFunctions, [ 'dateI18n' => 'success', ])); $result = $event->handleOrderDateShortcode($shortcode, true, true, false); verify($result)->equals('success'); } public function testDateShortcodeHandlerReturnsCurrentDateWhenDateIsMissingInQueueMeta() { $event = new FirstPurchase(); $shortcode = FirstPurchase::ORDER_DATE_SHORTCODE; $queue = $this->createSendingQueue($this->newsletterFactory->create()); WPFunctions::set(Stub::make(new WPFunctions, [ 'dateI18n' => 'success', ])); $result = $event->handleOrderDateShortcode($shortcode, true, true, $queue); verify($result)->equals('success'); } public function testDateShortcodeHandlerReturnsSystemFormattedDate() { $event = new FirstPurchase(); $shortcode = FirstPurchase::ORDER_DATE_SHORTCODE; $queue = $this->createSendingQueue($this->newsletterFactory->create()); WPFunctions::set(Stub::make(new WPFunctions, [ 'dateI18n' => 'success', ])); $result = $event->handleOrderDateShortcode($shortcode, true, true, $queue); verify($result)->equals('success'); } public function testOrderAmountShortcodeHandlerReturnsShortcodeWhenItCannotDetectProperShortcode() { $event = new FirstPurchase(); $shortcode = 'wrong shortcode'; $result = $event->handleOrderTotalShortcode($shortcode, true, true, true); verify($result)->equals($shortcode); } public function testOrderAmountShortcodeHandlerReturnsFormattedZeroValueWhenQueueIsMissing() { $helper = Stub::make(WCHelper::class, [ 'wcPrice' => function($price) { return $price; }, ]); $event = new FirstPurchase($helper); $shortcode = FirstPurchase::ORDER_TOTAL_SHORTCODE; $result = $event->handleOrderTotalShortcode($shortcode, true, true, false); verify($result)->equals(0); } public function testOrderAmountShortcodeHandlerReturnsFormattedZeroValueWhenOrderAmountIsMissingInQueueMeta() { $helper = Stub::make(WCHelper::class, [ 'wcPrice' => function($price) { return $price; }, ]); $event = new FirstPurchase($helper); $shortcode = FirstPurchase::ORDER_TOTAL_SHORTCODE; $queue = $this->createSendingQueue($this->newsletterFactory->create()); $result = $event->handleOrderTotalShortcode($shortcode, true, true, $queue); verify($result)->equals(0); } public function testOrderAmountShortcodeHandlerReturnsFormattedPrice() { $helper = Stub::make(WCHelper::class, [ 'wcPrice' => function($price) { return $price; }, ]); $event = new FirstPurchase($helper); $shortcode = FirstPurchase::ORDER_TOTAL_SHORTCODE; $queue = $this->createSendingQueue($this->newsletterFactory->create(), ['order_amount' => 15]); $result = $event->handleOrderTotalShortcode($shortcode, true, true, $queue); verify($result)->equals(15); } public function testItDoesNotScheduleEmailWhenOrderDetailsAreNotAvailable() { $helper = Stub::make(WCHelper::class, [ 'wcGetOrder' => false, ]); $event = new FirstPurchase($helper); $result = $event->scheduleEmailWhenOrderIsPlaced(12); verify($result)->empty(); } public function testItDoesNotScheduleEmailWhenCustomerEmailIsEmpty() { $orderDetails = Stub::make( new OrderDetails(), [ 'get_billing_email' => Expected::once(), ], $this ); $helper = Stub::make(WCHelper::class, [ 'wcGetOrder' => $orderDetails, ]); $event = new FirstPurchase($helper); $result = $event->scheduleEmailWhenOrderIsPlaced(12); verify($result)->empty(); } public function testItDoesNotScheduleEmailWhenItIsNotCustomersFirstPurchase() { $orderDetails = Stub::make(new OrderDetails(), ['get_billing_email' => 'test@example.com']); $helper = Stub::make(WCHelper::class, [ 'wcGetOrder' => $orderDetails, ]); $event = $this->construct(FirstPurchase::class, [$helper], [ 'getCustomerOrderCount' => 2, ]); $result = $event->scheduleEmailWhenOrderIsPlaced(12); verify($result)->empty(); } public function testItDoesNotScheduleEmailWhenCustomerIsNotAWCSegmentSubscriber() { $dateCreated = new \DateTime('2018-12-12'); $orderDetails = Stub::make( new OrderDetails(), [ 'get_billing_email' => 'test@example.com', 'get_date_created' => Expected::once(function() use ($dateCreated) { return $dateCreated; }), 'get_id' => Expected::once(function() { return 'order_id'; }), ] ); $orderDetails->total = 'order_total'; $helper = Stub::make(WCHelper::class, [ 'wcGetOrder' => $orderDetails, 'wcGetCustomerOrderCount' => 0, ]); $customerEmail = 'test@example.com'; $subscriber = (new SubscriberFactory())->withEmail($customerEmail) ->withIsWooCommerceUser() ->withStatus(SubscriberEntity::STATUS_SUBSCRIBED) ->create(); $event = new FirstPurchase($helper); $result = $event->scheduleEmailWhenOrderIsPlaced(12); verify($result)->empty(); } public function testItScheduleEmailForGuestCustomer() { $newsletter = $this->createWooCommerceEmail(); $customerEmail = 'guest_customer@example.com'; $subscriber = (new SubscriberFactory())->withEmail($customerEmail) ->withIsWooCommerceUser() ->withStatus(SubscriberEntity::STATUS_SUBSCRIBED) ->create(); $subscriberSegment = new SubscriberSegmentEntity( $this->segmentsRepository->getWooCommerceSegment(), $subscriber, SubscriberEntity::STATUS_SUBSCRIBED ); $this->entityManager->persist($subscriberSegment); $this->entityManager->flush(); $this->tester->createWooCommerceOrder(); $order = $this->tester->createWooCommerceOrder(['billing_email' => $customerEmail]); $orderDate = $order->get_date_created(); $this->assertInstanceOf(\WC_DateTime::class, $orderDate); $event = new FirstPurchase($this->wooCommerceHelper); $result = $event->scheduleEmailWhenOrderIsPlaced($order->get_id()); verify($result)->empty(); $sendingQueue = $this->sendingQueueRepository->findOneBy(['newsletter' => $newsletter]); $this->assertInstanceOf(SendingQueueEntity::class, $sendingQueue); $meta = $sendingQueue->getMeta(); verify($meta)->equals([ 'order_amount' => $order->get_total(), 'order_date' => $orderDate->getTimestamp(), 'order_id' => $order->get_id(), ]); } public function testItSchedulesEmailForProcessingOrder() { WPFunctions::get()->removeAllFilters('woocommerce_order_status_processing'); $this->_runTestItSchedulesEmailForState('processing'); } public function testItSchedulesEmailForCompletedOrder() { WPFunctions::get()->removeAllFilters('woocommerce_order_status_completed'); $this->_runTestItSchedulesEmailForState('completed'); } public function testItSchedulesEmailOnlyOnce() { WPFunctions::get()->removeAllFilters('woocommerce_order_status_processing'); WPFunctions::get()->removeAllFilters('woocommerce_order_status_completed'); $orderId = $this->_runTestItSchedulesEmailForState('processing'); $tasksCountBeforeStatusChange = count($this->scheduledTasksRepository->findBy(['type' => SendingQueue::TASK_TYPE])); WPFunctions::get()->doAction('woocommerce_order_status_completed', $orderId); $tasksCountAfterStatusChange = count($this->scheduledTasksRepository->findBy(['type' => SendingQueue::TASK_TYPE])); verify($tasksCountAfterStatusChange)->equals($tasksCountBeforeStatusChange); } public function _runTestItSchedulesEmailForState($orderState) { $newsletter = $this->createWooCommerceEmail(); $customerEmail = 'test@example.com'; $subscriber = (new SubscriberFactory())->withEmail($customerEmail) ->withIsWooCommerceUser() ->withStatus(SubscriberEntity::STATUS_SUBSCRIBED) ->create(); $subscriberSegment = new SubscriberSegmentEntity( $this->segmentsRepository->getWooCommerceSegment(), $subscriber, SubscriberEntity::STATUS_SUBSCRIBED ); $this->entityManager->persist($subscriberSegment); $this->entityManager->flush(); $dateCreated = new \DateTime('2018-12-12'); $helper = Stub::make(WCHelper::class, [ 'wcGetCustomerOrderCount' => 0, 'wcGetOrder' => function($orderId) use ($customerEmail, $dateCreated) { $orderDetails = Stub::construct( new OrderDetails(), [$orderId], [ 'get_billing_email' => $customerEmail, 'get_date_created' => $dateCreated, ] ); $orderDetails->total = 'order_total'; return $orderDetails; }, ]); $event = new FirstPurchase($helper); $event->init(); $orderId = 12; // ensure there are no existing scheduled tasks $scheduledTask = $this->sendingQueueRepository->findOneBy(['newsletter' => $newsletter]); $this->assertNull($scheduledTask); // check the customer doesn't exist yet, so he is eligible for this email WPFunctions::get()->doAction('woocommerce_checkout_posted_data', ['billing_email' => $customerEmail]); // when 'woocommerce_order_status_$order_state' hook is triggered, an email should be scheduled WPFunctions::get()->doAction('woocommerce_order_status_' . $orderState, $orderId); $sendingQueue = $this->sendingQueueRepository->findOneBy(['newsletter' => $newsletter]); $this->assertInstanceOf(SendingQueueEntity::class, $sendingQueue); $meta = $sendingQueue->getMeta(); verify($meta)->equals([ 'order_amount' => 'order_total', 'order_date' => $dateCreated->getTimestamp(), 'order_id' => $orderId, ]); return $orderId; } private function createWooCommerceEmail(): NewsletterEntity { $newsletter = $this->newsletterFactory ->withSubject('WooCommerce') ->withType(NewsletterEntity::TYPE_AUTOMATIC) ->withActiveStatus() ->create(); $this->newsletterOptionFactory->createMultipleOptions($newsletter, [ 'group' => WooCommerce::SLUG, 'event' => FirstPurchase::SLUG, 'afterTimeType' => 'days', 'afterTimeNumber' => 1, 'sendTo' => 'user', ]); return $newsletter; } private function createSendingQueue(NewsletterEntity $newsletter, array $meta = []): SendingQueueEntity { $task = new ScheduledTaskEntity(); $this->entityManager->persist($task); $this->entityManager->flush(); $sendingQueue = new SendingQueueEntity(); $sendingQueue->setNewsletter($newsletter); $sendingQueue->setMeta($meta); $sendingQueue->setTask($task); $this->entityManager->persist($sendingQueue); $this->entityManager->flush(); return $sendingQueue; } }