From 37ffcbc8561444cbef586d62a9a3597c76a54ebf Mon Sep 17 00:00:00 2001 From: wxa Date: Thu, 1 Oct 2020 17:57:02 +0300 Subject: [PATCH] Add integration tests [MAILPOET-2979] --- .../WooCommerce/Events/AbandonedCartTest.php | 8 +- .../Newsletter/Blocks/RendererTest.php | 163 +++++++++++++++++- 2 files changed, 169 insertions(+), 2 deletions(-) diff --git a/tests/integration/AutomaticEmails/WooCommerce/Events/AbandonedCartTest.php b/tests/integration/AutomaticEmails/WooCommerce/Events/AbandonedCartTest.php index 467aa0b389..4c071e071a 100644 --- a/tests/integration/AutomaticEmails/WooCommerce/Events/AbandonedCartTest.php +++ b/tests/integration/AutomaticEmails/WooCommerce/Events/AbandonedCartTest.php @@ -61,7 +61,7 @@ class AbandonedCartTest extends \MailPoetTest { WPFunctions::set($this->wp); $this->wooCommerceMock = $this->mockWooCommerceClass(WooCommerce::class, []); - $this->wooCommerceCartMock = $this->mockWooCommerceClass(WC_Cart::class, ['is_empty']); + $this->wooCommerceCartMock = $this->mockWooCommerceClass(WC_Cart::class, ['is_empty', 'get_cart']); $this->wooCommerceMock->cart = $this->wooCommerceCartMock; $this->wooCommerceHelperMock = $this->make(WooCommerceHelper::class, [ 'isWooCommerceActive' => true, @@ -147,6 +147,9 @@ class AbandonedCartTest extends \MailPoetTest { $this->pageVisitTrackerMock->expects($this->once())->method('startTracking'); $this->wooCommerceCartMock->method('is_empty')->willReturn(false); + $this->wooCommerceCartMock->method('get_cart')->willReturn([ + ['product_id' => 123], ['product_id' => 456], // dummy product IDs + ]); $abandonedCartEmail = $this->createAbandonedCartEmail(); $abandonedCartEmail->init(); $abandonedCartEmail->handleCartChange(); @@ -156,6 +159,9 @@ class AbandonedCartTest extends \MailPoetTest { expect($scheduledTasks)->count(1); expect($scheduledTasks[0]->status)->same(ScheduledTask::STATUS_SCHEDULED); expect($scheduledTasks[0]->scheduled_at)->same($expectedTime->format('Y-m-d H:i:s')); + /** @var SendingQueue $sendingQueue */ + $sendingQueue = SendingQueue::where('task_id', $scheduledTasks[0]->id)->findOne(); + expect($sendingQueue->getMeta())->same([AbandonedCart::TASK_META_NAME => [123, 456]]); } public function testItPostponesEmailWhenCartEdited() { diff --git a/tests/integration/Newsletter/Blocks/RendererTest.php b/tests/integration/Newsletter/Blocks/RendererTest.php index b7cca571b3..b1d5ffc87e 100644 --- a/tests/integration/Newsletter/Blocks/RendererTest.php +++ b/tests/integration/Newsletter/Blocks/RendererTest.php @@ -2,10 +2,16 @@ namespace MailPoet\Newsletter\Renderer\Blocks; +use MailPoet\AutomaticEmails\WooCommerce\Events\AbandonedCart; +use MailPoet\AutomaticEmails\WooCommerce\WooCommerce as WooCommerceEmail; use MailPoet\Entities\NewsletterEntity; +use MailPoet\Entities\NewsletterOptionEntity; +use MailPoet\Entities\NewsletterOptionFieldEntity; use MailPoet\Entities\NewsletterPostEntity; +use MailPoet\Models\Newsletter; use MailPoet\Newsletter\NewsletterPostsRepository; use MailPoet\Newsletter\NewslettersRepository; +use MailPoet\Newsletter\Scheduler\AutomaticEmailScheduler; use MailPoet\WP\Functions as WPFunctions; class RendererTest extends \MailPoetTest { @@ -21,6 +27,9 @@ class RendererTest extends \MailPoetTest { /** @var WPFunctions */ private $wp; + /** @var AutomaticEmailScheduler */ + private $automaticEmailScheduler; + /** @var array */ private $postIds = []; @@ -86,12 +95,52 @@ class RendererTest extends \MailPoetTest { 'backgroundColorAlternate' => '#eeeeee', ]; + /** @var array */ + private $productIds = []; + + private $accBlock = [ + 'type' => 'abandonedCartContent', + 'amount' => '2', + 'withLayout' => true, + 'contentType' => 'product', + 'postStatus' => 'publish', + 'inclusionType' => 'include', + 'displayType' => 'excerpt', + 'titleFormat' => 'h1', + 'titleAlignment' => 'left', + 'titleIsLink' => false, + 'imageFullWidth' => false, + 'featuredImagePosition' => 'alternate', + 'pricePosition' => 'below', + 'readMoreType' => 'none', + 'readMoreText' => '', + 'readMoreButton' => [], + 'sortBy' => 'newest', + 'showDivider' => true, + 'divider' => [ + 'type' => 'divider', + 'context' => 'abandonedCartContent.divider', + 'styles' => [ + 'block' => [ + 'backgroundColor' => 'transparent', + 'padding' => '13px', + 'borderStyle' => 'solid', + 'borderWidth' => '3px', + 'borderColor' => '#aaaaaa', + ], + ], + ], + 'backgroundColor' => '#ffffff', + 'backgroundColorAlternate' => '#eeeeee', + ]; + public function _before() { parent::_before(); $this->renderer = $this->diContainer->get(Renderer::class); $this->wp = $this->diContainer->get(WPFunctions::class); $this->newsletterPostRepository = $this->diContainer->get(NewsletterPostsRepository::class); $this->newslettersRepository = $this->diContainer->get(NewslettersRepository::class); + $this->automaticEmailScheduler = new AutomaticEmailScheduler(); // Clear old posts $posts = $this->wp->getPosts(['post_type' => 'post']); @@ -99,10 +148,23 @@ class RendererTest extends \MailPoetTest { $this->wp->wpDeletePost((int)$post->ID); } + // Clear old products + $products = $this->wp->getPosts(['post_type' => 'product']); + foreach ($products as $product) { + $this->wp->wpDeletePost((int)$product->ID); + } + + $this->postIds = []; $this->postIds[] = $this->createPost('POST 1', '2020-01-01 01:01:01'); $this->postIds[] = $this->createPost('POST 2', '2020-02-01 01:01:01'); $this->postIds[] = $this->createPost('POST 3', '2020-03-01 01:01:01'); $this->postIds[] = $this->createPost('POST 4', '2020-04-01 01:01:01'); + + $this->productIds = []; + $this->productIds[] = $this->createPost('Product 1', '2020-05-01 01:01:01', 'product'); + $this->productIds[] = $this->createPost('Product 2', '2020-06-01 01:01:01', 'product'); + $this->productIds[] = $this->createPost('Product 3', '2020-07-01 01:01:01', 'product'); + $this->productIds[] = $this->createPost('Product 4', '2020-08-01 01:01:01', 'product'); } public function testItRendersLatestPostsInAlc() { @@ -168,12 +230,78 @@ class RendererTest extends \MailPoetTest { expect($encodedResult)->notContains('POST 1'); } - private function createPost(string $title, string $publishDate) { + public function testItDoesNotRenderIfNewsletterTypeIsNotAutomatic() { + $newsletter = $this->createNewsletter('Newsletter', NewsletterEntity::TYPE_STANDARD); + $sendingTask = $this->createSendingTask($newsletter); + $result = $this->renderer->abandonedCartContentTransformedProducts($newsletter, $this->accBlock, false, $sendingTask); + $encodedResult = json_encode($result); + expect($encodedResult)->equals('[]'); + } + + public function testItDoesNotRenderIfAutomaticNewsletterIsNotForAbandonedCart() { + $newsletter = $this->createNewsletter('Newsletter', NewsletterEntity::TYPE_AUTOMATIC); + $this->setGroupAndEventOptions($newsletter, WooCommerceEmail::SLUG, 'some_event'); + $sendingTask = $this->createSendingTask($newsletter); + $result = $this->renderer->abandonedCartContentTransformedProducts($newsletter, $this->accBlock, false, $sendingTask); + $encodedResult = json_encode($result); + expect($encodedResult)->equals('[]'); + } + + public function testItRendersLatestProductsInPreviewMode() { + $newsletter = $this->createNewsletter('Newsletter', NewsletterEntity::TYPE_AUTOMATIC); + $this->setGroupAndEventOptions($newsletter); + $this->accBlock['displayType'] = 'titleOnly'; + $this->accBlock['pricePosition'] = 'hidden'; + $result = $this->renderer->abandonedCartContentTransformedProducts($newsletter, $this->accBlock, true); + $encodedResult = json_encode($result); + expect($encodedResult)->contains('Product 4'); + expect($encodedResult)->contains('Product 3'); + expect($encodedResult)->notContains('Product 2'); + expect($encodedResult)->notContains('Product 1'); + } + + public function testItDoesNotRenderIfNoSendingTaskIsSupplied() { + $newsletter = $this->createNewsletter('Newsletter', NewsletterEntity::TYPE_AUTOMATIC); + $this->setGroupAndEventOptions($newsletter); + $this->accBlock['displayType'] = 'titleOnly'; + $this->accBlock['pricePosition'] = 'hidden'; + $result = $this->renderer->abandonedCartContentTransformedProducts($newsletter, $this->accBlock, false); + $encodedResult = json_encode($result); + expect($encodedResult)->equals('[]'); + } + + public function testItDoesNotRenderIfCartIsEmpty() { + $newsletter = $this->createNewsletter('Newsletter', NewsletterEntity::TYPE_AUTOMATIC); + $this->setGroupAndEventOptions($newsletter); + $this->accBlock['displayType'] = 'titleOnly'; + $this->accBlock['pricePosition'] = 'hidden'; + $sendingTask = $this->createSendingTask($newsletter, 1, [AbandonedCart::TASK_META_NAME => []]); + $result = $this->renderer->abandonedCartContentTransformedProducts($newsletter, $this->accBlock, false, $sendingTask); + $encodedResult = json_encode($result); + expect($encodedResult)->equals('[]'); + } + + public function testItRendersAbandonedCartContentBlock() { + $newsletter = $this->createNewsletter('Newsletter', NewsletterEntity::TYPE_AUTOMATIC); + $this->setGroupAndEventOptions($newsletter); + $this->accBlock['displayType'] = 'titleOnly'; + $this->accBlock['pricePosition'] = 'hidden'; + $sendingTask = $this->createSendingTask($newsletter); + $result = $this->renderer->abandonedCartContentTransformedProducts($newsletter, $this->accBlock, false, $sendingTask); + $encodedResult = json_encode($result); + expect($encodedResult)->notContains('Product 4'); + expect($encodedResult)->contains('Product 3'); + expect($encodedResult)->contains('Product 2'); + expect($encodedResult)->contains('Product 1'); + } + + private function createPost(string $title, string $publishDate, string $type = 'post') { return $this->wp->wpInsertPost([ 'post_title' => $title, 'post_status' => 'publish', 'post_date' => $publishDate, 'post_date_gmt' => $this->wp->getGmtFromDate($publishDate), + 'post_type' => $type, ]); } @@ -187,9 +315,42 @@ class RendererTest extends \MailPoetTest { return $newsletter; } + private function setGroupAndEventOptions($newsletter, $group = WooCommerceEmail::SLUG, $event = AbandonedCart::SLUG) { + $newsletterOptionField = new NewsletterOptionFieldEntity(); + $newsletterOptionField->setName('group'); + $newsletterOptionField->setNewsletterType(NewsletterEntity::TYPE_AUTOMATIC); + $this->entityManager->persist($newsletterOptionField); + + $newsletterOption = new NewsletterOptionEntity($newsletter, $newsletterOptionField); + $newsletterOption->setValue($group); + $this->entityManager->persist($newsletterOption); + + $newsletterOptionField = new NewsletterOptionFieldEntity(); + $newsletterOptionField->setName('event'); + $newsletterOptionField->setNewsletterType(NewsletterEntity::TYPE_AUTOMATIC); + $this->entityManager->persist($newsletterOptionField); + + $newsletterOption = new NewsletterOptionEntity($newsletter, $newsletterOptionField); + $newsletterOption->setValue($event); + $this->entityManager->persist($newsletterOption); + + $this->entityManager->flush($newsletter); + $this->entityManager->refresh($newsletter); + } + + private function createSendingTask($newsletter, $subscriberId = null, $meta = null) { + $subscriberId = $subscriberId ?: 1; // dummy default value + $meta = $meta ?: [AbandonedCart::TASK_META_NAME => array_slice($this->productIds, 0, 3)]; + $sendingTask = $this->automaticEmailScheduler + ->createAutomaticEmailSendingTask(Newsletter::findOne($newsletter->getId()), $subscriberId, $meta); + return $sendingTask; + } + public function _after() { parent::_after(); $this->truncateEntity(NewsletterPostEntity::class); + $this->truncateEntity(NewsletterOptionEntity::class); + $this->truncateEntity(NewsletterOptionFieldEntity::class); $this->truncateEntity(NewsletterEntity::class); } }