diff --git a/assets/js/src/newsletters/send.jsx b/assets/js/src/newsletters/send.jsx index 3cc64c266a..183bf1028e 100644 --- a/assets/js/src/newsletters/send.jsx +++ b/assets/js/src/newsletters/send.jsx @@ -60,6 +60,25 @@ function validateNewsletter(newsletter) { return MailPoet.I18n.t('emailAlreadySent'); } + if (newsletter.type === 're_engagement' && !window.mailpoet_tracking_enabled) { + return ( + + {ReactStringReplace( + MailPoet.I18n.t('reEngagementEmailsDisableIfTrackingIs'), + /\[link\](.*?)\[\/link\]/g, + (match) => ( + + {match} + + ) + )} + + ); + } return undefined; } @@ -551,7 +570,7 @@ class NewsletterSend extends React.Component { { this.state.validationError !== undefined && ( {this.state.validationError})} - tooltipId={this.state.validationError} + tooltipId="helpTooltipSendEmail" /> ) } diff --git a/lib/API/JSON/v1/Settings.php b/lib/API/JSON/v1/Settings.php index bc2f133853..09980c1f48 100644 --- a/lib/API/JSON/v1/Settings.php +++ b/lib/API/JSON/v1/Settings.php @@ -294,7 +294,7 @@ class Settings extends APIEndpoint { return $this->deactivateReEngagementEmails(); } catch (\Exception $e) { throw new \Exception( - __('Unable to deactivate re-engagement emails: ' . $e->getMessage()), 'mailpoet'); + __('Unable to deactivate re-engagement emails: ' . $e->getMessage(), 'mailpoet')); } } diff --git a/tests/acceptance/Newsletters/NewsletterCreationCest.php b/tests/acceptance/Newsletters/NewsletterCreationCest.php index e643f5463b..864c86609b 100644 --- a/tests/acceptance/Newsletters/NewsletterCreationCest.php +++ b/tests/acceptance/Newsletters/NewsletterCreationCest.php @@ -134,8 +134,7 @@ class NewsletterCreationCest { $i->waitForElement('[data-automation-id="newsletter_send_heading"]'); $i->waitForText('You’ll soon be able to send once our team reviews your account. In the meantime, you can send previews to your authorized emails.'); $href = $i->grabAttributeFrom('//a[text()="your authorized emails"]', 'href'); - $sendButton = $i->grabAttributeFrom('[data-automation-id="email-submit"]', 'class'); expect($href)->same('https://account.mailpoet.com/authorization'); - expect($sendButton)->stringContainsString('mailpoet-button-disabled'); + $i->seeElement('[data-automation-id="email-submit"]:disabled'); } } diff --git a/tests/acceptance/Settings/AdvancedSettingsCest.php b/tests/acceptance/Settings/AdvancedSettingsCest.php index 6a6a9e0b53..d2a002fa01 100644 --- a/tests/acceptance/Settings/AdvancedSettingsCest.php +++ b/tests/acceptance/Settings/AdvancedSettingsCest.php @@ -3,6 +3,7 @@ namespace MailPoet\Test\Acceptance; use Codeception\Util\Locator; +use MailPoet\Test\DataFactories\Features; class AdvancedSettingsCest { public function toggleAnonymousDataSetting(\AcceptanceTester $i) { @@ -133,8 +134,10 @@ class AdvancedSettingsCest { $i->waitForElement($chooseLogErrors); } - public function checkInactiveSubscribers(\AcceptanceTester $i) { - $i->wantTo('Check that inactive subsribers has default value'); + public function checkInactiveSubscribersAndEmails(\AcceptanceTester $i) { + $features = new Features(); + $features->withFeatureEnabled('re-engagement-email'); + $i->wantTo('Check that inactive subscribers has default value'); $inactiveSubscribersDefault = '[data-automation-id="inactive-subscribers-default"]'; $trackingEnabled = '[data-automation-id="tracking-enabled-radio"]'; $i->login(); @@ -145,12 +148,14 @@ class AdvancedSettingsCest { $i->waitForElement($inactiveSubscribersDefault); $i->seeCheckboxIsChecked($inactiveSubscribersDefault . ' input'); - $i->wantTo('See that inactive subsribers is disabled when tracking is disabled'); + $i->wantTo('See that inactive subscribers and re-engagement emails are disabled when tracking is disabled'); $trackingDisabled = '[data-automation-id="tracking-disabled-radio"]'; $inactiveSubscribersDisabled = '[data-automation-id="inactive-subscribers-disabled"]'; $inactiveSubscribersEnabled = '[data-automation-id="inactive-subscribers-enabled"]'; + $reEngagementEmailsDisabledNotice = 're-engagement emails are disabled when tracking is disabled'; $i->click($trackingDisabled); $i->waitForElement($inactiveSubscribersDisabled); $i->dontSee($inactiveSubscribersEnabled); + $i->see($reEngagementEmailsDisabledNotice); } } diff --git a/tests/integration/API/JSON/v1/SettingsTest.php b/tests/integration/API/JSON/v1/SettingsTest.php index 6dfc40375f..a0da4d5ec8 100644 --- a/tests/integration/API/JSON/v1/SettingsTest.php +++ b/tests/integration/API/JSON/v1/SettingsTest.php @@ -3,12 +3,14 @@ namespace MailPoet\Test\API\JSON\v1; use Codeception\Stub\Expected; +use Codeception\Util\Fixtures; use MailPoet\API\JSON\Error as APIError; use MailPoet\API\JSON\Response as APIResponse; use MailPoet\API\JSON\v1\Settings; use MailPoet\Config\ServicesChecker; use MailPoet\Cron\Workers\InactiveSubscribers; use MailPoet\Cron\Workers\WooCommerceSync; +use MailPoet\Entities\NewsletterEntity; use MailPoet\Entities\ScheduledTaskEntity; use MailPoet\Form\FormMessageController; use MailPoet\Mailer\MailerLog; @@ -39,10 +41,14 @@ class SettingsTest extends \MailPoetTest { /** @var ScheduledTasksRepository */ private $tasksRepository; + /* @var NewslettersRepository */ + private $newsletterRepository; + public function _before() { parent::_before(); ORM::raw_execute('TRUNCATE ' . ScheduledTask::$_table); $this->tasksRepository = $this->diContainer->get(ScheduledTasksRepository::class); + $this->newsletterRepository = $this->diContainer->get(NewslettersRepository::class); $this->settings = SettingsController::getInstance(); $this->settings->set('some.setting.key', true); $this->endpoint = new Settings( @@ -52,6 +58,7 @@ class SettingsTest extends \MailPoetTest { $this->make(TransactionalEmails::class), WPFunctions::get(), $this->diContainer->get(EntityManager::class), + $this->diContainer->get(NewslettersRepository::class), $this->diContainer->get(StatisticsOpensRepository::class), $this->diContainer->get(ScheduledTasksRepository::class), $this->diContainer->get(FormMessageController::class), @@ -92,6 +99,7 @@ class SettingsTest extends \MailPoetTest { $this->make(TransactionalEmails::class), WPFunctions::get(), $this->diContainer->get(EntityManager::class), + $this->diContainer->get(NewslettersRepository::class), $this->diContainer->get(StatisticsOpensRepository::class), $this->diContainer->get(ScheduledTasksRepository::class), $this->diContainer->get(FormMessageController::class), @@ -123,6 +131,7 @@ class SettingsTest extends \MailPoetTest { $this->make(TransactionalEmails::class), WPFunctions::get(), $this->diContainer->get(EntityManager::class), + $this->diContainer->get(NewslettersRepository::class), $this->diContainer->get(StatisticsOpensRepository::class), $this->diContainer->get(ScheduledTasksRepository::class), $this->diContainer->get(FormMessageController::class), @@ -148,6 +157,7 @@ class SettingsTest extends \MailPoetTest { $this->make(TransactionalEmails::class), WPFunctions::get(), $this->diContainer->get(EntityManager::class), + $this->diContainer->get(NewslettersRepository::class), $this->diContainer->get(StatisticsOpensRepository::class), $this->diContainer->get(ScheduledTasksRepository::class), $this->diContainer->get(FormMessageController::class), @@ -248,6 +258,32 @@ class SettingsTest extends \MailPoetTest { expect($task)->isInstanceOf(ScheduledTaskEntity::class); } + public function testItDeactivatesReEngagementEmailsIfTrackingDisabled(): void { + $this->createNewsletter(NewsletterEntity::TYPE_RE_ENGAGEMENT, NewsletterEntity::STATUS_ACTIVE); + $this->settings->set('tracking', ['enabled' => '1']); + $response = $this->endpoint->set(['tracking' => ['enabled' => '0']]); + expect($response->meta['showNotice'])->equals(true); + expect($response->meta['action'])->equals('deactivate'); + expect($this->newsletterRepository->findActiveByTypes([NewsletterEntity::TYPE_RE_ENGAGEMENT]))->equals([]); + } + + public function testItFlagsNoticeToReactivateReEngagementEmailsIfTrackingEnabled(): void { + $this->createNewsletter(NewsletterEntity::TYPE_RE_ENGAGEMENT); + $this->settings->set('tracking', ['enabled' => '0']); + $response = $this->endpoint->set(['tracking' => ['enabled' => '1']]); + expect($response->meta['showNotice'])->equals(true); + expect($response->meta['action'])->equals('reactivate'); + } + + public function testNoNoticeWhenTrackingChangesIfNoReEngagementEmails(): void { + $this->createNewsletter(NewsletterEntity::TYPE_STANDARD, NewsletterEntity::STATUS_ACTIVE); + $this->settings->set('tracking', ['enabled' => '0']); + $response = $this->endpoint->set(['tracking' => ['enabled' => '1']]); + expect($response->meta['showNotice'])->equals(false); + $response = $this->endpoint->set(['tracking' => ['enabled' => '0']]); + expect($response->meta['showNotice'])->equals(false); + } + private function createScheduledTask(string $type): ScheduledTaskEntity { $task = new ScheduledTaskEntity(); $task->setType($type); @@ -264,8 +300,21 @@ class SettingsTest extends \MailPoetTest { ]); } + private function createNewsletter(string $type, string $status = NewsletterEntity::STATUS_DRAFT, $parent = null): NewsletterEntity { + $newsletter = new NewsletterEntity(); + $newsletter->setType($type); + $newsletter->setSubject('My Standard Newsletter'); + $newsletter->setBody(Fixtures::get('newsletter_body_template')); + $newsletter->setStatus($status); + $newsletter->setParent($parent); + $this->entityManager->persist($newsletter); + $this->entityManager->flush(); + return $newsletter; + } + public function _after() { $this->truncateEntity(ScheduledTaskEntity::class); + $this->truncateEntity(NewsletterEntity::class); $this->diContainer->get(SettingsRepository::class)->truncate(); } } diff --git a/views/newsletters.html b/views/newsletters.html index 4c22e31dea..ba561c8f17 100644 --- a/views/newsletters.html +++ b/views/newsletters.html @@ -298,6 +298,7 @@ 'newsletterSendingError': __('An error occurred while trying to send. Please check your settings.'), 'finalNewsletterStep': __('Final Step: Last Details'), 'saveDraftAndClose': __('Save as draft and close'), + 'helpTooltipSendEmail': __('You cannot send the same email twice, as that would be considered spam.
If you must send the same email more than one time, simply duplicate this email first.'), 'pendingKeyApprovalNotice': __('You’ll soon be able to send once our team reviews your account. In the meantime, you can send previews to [link]your authorized emails[/link].'), 'orSimply': __('or simply'), 'goBackToDesign': __('go back to the Design page'), @@ -431,6 +432,7 @@ 'sentToXCustomers': __('Sent to %$1d customers'), 'wooCommerceEmailsWarning': __('WooCommerce emails won’t be sent to new customers because the opt-in on checkout is disabled. Enable it so they can immediately get your emails after their first purchase.'), 'wooCommerceEmailsWarningLink': __('Edit WooCommerce settings'), + 'reEngagementEmailsDisableIfTrackingIs': __('Re-engagement emails are disabled because [link]open and click tracking[/link] is disabled.'), 'unsubscribeLinkMissing': __('All emails must include an "Unsubscribe" link. Add a footer widget to your email to continue.'), 'newsletterIsEmpty': __('Poet, please add prose to your masterpiece before you send it to your followers.'), 'automatedLatestContentMissing': _x('Please add an “Automatic Latest Content” widget to the email from the right sidebar.', '(Please reuse the current translation used for the string “Automatic Latest Content”) This Error message is displayed when a user tries to send a “Post Notification” email without any “Automatic Latest Content” widget inside'), diff --git a/views/settings.html b/views/settings.html index 0544021551..cadacd586c 100644 --- a/views/settings.html +++ b/views/settings.html @@ -130,7 +130,7 @@ 'trackingDescription': __('Enable or disable open and click tracking.'), 're-engagementDisabledBecauseTrackingIs': __('Note: re-engagement emails are disabled when tracking is disabled.'), 're-engagementDisabledNotice': __('Re-engagement emails were deactivated.'), - 're-engagementReactivatedNotice': __('Re-engagement emails are now enabled. Dont forget to [link]activate them[/link].'), + 're-engagementReactivatedNotice': __("Re-engagement emails are now enabled. Don't forget to [link]activate them[/link]."), 'transactionalTitle': _x('Send all site’s emails with…', 'Transational emails settings title'), 'transactionalDescription': _x('Choose which method to send all your WordPress emails (e.g. password reset, new registration, WooCommerce invoices, etc.).', 'Transational emails settings description'), 'transactionalLink': _x('Read more.', 'Transactional emails settings link'),