Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,435 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PageBundle\Tests\Functional\EventListener;
|
||||
|
||||
use Mautic\CategoryBundle\Entity\Category;
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\EmailBundle\Entity\Email;
|
||||
use Mautic\EmailBundle\Entity\Stat;
|
||||
use Mautic\EmailBundle\Helper\MailHashHelper;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\LeadBundle\Entity\LeadList as Segment;
|
||||
use Mautic\PageBundle\Entity\Page;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\PreserveGlobalState(false)]
|
||||
#[\PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses]
|
||||
class BuilderSubscriberTest extends MauticMysqlTestCase
|
||||
{
|
||||
protected $useCleanupRollback = false;
|
||||
|
||||
// Custom preference center page
|
||||
public const CUSTOM_SEGMENT_SELECTOR = '.pref-segmentlist input';
|
||||
public const CUSTOM_CATEGORY_SELECTOR = '.pref-categorylist input';
|
||||
public const CUSTOM_PREFERRED_CHANNEL_SELECTOR = '.pref-preferredchannel select';
|
||||
public const CUSTOM_CHANNEL_FREQ_SELECTOR = '.pref-channelfrequency div[data-contact-frequency="1"]';
|
||||
public const CUSTOM_SAVE_BUTTON_SELECTOR = '.prefs-saveprefs a.btn-save';
|
||||
|
||||
// Default preference center page
|
||||
public const DEFAULT_SEGMENT_SELECTOR = '#contact-segments';
|
||||
public const DEFAULT_CATEGORY_SELECTOR = '#global-categories';
|
||||
public const DEFAULT_PREFERRED_CHANNEL_SELECTOR = '#preferred_channel';
|
||||
public const DEFAULT_CHANNEL_FREQ_SELECTOR = '[data-contact-frequency="1"]';
|
||||
public const DEFAULT_PAUSE_DATES_SELECTOR = '[data-contact-pause-dates="1"]';
|
||||
public const DEFAULT_SAVE_BUTTON_SELECTOR = '#lead_contact_frequency_rules_buttons_save';
|
||||
|
||||
// Common to both custom and default
|
||||
public const TOKEN_SELECTOR = '#lead_contact_frequency_rules__token';
|
||||
public const FORM_SELECTOR = 'form[name="lead_contact_frequency_rules"]';
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->configParams['show_contact_preferences'] = 1;
|
||||
$data = $this->providedData();
|
||||
$this->configParams = array_merge($data[0], $this->configParams);
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests both the default and custom preference center pages.
|
||||
*
|
||||
* @param mixed[] $configParams
|
||||
* @param array<string,int> $selectorsAndExpectedCounts
|
||||
*/
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('frequencyFormRenderingDataProvider')]
|
||||
public function testUnsubscribeFormRendersPreferenceCenterPageCorrectly(array $configParams, array $selectorsAndExpectedCounts, bool $hasPreferenceCenter): void
|
||||
{
|
||||
$emailStat = $this->createStat(
|
||||
$this->createEmail($hasPreferenceCenter),
|
||||
$lead = $this->createLead()
|
||||
);
|
||||
|
||||
$this->createSegment();
|
||||
$this->createCategory();
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
$mailHashHelper = static::getContainer()->get(MailHashHelper::class);
|
||||
\assert($mailHashHelper instanceof MailHashHelper);
|
||||
|
||||
$unsubscribeUrl = $this->router->generate('mautic_email_unsubscribe', [
|
||||
'idHash' => $emailStat->getTrackingHash(),
|
||||
'urlEmail' => $lead->getEmail(),
|
||||
'secretHash' => $mailHashHelper->getEmailHash($lead->getEmail()),
|
||||
], UrlGeneratorInterface::ABSOLUTE_PATH);
|
||||
|
||||
$crawler = $this->client->request('GET', $unsubscribeUrl);
|
||||
|
||||
self::assertTrue($this->client->getResponse()->isSuccessful(), $this->client->getResponse()->getContent());
|
||||
|
||||
$form = $crawler->filter(static::FORM_SELECTOR);
|
||||
$html = $form->html();
|
||||
|
||||
foreach ($selectorsAndExpectedCounts as $selector => $expectedCount) {
|
||||
$message = sprintf(
|
||||
'The form HTML %s not contain the %s section. %s',
|
||||
0 === $expectedCount ? 'should' : 'does',
|
||||
$selector,
|
||||
$html
|
||||
);
|
||||
|
||||
Assert::assertCount(
|
||||
$expectedCount,
|
||||
$form->filter($selector),
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
// Ensure the token and save button are always included within the <form> tag
|
||||
Assert::assertCount(1, $form->filter(static::TOKEN_SELECTOR), sprintf('The following HTML does not contain the _token. %s', $html));
|
||||
|
||||
if ($hasPreferenceCenter) {
|
||||
Assert::assertCount(1, $form->filter(static::CUSTOM_SAVE_BUTTON_SELECTOR), sprintf('The following HTML does not contain the save button. %s', $html));
|
||||
} else {
|
||||
Assert::assertCount(1, $form->filter(static::DEFAULT_SAVE_BUTTON_SELECTOR), sprintf('The following HTML does not contain the save button. %s', $html));
|
||||
}
|
||||
}
|
||||
|
||||
public static function frequencyFormRenderingDataProvider(): \Generator
|
||||
{
|
||||
yield 'Custom Preference Center: All preferences enabled' => [
|
||||
[
|
||||
'show_contact_segments' => 1,
|
||||
'show_contact_categories' => 1,
|
||||
'show_contact_preferred_channels' => 1,
|
||||
'show_contact_frequency' => 1,
|
||||
'show_contact_pause_dates' => 1,
|
||||
],
|
||||
[
|
||||
static::CUSTOM_SEGMENT_SELECTOR => 1, // determined by show_contact_segments
|
||||
static::CUSTOM_CATEGORY_SELECTOR => 1, // determined by show_contact_categories
|
||||
static::CUSTOM_PREFERRED_CHANNEL_SELECTOR => 1, // determined by show_contact_preferred_channels
|
||||
static::CUSTOM_CHANNEL_FREQ_SELECTOR => 1, // determined by EITHER show_contact_frequency & show_contact_pause_dates
|
||||
],
|
||||
true,
|
||||
];
|
||||
|
||||
yield 'Custom Preference Center: Segments & Categories disabled' => [
|
||||
[
|
||||
'show_contact_segments' => 0,
|
||||
'show_contact_categories' => 0,
|
||||
'show_contact_preferred_channels' => 1,
|
||||
'show_contact_frequency' => 1,
|
||||
'show_contact_pause_dates' => 1,
|
||||
],
|
||||
[
|
||||
static::CUSTOM_SEGMENT_SELECTOR => 0, // determined by show_contact_segments
|
||||
static::CUSTOM_CATEGORY_SELECTOR => 0, // determined by show_contact_categories
|
||||
static::CUSTOM_PREFERRED_CHANNEL_SELECTOR => 1, // determined by show_contact_preferred_channels
|
||||
static::CUSTOM_CHANNEL_FREQ_SELECTOR => 1, // determined by EITHER show_contact_frequency & show_contact_pause_dates
|
||||
],
|
||||
true,
|
||||
];
|
||||
|
||||
yield 'Custom Preference Center: Preferred Channels & Frequency disabled' => [
|
||||
[
|
||||
'show_contact_segments' => 1,
|
||||
'show_contact_categories' => 1,
|
||||
'show_contact_preferred_channels' => 0,
|
||||
'show_contact_frequency' => 0,
|
||||
'show_contact_pause_dates' => 0,
|
||||
],
|
||||
[
|
||||
static::CUSTOM_SEGMENT_SELECTOR => 1, // determined by show_contact_segments
|
||||
static::CUSTOM_CATEGORY_SELECTOR => 1, // determined by show_contact_categories
|
||||
static::CUSTOM_PREFERRED_CHANNEL_SELECTOR => 0, // determined by show_contact_preferred_channels
|
||||
static::CUSTOM_CHANNEL_FREQ_SELECTOR => 0, // determined by EITHER show_contact_frequency & show_contact_pause_dates
|
||||
],
|
||||
true,
|
||||
];
|
||||
|
||||
yield 'Custom Preference Center: Frequency enabled & Pause Dates disabled' => [
|
||||
[
|
||||
'show_contact_segments' => 0,
|
||||
'show_contact_categories' => 0,
|
||||
'show_contact_preferred_channels' => 0,
|
||||
'show_contact_frequency' => 1,
|
||||
'show_contact_pause_dates' => 0,
|
||||
],
|
||||
[
|
||||
static::CUSTOM_SEGMENT_SELECTOR => 0, // determined by show_contact_segments
|
||||
static::CUSTOM_CATEGORY_SELECTOR => 0, // determined by show_contact_categories
|
||||
static::CUSTOM_PREFERRED_CHANNEL_SELECTOR => 0, // determined by show_contact_preferred_channels
|
||||
static::CUSTOM_CHANNEL_FREQ_SELECTOR => 1, // determined by EITHER show_contact_frequency & show_contact_pause_dates
|
||||
],
|
||||
true,
|
||||
];
|
||||
|
||||
yield 'Custom Preference Center: Frequency disabled & Pause Dates enabled' => [
|
||||
[
|
||||
'show_contact_segments' => 0,
|
||||
'show_contact_categories' => 0,
|
||||
'show_contact_preferred_channels' => 0,
|
||||
'show_contact_frequency' => 0,
|
||||
'show_contact_pause_dates' => 1,
|
||||
],
|
||||
[
|
||||
static::CUSTOM_SEGMENT_SELECTOR => 0, // determined by show_contact_segments
|
||||
static::CUSTOM_CATEGORY_SELECTOR => 0, // determined by show_contact_categories
|
||||
static::CUSTOM_PREFERRED_CHANNEL_SELECTOR => 0, // determined by show_contact_preferred_channels
|
||||
static::CUSTOM_CHANNEL_FREQ_SELECTOR => 0, // determined by show_contact_frequency
|
||||
static::DEFAULT_PAUSE_DATES_SELECTOR => 1, // determined by show_contact_pause_dates
|
||||
],
|
||||
true,
|
||||
];
|
||||
|
||||
yield 'Custom Preference Center: All preferences disabled' => [
|
||||
[
|
||||
'show_contact_segments' => 0,
|
||||
'show_contact_categories' => 0,
|
||||
'show_contact_preferred_channels' => 0,
|
||||
'show_contact_frequency' => 0,
|
||||
'show_contact_pause_dates' => 0,
|
||||
],
|
||||
[
|
||||
static::CUSTOM_SEGMENT_SELECTOR => 0, // determined by show_contact_segments
|
||||
static::CUSTOM_CATEGORY_SELECTOR => 0, // determined by show_contact_categories
|
||||
static::CUSTOM_PREFERRED_CHANNEL_SELECTOR => 0, // determined by show_contact_preferred_channels
|
||||
static::CUSTOM_CHANNEL_FREQ_SELECTOR => 0, // determined by EITHER show_contact_frequency & show_contact_pause_dates
|
||||
],
|
||||
true,
|
||||
];
|
||||
|
||||
yield 'Default Preference Center: All preferences enabled' => [
|
||||
[
|
||||
'show_contact_segments' => 1,
|
||||
'show_contact_categories' => 1,
|
||||
'show_contact_preferred_channels' => 1,
|
||||
'show_contact_frequency' => 1,
|
||||
'show_contact_pause_dates' => 1,
|
||||
],
|
||||
[
|
||||
static::DEFAULT_SEGMENT_SELECTOR => 1, // determined by show_contact_segments
|
||||
static::DEFAULT_CATEGORY_SELECTOR => 1, // determined by show_contact_categories
|
||||
static::DEFAULT_PREFERRED_CHANNEL_SELECTOR => 1, // determined by show_contact_preferred_channels
|
||||
static::DEFAULT_CHANNEL_FREQ_SELECTOR => 1, // determined by show_contact_frequency. This differs from a custom page.
|
||||
static::DEFAULT_PAUSE_DATES_SELECTOR => 1, // determined FIRST by show_contact_frequency, then by show_contact_pause_dates
|
||||
],
|
||||
false,
|
||||
];
|
||||
|
||||
yield 'Default Preference Center: Segments & Categories disabled' => [
|
||||
[
|
||||
'show_contact_segments' => 0,
|
||||
'show_contact_categories' => 0,
|
||||
'show_contact_preferred_channels' => 1,
|
||||
'show_contact_frequency' => 1,
|
||||
'show_contact_pause_dates' => 1,
|
||||
],
|
||||
[
|
||||
static::DEFAULT_SEGMENT_SELECTOR => 0, // determined by show_contact_segments
|
||||
static::DEFAULT_CATEGORY_SELECTOR => 0, // determined by show_contact_categories
|
||||
static::DEFAULT_PREFERRED_CHANNEL_SELECTOR => 1, // determined by show_contact_preferred_channels
|
||||
static::DEFAULT_CHANNEL_FREQ_SELECTOR => 1, // determined by show_contact_frequency. This differs from a custom page.
|
||||
static::DEFAULT_PAUSE_DATES_SELECTOR => 1, // determined FIRST by show_contact_frequency, then by show_contact_pause_dates
|
||||
],
|
||||
false,
|
||||
];
|
||||
|
||||
yield 'Default Preference Center: Preferred Channels & Frequency disabled' => [
|
||||
[
|
||||
'show_contact_segments' => 1,
|
||||
'show_contact_categories' => 1,
|
||||
'show_contact_preferred_channels' => 0,
|
||||
'show_contact_frequency' => 0,
|
||||
'show_contact_pause_dates' => 0,
|
||||
],
|
||||
[
|
||||
static::DEFAULT_SEGMENT_SELECTOR => 1, // determined by show_contact_segments
|
||||
static::DEFAULT_CATEGORY_SELECTOR => 1, // determined by show_contact_categories
|
||||
static::DEFAULT_PREFERRED_CHANNEL_SELECTOR => 0, // determined by show_contact_preferred_channels
|
||||
static::DEFAULT_CHANNEL_FREQ_SELECTOR => 0, // determined by show_contact_frequency. This differs from a custom page.
|
||||
static::DEFAULT_PAUSE_DATES_SELECTOR => 0, // determined FIRST by show_contact_frequency, then by show_contact_pause_dates
|
||||
],
|
||||
false,
|
||||
];
|
||||
|
||||
yield 'Default Preference Center: Frequency enabled & Pause Dates disabled' => [
|
||||
[
|
||||
'show_contact_segments' => 0,
|
||||
'show_contact_categories' => 0,
|
||||
'show_contact_preferred_channels' => 0,
|
||||
'show_contact_frequency' => 1,
|
||||
'show_contact_pause_dates' => 0,
|
||||
],
|
||||
[
|
||||
static::DEFAULT_SEGMENT_SELECTOR => 0, // determined by show_contact_segments
|
||||
static::DEFAULT_CATEGORY_SELECTOR => 0, // determined by show_contact_categories
|
||||
static::DEFAULT_PREFERRED_CHANNEL_SELECTOR => 0, // determined by show_contact_preferred_channels
|
||||
static::DEFAULT_CHANNEL_FREQ_SELECTOR => 1, // determined by show_contact_frequency. This differs from a custom page.
|
||||
static::DEFAULT_PAUSE_DATES_SELECTOR => 0, // determined FIRST by show_contact_frequency, then by show_contact_pause_dates
|
||||
],
|
||||
false,
|
||||
];
|
||||
|
||||
yield 'Default Preference Center: Frequency disabled & Pause Dates enabled' => [
|
||||
[
|
||||
'show_contact_segments' => 0,
|
||||
'show_contact_categories' => 0,
|
||||
'show_contact_preferred_channels' => 0,
|
||||
'show_contact_frequency' => 0,
|
||||
'show_contact_pause_dates' => 1,
|
||||
],
|
||||
[
|
||||
static::DEFAULT_SEGMENT_SELECTOR => 0, // determined by show_contact_segments
|
||||
static::DEFAULT_CATEGORY_SELECTOR => 0, // determined by show_contact_categories
|
||||
static::DEFAULT_PREFERRED_CHANNEL_SELECTOR => 0, // determined by show_contact_preferred_channels
|
||||
static::DEFAULT_CHANNEL_FREQ_SELECTOR => 0, // determined by show_contact_frequency. This differs from a custom page.
|
||||
static::DEFAULT_PAUSE_DATES_SELECTOR => 0, // determined FIRST by show_contact_frequency, then by show_contact_pause_dates
|
||||
],
|
||||
false,
|
||||
];
|
||||
|
||||
yield 'Default Preference Center: All preferences disabled' => [
|
||||
[
|
||||
'show_contact_segments' => 0,
|
||||
'show_contact_categories' => 0,
|
||||
'show_contact_preferred_channels' => 0,
|
||||
'show_contact_frequency' => 0,
|
||||
'show_contact_pause_dates' => 0,
|
||||
],
|
||||
[
|
||||
static::DEFAULT_SEGMENT_SELECTOR => 0, // determined by show_contact_segments
|
||||
static::DEFAULT_CATEGORY_SELECTOR => 0, // determined by show_contact_categories
|
||||
static::DEFAULT_PREFERRED_CHANNEL_SELECTOR => 0, // determined by show_contact_preferred_channels
|
||||
static::DEFAULT_CHANNEL_FREQ_SELECTOR => 0, // determined by show_contact_frequency. This differs from a custom page.
|
||||
static::DEFAULT_PAUSE_DATES_SELECTOR => 0, // determined FIRST by show_contact_frequency, then by show_contact_pause_dates
|
||||
],
|
||||
false,
|
||||
];
|
||||
}
|
||||
|
||||
private function createStat(Email $email, Lead $lead): Stat
|
||||
{
|
||||
$stat = new Stat();
|
||||
$stat->setEmail($email);
|
||||
$stat->setLead($lead);
|
||||
$stat->setEmailAddress($lead->getEmail());
|
||||
$stat->setDateSent(new \DateTime());
|
||||
$stat->setTrackingHash(uniqid());
|
||||
$this->em->persist($stat);
|
||||
|
||||
return $stat;
|
||||
}
|
||||
|
||||
private function createEmail(bool $hasPreferenceCenter = true): Email
|
||||
{
|
||||
$email = new Email();
|
||||
$email->setName('Example');
|
||||
|
||||
if ($hasPreferenceCenter) {
|
||||
$email->setPreferenceCenter($this->createPage());
|
||||
}
|
||||
|
||||
$this->em->persist($email);
|
||||
|
||||
return $email;
|
||||
}
|
||||
|
||||
private function createLead(): Lead
|
||||
{
|
||||
$lead = new Lead();
|
||||
$lead->setEmail('test@example.com');
|
||||
$this->em->persist($lead);
|
||||
|
||||
return $lead;
|
||||
}
|
||||
|
||||
private function createSegment(): Segment
|
||||
{
|
||||
$segment = new Segment();
|
||||
$segment->setName('My Segment');
|
||||
$segment->setPublicName('My Segment');
|
||||
$segment->setAlias('my-segment');
|
||||
$segment->setIsPreferenceCenter(true);
|
||||
$this->em->persist($segment);
|
||||
|
||||
return $segment;
|
||||
}
|
||||
|
||||
private function createCategory(): Category
|
||||
{
|
||||
$category = new Category();
|
||||
$category->setTitle('My Category');
|
||||
$category->setAlias('my-category');
|
||||
$category->setIsPublished(true);
|
||||
$category->setBundle('global');
|
||||
$this->em->persist($category);
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
private function createPage(): Page
|
||||
{
|
||||
$page = new Page();
|
||||
$page->setTitle('Preference Center');
|
||||
$page->setAlias('preference-center');
|
||||
$page->setIsPreferenceCenter(true);
|
||||
$page->setCustomHtml($this->getPageContent());
|
||||
$page->setIsPublished(true);
|
||||
$this->em->persist($page);
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
private function getPageContent(): string
|
||||
{
|
||||
return <<<PAGE
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||
<head>
|
||||
<title>{pagetitle}</title>
|
||||
<meta name="description" content="{pagemetadescription}">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
{langbar}
|
||||
{sharebuttons}
|
||||
</div>
|
||||
<div>
|
||||
{successmessage}
|
||||
<div>
|
||||
{segmentlist}
|
||||
</div>
|
||||
<div>
|
||||
{categorylist}
|
||||
</div>
|
||||
<div>
|
||||
{preferredchannel}
|
||||
</div>
|
||||
<div>
|
||||
{channelfrequency}
|
||||
</div>
|
||||
<div>
|
||||
{saveprefsbutton}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
PAGE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PageBundle\Tests\Functional\Model;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\EmailBundle\Entity\Email;
|
||||
use Mautic\EmailBundle\Entity\Stat;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\PageBundle\Entity\Hit;
|
||||
use Mautic\PageBundle\Entity\HitRepository;
|
||||
use Mautic\PageBundle\Entity\Page;
|
||||
use Mautic\PageBundle\Entity\Redirect;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class PageModelTest extends MauticMysqlTestCase
|
||||
{
|
||||
private HitRepository $pageHitRepository;
|
||||
|
||||
private const DO_NOT_TRACK_IP = '218.30.65.10';
|
||||
|
||||
private const BOT_BLOCKED_IP = '218.30.65.11';
|
||||
|
||||
private const IP_NOT_IN_ANY_BLOCK_LIST = '218.30.65.12';
|
||||
|
||||
private const IP_NOT_IN_ANY_BLOCK_LIST2 = '218.30.65.111';
|
||||
|
||||
private const BOT_BLOCKED_USER_AGENTS = [
|
||||
'AHC/2.1',
|
||||
'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6',
|
||||
'Mozilla/5.0 (compatible; Codewisebot/2.0; +http://www.nosite.com/somebot.htm)',
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 8_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B411 Safari/600.1.4 (compatible; YandexMobileBot/3.0; +http://yandex.com/bots)',
|
||||
'serpstatbot/2.0 beta (advanced backlink tracking bot; http://serpstatbot.com/; abuse@serpstatbot.com)',
|
||||
'Mozilla/5.0 (Linux; Android 7.0;) AppleWebKit/537.36 (KHTML, like Gecko) Mobile Safari/537.36 (compatible; AspiegelBot)',
|
||||
'serpstatbot/2.1 (advanced backlink tracking bot; https://serpstatbot.com/; abuse@serpstatbot.com)',
|
||||
];
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->configParams['do_not_track_ips'] = [self::DO_NOT_TRACK_IP];
|
||||
$this->configParams['bot_helper_blocked_ip_addresses'] = [self::BOT_BLOCKED_IP];
|
||||
$this->configParams['bot_helper_blocked_user_agents'] = self::BOT_BLOCKED_USER_AGENTS;
|
||||
$this->configParams['site_url'] = 'https://mautic-cloud.local';
|
||||
parent::setUp();
|
||||
$this->pageHitRepository = $this->em->getRepository(Hit::class);
|
||||
$this->logoutUser();
|
||||
}
|
||||
|
||||
public function testItRegistersPageHitsWithFieldValues(): void
|
||||
{
|
||||
$requestParameters = [
|
||||
'page_title' => $this->generateRandomUTF8String(512),
|
||||
'page_language' => $this->generateRandomUTF8String(512),
|
||||
'page_url' => 'https://some.page.url/test/'.$this->generateRandomUTF8String(512),
|
||||
'counter' => 0,
|
||||
'timezone_offset' => -120,
|
||||
'resolution' => '2560x1440',
|
||||
'platform' => 'MacOs',
|
||||
'do_not_track' => 'false',
|
||||
'mautic_device_id' => 'some_device_id',
|
||||
];
|
||||
$this->client->request(Request::METHOD_POST, '/mtc/event', $requestParameters);
|
||||
/** @var Hit $pageHit */
|
||||
$pageHit = $this->pageHitRepository->findOneBy([]);
|
||||
Assert::assertInstanceOf(Hit::class, $pageHit);
|
||||
Assert::assertStringStartsWith($pageHit->getUrlTitle(), $requestParameters['page_title']);
|
||||
Assert::assertStringStartsWith($pageHit->getPageLanguage(), $requestParameters['page_language']);
|
||||
Assert::assertStringStartsWith($pageHit->getUrl(), $requestParameters['page_url']);
|
||||
}
|
||||
|
||||
public function generateRandomString(int $length): string
|
||||
{
|
||||
return substr(bin2hex(random_bytes($length)), 0, $length);
|
||||
}
|
||||
|
||||
public function generateRandomUTF8String(int $length): string
|
||||
{
|
||||
$result = '';
|
||||
|
||||
for ($i = 0; $i < $length; ++$i) {
|
||||
$codePoint = mt_rand(0x80, 0xFFFF);
|
||||
$char = \IntlChar::chr($codePoint);
|
||||
if (null !== $char && \IntlChar::isprint($char)) {
|
||||
$result .= $char;
|
||||
} else {
|
||||
--$i;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('pageHitBotScenariosProvider')]
|
||||
public function testItNotRegistersPageHitsFromBot(string $trackingHash, string $sentBefore, string $userAgent, string $ipAddress, bool $isHit): void
|
||||
{
|
||||
$lead = new Lead();
|
||||
$lead->setFirstname('Test Page Hit');
|
||||
$this->em->persist($lead);
|
||||
|
||||
$email = new Email();
|
||||
$email->setName('Email A');
|
||||
$email->setSubject('Email A Subject');
|
||||
$this->em->persist($email);
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
$emailId = $email->getId();
|
||||
$clickThrough = [
|
||||
'source' => ['email', $emailId],
|
||||
'email' => $emailId,
|
||||
'stat' => $trackingHash,
|
||||
'lead' => $lead->getId(),
|
||||
'channel' => [
|
||||
'email' => $emailId,
|
||||
],
|
||||
'mtc_redirect_destination' => 'https://some.page.url/test/redirect',
|
||||
];
|
||||
|
||||
$requestParameters = [
|
||||
'page_title' => $this->generateRandomString(50),
|
||||
'page_language' => $this->generateRandomString(50),
|
||||
'page_url' => 'https://some.page.url/test/'.$this->generateRandomString(50),
|
||||
'counter' => 0,
|
||||
'timezone_offset' => -120,
|
||||
'resolution' => '2560x1440',
|
||||
'platform' => 'MacOs',
|
||||
'do_not_track' => 'false',
|
||||
'mautic_device_id' => 'some_device_id',
|
||||
'ct' => base64_encode(serialize($clickThrough)),
|
||||
];
|
||||
|
||||
// Create Email Stat
|
||||
$emailStat = new Stat();
|
||||
$emailStat->setEmailAddress('lukas.sykora@acquia.com');
|
||||
$emailStat->setTrackingHash($trackingHash);
|
||||
$emailSendTime = new \DateTime();
|
||||
$emailStat->setDateSent($emailSendTime->modify($sentBefore));
|
||||
$this->em->persist($emailStat);
|
||||
$this->em->flush();
|
||||
|
||||
// Send Request
|
||||
$server = [
|
||||
'HTTP_USER_AGENT' => $userAgent,
|
||||
'REMOTE_ADDR' => $ipAddress,
|
||||
];
|
||||
$this->client->request(Request::METHOD_POST, '/mtc/event', $requestParameters, [], $server);
|
||||
/** @var Hit $pageHit */
|
||||
$pageHit = $this->pageHitRepository->findOneBy([]);
|
||||
|
||||
if ($isHit) {
|
||||
Assert::assertInstanceOf(Hit::class, $pageHit);
|
||||
Assert::assertStringStartsWith($pageHit->getUrlTitle(), $requestParameters['page_title']);
|
||||
Assert::assertStringStartsWith($pageHit->getPageLanguage(), $requestParameters['page_language']);
|
||||
Assert::assertStringStartsWith($pageHit->getUrl(), $requestParameters['page_url']);
|
||||
} else {
|
||||
Assert::assertNull($pageHit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<string, array<mixed>>
|
||||
*/
|
||||
public static function pageHitBotScenariosProvider(): iterable
|
||||
{
|
||||
// $trackingHash, $sentBefore, $userAgent, $ipAddress, $isHit
|
||||
yield 'All good' => ['test_hash_bot_ratio_1', '-80 second', 'Mozilla/5.0', self::IP_NOT_IN_ANY_BLOCK_LIST, true];
|
||||
yield 'Time and User' => ['test_hash_bot_ratio_2', '+80 second', 'AHC/2.1', self::IP_NOT_IN_ANY_BLOCK_LIST, false];
|
||||
yield 'Time and IP' => ['test_hash_bot_ratio_3', '+80 second', 'Mozilla/5.0', self::BOT_BLOCKED_IP, false];
|
||||
yield 'Permanently blocked IP' => ['test_hash_bot_ratio_4', '-80 second', 'Mozilla/5.0', self::DO_NOT_TRACK_IP, false];
|
||||
yield 'Bot Blocked IP address only' => ['test_hash_bot_ratio_5', '-80 second', 'Mozilla/5.0', self::BOT_BLOCKED_IP, true];
|
||||
yield 'Bot Blocked User Agent only' => ['test_hash_bot_ratio_6', '-80 second', 'AHC/2.1', self::IP_NOT_IN_ANY_BLOCK_LIST, true];
|
||||
yield 'Time Only' => ['test_hash_bot_ratio_7', '+80 second', 'Mozilla/5.0', self::IP_NOT_IN_ANY_BLOCK_LIST, true];
|
||||
yield 'Time and Bot User Agent and Bot IP' => ['test_hash_bot_ratio_8', '+80 second', 'AHC/2.1', self::BOT_BLOCKED_IP, false];
|
||||
yield 'Bot User Agent and Bot IP' => ['test_hash_bot_ratio_9', '-80 second', 'AHC/2.1', self::BOT_BLOCKED_IP, false];
|
||||
yield 'Permanently blocked User Agent' => ['test_hash_bot_ratio_10', '-80 second', 'MSNBOT', self::IP_NOT_IN_ANY_BLOCK_LIST2, false];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('pageHitBotScenariosProvider')]
|
||||
public function testRedirect(string $trackingHash, string $sentBefore, string $userAgent, string $ipAddress, bool $isHit): void
|
||||
{
|
||||
$lead = new Lead();
|
||||
$lead->setFirstname('Test Page Hit');
|
||||
$this->em->persist($lead);
|
||||
|
||||
$email = new Email();
|
||||
$email->setName('Email A');
|
||||
$email->setSubject('Email A Subject');
|
||||
$this->em->persist($email);
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
$page = new Page();
|
||||
$page->setTitle('Page A');
|
||||
$page->setAlias('page_a');
|
||||
$page->setCustomHtml('Page A');
|
||||
$page->setRedirectUrl('http://mautic-cloud.local/page_a');
|
||||
$this->em->persist($page);
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
$emailId = $email->getId();
|
||||
$clickThrough = [
|
||||
'source' => ['email', $emailId],
|
||||
'email' => $emailId,
|
||||
'stat' => $trackingHash,
|
||||
'lead' => $lead->getId(),
|
||||
'channel' => [
|
||||
'email' => $emailId,
|
||||
],
|
||||
'mtc_redirect_destination' => 'http://mautic-cloud.local/page_a',
|
||||
];
|
||||
|
||||
// Create Email Stat
|
||||
$emailStat = new Stat();
|
||||
$emailStat->setEmailAddress('lukas.sykora@acquia.com');
|
||||
$emailStat->setTrackingHash($trackingHash);
|
||||
$emailSendTime = new \DateTime();
|
||||
$emailStat->setDateSent($emailSendTime->modify($sentBefore));
|
||||
$this->em->persist($emailStat);
|
||||
$this->em->flush();
|
||||
|
||||
$redirectId = 'abc';
|
||||
$redirect = new Redirect();
|
||||
$redirect->setRedirectId($redirectId);
|
||||
$redirect->setUrl('http://mautic-cloud.local/page_a');
|
||||
$this->em->persist($redirect);
|
||||
$this->em->flush();
|
||||
|
||||
$redirectModel = $this->getContainer()->get('mautic.page.model.redirect');
|
||||
$redirectURL = $redirectModel->generateRedirectUrl($redirect, $clickThrough);
|
||||
// Send Request
|
||||
$server = [
|
||||
'HTTP_USER_AGENT' => $userAgent,
|
||||
'REMOTE_ADDR' => $ipAddress,
|
||||
];
|
||||
|
||||
$this->client->request(Request::METHOD_GET, $redirectURL, [], [], $server);
|
||||
/** @var Hit $pageHit */
|
||||
$pageHit = $this->pageHitRepository->findOneBy([]);
|
||||
|
||||
if ($isHit) {
|
||||
Assert::assertInstanceOf(Hit::class, $pageHit);
|
||||
Assert::assertStringStartsWith($pageHit->getUrl(), $page->getRedirectUrl());
|
||||
} else {
|
||||
Assert::assertNull($pageHit);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user