Files
piratepoet/mailpoet/tests/integration/Services/AuthorizedSenderDomainControllerTest.php
Brezo Cordero 1e373ab7e0 Update Sender Domain inline notice
Remove unused notices displayed before enforcement date.

[MAILPOET-5844]
2024-02-05 10:52:56 +01:00

530 lines
18 KiB
PHP

<?php declare(strict_types = 1);
namespace MailPoet\Test\Services;
use Codeception\Stub\Expected;
use InvalidArgumentException;
use MailPoet\Mailer\Mailer;
use MailPoet\Newsletter\Statistics\NewsletterStatisticsRepository;
use MailPoet\Services\AuthorizedSenderDomainController;
use MailPoet\Services\Bridge;
use MailPoet\Services\Bridge\API;
use MailPoet\Settings\SettingsController;
use MailPoet\Test\DataFactories\Newsletter;
use MailPoet\Test\DataFactories\StatisticsNewsletters;
use MailPoet\Test\DataFactories\Subscriber;
use MailPoet\Util\License\Features\Subscribers;
use MailPoet\WP\Functions as WPFunctions;
use MailPoetVendor\Carbon\Carbon;
require_once('BridgeTestMockAPI.php');
class AuthorizedSenderDomainControllerTest extends \MailPoetTest {
/** @var SettingsController */
private $settings;
/** @var Bridge */
private $bridge;
private $apiKey;
/**@var WPFunctions */
private $wp;
private int $lowerLimit;
private int $upperLimit;
public function _before() {
parent::_before();
$this->apiKey = getenv('WP_TEST_MAILER_MAILPOET_API');
$this->bridge = new Bridge();
$this->bridge->api = new API($this->apiKey, new WPFunctions());
$this->settings = SettingsController::getInstance();
$this->settings->set(
Mailer::MAILER_CONFIG_SETTING_NAME,
[
'method' => 'MailPoet',
'mailpoet_api_key' => $this->apiKey,
]
);
$this->wp = $this->make(WPFunctions::class, [
'getTransient' => false,
'setTransient' => true,
]);
$this->lowerLimit = AuthorizedSenderDomainController::LOWER_LIMIT;
$this->upperLimit = AuthorizedSenderDomainController::UPPER_LIMIT;
}
public function testItFetchSenderDomains() {
$domains = ['mailpoet.com', 'good', 'testdomain.com'];
$bridgeResponse = [
'mailpoet.com' => ['data'],
'good' => ['data'],
'testdomain.com' => ['data'],
];
$bridgeMock = $this->make(Bridge::class, [
'getAuthorizedSenderDomains' => Expected::once($bridgeResponse),
]);
$controller = $this->getController($bridgeMock);
$allDomains = $controller->getAllSenderDomains();
verify($allDomains)->same($domains);
}
public function testItReturnsVerifiedSenderDomains() {
$bridgeResponse = [
[
'domain' => 'mailpoet.com',
'domain_status' => 'verified',
'dns' => Bridge\BridgeTestMockAPI::VERIFIED_DOMAIN_RESPONSE['dns'],
],
[
'domain' => 'testdomain.com',
'domain_status' => 'unverified',
'dns' => [],
],
];
$bridgeMock = $this->make(Bridge::class, [
'getRawSenderDomainData' => Expected::once($bridgeResponse),
]);
$controller = $this->getController($bridgeMock);
$verifiedDomains = $controller->getVerifiedSenderDomains();
verify($verifiedDomains)->same(['mailpoet.com']); // only this is Verified for now
}
public function testItReturnsVerifiedSenderDomainsFromTransient() {
$bridgeResponse = [
[
'domain' => 'mailpoet.com',
'domain_status' => 'verified',
'dns' => Bridge\BridgeTestMockAPI::VERIFIED_DOMAIN_RESPONSE['dns'],
],
[
'domain' => 'testdomain.com',
'domain_status' => 'unverified',
'dns' => [],
],
];
$bridgeMock = $this->make(Bridge::class, [
'getRawSenderDomainData' => Expected::never(),
]);
$this->wp = $this->make(WPFunctions::class, [
'getTransient' => $bridgeResponse,
'setTransient' => true,
]);
$controller = $this->getController($bridgeMock);
$verifiedDomains = $controller->getVerifiedSenderDomains();
verify($verifiedDomains)->same(['mailpoet.com']);
}
public function testItReturnsVerifiedSenderDomainsIgnoringCache() {
$oldBridgeResponse = [
[
'domain' => 'mailpoet.com',
'domain_status' => 'verified',
'dns' => Bridge\BridgeTestMockAPI::VERIFIED_DOMAIN_RESPONSE['dns'],
],
[
'domain' => 'testdomain.com',
'domain_status' => 'unverified',
'dns' => [],
],
];
$newBridgeResponse = [
[
'domain' => 'mailpoet.com',
'domain_status' => 'verified',
'dns' => Bridge\BridgeTestMockAPI::VERIFIED_DOMAIN_RESPONSE['dns'],
],
[
'domain' => 'testdomain.com',
'domain_status' => 'verified',
'dns' => [],
],
];
$bridgeMock = $this->make(Bridge::class, [
'getRawSenderDomainData' => Expected::once($newBridgeResponse),
]);
$this->wp = $this->make(WPFunctions::class, [
'getTransient' => $oldBridgeResponse,
'setTransient' => true,
]);
$controller = $this->getController($bridgeMock);
$verifiedDomains = $controller->getVerifiedSenderDomainsIgnoringCache();
verify($verifiedDomains)->same(['mailpoet.com', 'testdomain.com']);
// Reset mock
$this->wp = $this->make(WPFunctions::class, [
'getTransient' => false,
'setTransient' => true,
]);
}
public function testItReturnsEmptyArrayWhenNoVerifiedSenderDomains() {
$expectation = Expected::once([]); // with empty array
$bridgeMock = $this->make(Bridge::class, ['getRawSenderDomainData' => $expectation]);
$controller = $this->getController($bridgeMock);
$verifiedDomains = $controller->getVerifiedSenderDomains();
verify($verifiedDomains)->same([]);
$domains = [
[
'domain' => 'testdomain.com',
'domain_status' => 'unverified',
'dns' => [],
],
];
$expectation = Expected::once($domains);
$bridgeMock = $this->make(Bridge::class, ['getRawSenderDomainData' => $expectation]);
$controller = $this->getController($bridgeMock);
$verifiedDomains = $controller->getVerifiedSenderDomains();
verify($verifiedDomains)->same([]);
}
public function testCreateAuthorizedSenderDomainThrowsForExistingDomains() {
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Sender domain exist');
$domains = ['testdomain.com' => []];
$getSenderDomainsExpectation = Expected::once($domains);
$createSenderDomainsExpectation = Expected::never();
$bridgeMock = $this->make(Bridge::class, [
'getAuthorizedSenderDomains' => $getSenderDomainsExpectation,
'createAuthorizedSenderDomain' => $createSenderDomainsExpectation,
]);
$controller = $this->getController($bridgeMock);
$controller->createAuthorizedSenderDomain('testdomain.com');
}
public function testVerifyAuthorizedSenderDomainThrowsForNoneExistingDomains() {
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Sender domain does not exist');
$domains = ['newdomain.com' => []];
$getSenderDomainsExpectation = Expected::once($domains);
$verifySenderDomainsExpectation = Expected::never();
$bridgeMock = $this->make(Bridge::class, [
'getAuthorizedSenderDomains' => $getSenderDomainsExpectation,
'verifyAuthorizedSenderDomain' => $verifySenderDomainsExpectation,
]);
$controller = $this->getController($bridgeMock);
$controller->verifyAuthorizedSenderDomain('testdomain.com');
}
public function testVerifyAuthorizedSenderDomainThrowsForVerifiedDomains() {
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Sender domain already verified');
$domains = ['testdomain.com' => [
['status' => 'valid'],
['status' => 'valid'],
['status' => 'valid'],
['status' => 'valid'],
]];
$domainsRawData = [
'testdomain.com' => [
'domain' => 'testdomain.com',
'domain_status' => 'verified',
'dns' => [],
],
];
$getSenderDomainsExpectation = Expected::once($domains);
$getSenderDomainsRawDataExpectation = Expected::once($domainsRawData);
$verifySenderDomainsExpectation = Expected::never();
$bridgeMock = $this->make(Bridge::class, [
'getAuthorizedSenderDomains' => $getSenderDomainsExpectation,
'getRawSenderDomainData' => $getSenderDomainsRawDataExpectation,
'verifyAuthorizedSenderDomain' => $verifySenderDomainsExpectation,
]);
$controller = $this->getController($bridgeMock);
$controller->verifyAuthorizedSenderDomain('testdomain.com');
}
public function testVerifyAuthorizedSenderDomainVerifiesPartiallyVerifiedDomains() {
$domains = ['testdomain.com' => [
['status' => 'valid'],
['status' => 'valid'],
['status' => 'valid'],
['status' => 'pending'],
]];
$domainsRawData = [
'testdomain.com' => [
'domain' => 'testdomain.com',
'domain_status' => 'partially_verified',
'dns' => [],
],
];
$response = [
'status' => API::RESPONSE_STATUS_OK,
'dns' => [],
];
$getSenderDomainsExpectation = Expected::once($domains);
$getSenderDomainsRawDataExpectation = Expected::once($domainsRawData);
$verifySenderDomainsExpectation = Expected::once($response);
$bridgeMock = $this->make(Bridge::class, [
'getAuthorizedSenderDomains' => $getSenderDomainsExpectation,
'getRawSenderDomainData' => $getSenderDomainsRawDataExpectation,
'verifyAuthorizedSenderDomain' => $verifySenderDomainsExpectation,
]);
$controller = $this->getController($bridgeMock);
$controller->verifyAuthorizedSenderDomain('testdomain.com');
}
public function testItCanGetDomainsByOverallStatus(): void {
$verifiedDomain = [
'domain' => 'example1.com',
'domain_status' => 'verified',
'dns' => [],
];
$partiallyVerifiedDomain = [
'domain' => 'example2.com',
'domain_status' => 'partially-verified',
'dns' => [],
];
$unverifiedDomain = [
'domain' => 'example3.com',
'domain_status' => 'unverified',
'dns' => [],
];
$mockResponse = [
$verifiedDomain,
$partiallyVerifiedDomain,
$unverifiedDomain,
];
$getRawSenderDomainData = Expected::once($mockResponse);
$bridgeMock = $this->make(Bridge::class, [
'getRawSenderDomainData' => $getRawSenderDomainData,
]);
$controller = $this->getController($bridgeMock);
$domainsByStatus = $controller->getSenderDomainsByStatus(['verified']);
$this->assertEqualsCanonicalizing([$verifiedDomain], $domainsByStatus);
$domainsByStatus = $controller->getSenderDomainsByStatus(['partially-verified']);
$this->assertEqualsCanonicalizing([$partiallyVerifiedDomain], $domainsByStatus);
$domainsByStatus = $controller->getSenderDomainsByStatus(['unverified']);
$this->assertEqualsCanonicalizing([$unverifiedDomain], $domainsByStatus);
$grouped = $controller->getSenderDomainsGroupedByStatus();
$this->assertEqualsCanonicalizing([
'verified' => [$verifiedDomain],
'partially-verified' => [$partiallyVerifiedDomain],
'unverified' => [$unverifiedDomain],
], $grouped);
$domains = $controller->getFullyVerifiedSenderDomains(true);
$this->assertEqualsCanonicalizing(['example1.com'], $domains);
$domains = $controller->getPartiallyVerifiedSenderDomains(true);
$this->assertEqualsCanonicalizing(['example2.com'], $domains);
$domains = $controller->getFullyOrPartiallyVerifiedSenderDomains(true);
$this->assertEqualsCanonicalizing(['example1.com', 'example2.com'], $domains);
$domains = $controller->getUnverifiedSenderDomains(true);
$this->assertEqualsCanonicalizing(['example3.com'], $domains);
}
public function testVerifyAuthorizedSenderDomainThrowsForOtherErrors() {
$errorMessage = 'This is a test message';
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage($errorMessage);
$domains = ['testdomain.com' => []];
$domainsRawData = [
'testdomain.com' => [
'domain' => 'testdomain.com',
'domain_status' => 'unverified',
'dns' => [],
],
];
$getSenderDomainsExpectation = Expected::once($domains);
$getSenderDomainsRawDataExpectation = Expected::once($domainsRawData);
$verifySenderDomainsExpectation = Expected::once([
'error' => $errorMessage,
'message' => $errorMessage,
'status' => API::RESPONSE_STATUS_ERROR,
]);
$bridgeMock = $this->make(Bridge::class, [
'getAuthorizedSenderDomains' => $getSenderDomainsExpectation,
'getRawSenderDomainData' => $getSenderDomainsRawDataExpectation,
'verifyAuthorizedSenderDomain' => $verifySenderDomainsExpectation,
]);
$controller = $this->getController($bridgeMock);
$controller->verifyAuthorizedSenderDomain('testdomain.com');
}
public function testItCanRewriteEmailAddresses(): void {
$email = 'jane.doe@gmail.com';
$this->assertSame('jane.doe=gmail.com@replies.sendingservice.net', $this->getController()->getRewrittenEmailAddress($email));
}
private function getController($bridgeMock = null, $subscribersMock = null): AuthorizedSenderDomainController {
$newsletterStatisticsRepository = $this->diContainer->get(NewsletterStatisticsRepository::class);
$subscribers = $this->diContainer->get(Subscribers::class);
return new AuthorizedSenderDomainController(
$bridgeMock ?? $this->bridge,
$newsletterStatisticsRepository,
$this->settings,
$subscribersMock ?? $subscribers,
$this->wp
);
}
public function testUserIsNewIfTheyHaveNotCompletedWelcomeWizard(): void {
$this->settings->delete('version');
$this->assertTrue($this->getController()->isNewUser());
}
public function testUserIsNewIfTheyInstalledAfterNewRestrictionsImplemented(): void {
$this->settings->set('version', MAILPOET_VERSION);
$this->settings->set('installed_after_new_domain_restrictions', '1');
$this->assertTrue($this->getController()->isNewUser());
// also true even if they've sent emails
(new StatisticsNewsletters((new Newsletter())->withSendingQueue()->create(), (new Subscriber())->create()))->create();
$this->assertTrue($this->getController()->isNewUser());
}
public function testUserIsNotNewIfTheyDoNotHaveTheSettingAndHaveSentEmails(): void {
$this->settings->set('version', MAILPOET_VERSION);
$this->settings->delete('installed_after_new_domain_restrictions');
// No emails yet, so they are still "new"
$this->assertTrue($this->getController()->isNewUser());
(new StatisticsNewsletters((new Newsletter())->withSendingQueue()->create(), (new Subscriber())->create()))->create();
$this->assertFalse($this->getController()->isNewUser());
}
public function testIsSmallSenderIfSubscribersUnderLowerLimit(): void {
$subscribersMock = $this->make(Subscribers::class, [
'getSubscribersCount' => Expected::once($this->lowerLimit),
]);
$this->assertTrue($this->getController(null, $subscribersMock)->isSmallSender());
}
public function testIsNotSmallSenderIfSubscribersOverLowerLimit(): void {
$subscribersMock = $this->make(Subscribers::class, [
'getSubscribersCount' => Expected::once($this->lowerLimit + 1),
]);
$this->assertFalse($this->getController(null, $subscribersMock)->isSmallSender());
}
public function testIsAuthorizedDomainRequiredForNewCampaigns(): void {
// Is new user
$this->settings->set('version', MAILPOET_VERSION);
$this->settings->set('installed_after_new_domain_restrictions', '1');
// Is not small sender
$subscribersMock = $this->make(Subscribers::class, [
'getSubscribersCount' => Expected::once($this->lowerLimit + 1),
]);
$this->assertTrue($this->getController(null, $subscribersMock)->isAuthorizedDomainRequiredForNewCampaigns());
}
public function testIsAuthorizedDomainRequiredForExistingCampaigns(): void {
// Is new user
$this->settings->set('version', MAILPOET_VERSION);
$this->settings->set('installed_after_new_domain_restrictions', '1');
// Is Big Sender
$subscribersMock = $this->make(Subscribers::class, [
'getSubscribersCount' => Expected::once($this->upperLimit + 1),
]);
$this->assertTrue($this->getController(null, $subscribersMock)->isAuthorizedDomainRequiredForExistingCampaigns());
}
public function testNotIsAuthorizedDomainRequiredForNewCampaignsForExistingUsersBeforeEnforcementDate(): void {
// Is not new user
$this->settings->set('version', MAILPOET_VERSION);
$this->settings->delete('installed_after_new_domain_restrictions');
(new StatisticsNewsletters((new Newsletter())->withSendingQueue()->create(), (new Subscriber())->create()))->create();
// Before EnforcementDate
Carbon::setTestNow(Carbon::parse('2024-01-31 00:00:00 UTC'));
$this->assertFalse($this->getController()->isAuthorizedDomainRequiredForNewCampaigns());
}
public function testIsAuthorizedDomainRequiredForNewCampaignsForExistingUsersAfterEnforcementDate(): void {
// Is not new user
$this->settings->set('version', MAILPOET_VERSION);
$this->settings->delete('installed_after_new_domain_restrictions');
(new StatisticsNewsletters((new Newsletter())->withSendingQueue()->create(), (new Subscriber())->create()))->create();
// After EnforcementDate
Carbon::setTestNow(Carbon::parse('2024-02-01 00:00:01 UTC'));
// Is not small sender
$subscribersMock = $this->make(Subscribers::class, [
'getSubscribersCount' => Expected::once($this->lowerLimit + 1),
]);
$this->assertTrue($this->getController(null, $subscribersMock)->isAuthorizedDomainRequiredForNewCampaigns());
}
public function testNotIsAuthorizedDomainRequiredForNewCampaignsForSmallSenders(): void {
// Is not new user
$this->settings->set('version', MAILPOET_VERSION);
$this->settings->delete('installed_after_new_domain_restrictions');
(new StatisticsNewsletters((new Newsletter())->withSendingQueue()->create(), (new Subscriber())->create()))->create();
// After EnforcementDate
Carbon::setTestNow(Carbon::parse('2024-02-01 00:00:01 UTC'));
// Is small sender
$subscribersMock = $this->make(Subscribers::class, [
'getSubscribersCount' => Expected::once($this->lowerLimit),
]);
$this->assertFalse($this->getController(null, $subscribersMock)->isAuthorizedDomainRequiredForNewCampaigns());
}
public function testNotIsAuthorizedDomainRequiredForNewCampaignsForNewUsersSmallSenders(): void {
// Is new user
$this->settings->set('version', MAILPOET_VERSION);
$this->settings->set('installed_after_new_domain_restrictions', '1');
// Is small sender
$subscribersMock = $this->make(Subscribers::class, [
'getSubscribersCount' => Expected::once($this->lowerLimit),
]);
$this->assertFalse($this->getController(null, $subscribersMock)->isAuthorizedDomainRequiredForNewCampaigns());
}
}