Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Tests\Functional\Controller;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\PointBundle\Entity\Point;
|
||||
use Mautic\ProjectBundle\Entity\Project;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
final class PointControllerTest extends MauticMysqlTestCase
|
||||
{
|
||||
public function testPointWithProject(): void
|
||||
{
|
||||
$point = new Point();
|
||||
$point->setName('test');
|
||||
$point->setType('url.hit');
|
||||
$this->em->persist($point);
|
||||
|
||||
$project = new Project();
|
||||
$project->setName('Test Project');
|
||||
$this->em->persist($project);
|
||||
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$crawler = $this->client->request('GET', '/s/points/edit/'.$point->getId());
|
||||
$form = $crawler->selectButton('Save')->form();
|
||||
$form['point[projects]']->setValue((string) $project->getId());
|
||||
|
||||
$this->client->submit($form);
|
||||
|
||||
$this->assertResponseIsSuccessful();
|
||||
|
||||
$savedAsset = $this->em->find(Point::class, $point->getId());
|
||||
Assert::assertSame($project->getId(), $savedAsset->getProjects()->first()->getId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Tests\Functional\Controller;
|
||||
|
||||
use Mautic\PointBundle\Entity\Point;
|
||||
use Mautic\ProjectBundle\Tests\Functional\AbstractProjectSearchTestCase;
|
||||
|
||||
final class PointProjectSearchFunctionalTest extends AbstractProjectSearchTestCase
|
||||
{
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('searchDataProvider')]
|
||||
public function testProjectSearch(string $searchTerm, array $expectedEntities, array $unexpectedEntities): void
|
||||
{
|
||||
$projectOne = $this->createProject('Project One');
|
||||
$projectTwo = $this->createProject('Project Two');
|
||||
$projectThree = $this->createProject('Project Three');
|
||||
|
||||
$pointAlpha = $this->createPoint('Point Alpha');
|
||||
$pointBeta = $this->createPoint('Point Beta');
|
||||
$this->createPoint('Point Gamma');
|
||||
$this->createPoint('Point Delta');
|
||||
|
||||
$pointAlpha->addProject($projectOne);
|
||||
$pointAlpha->addProject($projectTwo);
|
||||
$pointBeta->addProject($projectTwo);
|
||||
$pointBeta->addProject($projectThree);
|
||||
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$this->searchAndAssert($searchTerm, $expectedEntities, $unexpectedEntities, ['/api/points', '/s/points']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Generator<string, array{searchTerm: string, expectedEntities: array<string>, unexpectedEntities: array<string>}>
|
||||
*/
|
||||
public static function searchDataProvider(): \Generator
|
||||
{
|
||||
yield 'search by one project' => [
|
||||
'searchTerm' => 'project:"Project Two"',
|
||||
'expectedEntities' => ['Point Alpha', 'Point Beta'],
|
||||
'unexpectedEntities' => ['Point Gamma', 'Point Delta'],
|
||||
];
|
||||
|
||||
yield 'search by one project AND point name' => [
|
||||
'searchTerm' => 'project:"Project Two" AND Beta',
|
||||
'expectedEntities' => ['Point Beta'],
|
||||
'unexpectedEntities' => ['Point Alpha', 'Point Gamma', 'Point Delta'],
|
||||
];
|
||||
|
||||
yield 'search by one project OR point name' => [
|
||||
'searchTerm' => 'project:"Project Two" OR Gamma',
|
||||
'expectedEntities' => ['Point Alpha', 'Point Beta', 'Point Gamma'],
|
||||
'unexpectedEntities' => ['Point Delta'],
|
||||
];
|
||||
|
||||
yield 'search by NOT one project' => [
|
||||
'searchTerm' => '!project:"Project Two"',
|
||||
'expectedEntities' => ['Point Gamma', 'Point Delta'],
|
||||
'unexpectedEntities' => ['Point Alpha', 'Point Beta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with AND' => [
|
||||
'searchTerm' => 'project:"Project Two" AND project:"Project Three"',
|
||||
'expectedEntities' => ['Point Beta'],
|
||||
'unexpectedEntities' => ['Point Alpha', 'Point Gamma', 'Point Delta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with NOT AND' => [
|
||||
'searchTerm' => '!project:"Project Two" AND !project:"Project Three"',
|
||||
'expectedEntities' => ['Point Gamma', 'Point Delta'],
|
||||
'unexpectedEntities' => ['Point Alpha', 'Point Beta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with OR' => [
|
||||
'searchTerm' => 'project:"Project Two" OR project:"Project Three"',
|
||||
'expectedEntities' => ['Point Alpha', 'Point Beta'],
|
||||
'unexpectedEntities' => ['Point Gamma', 'Point Delta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with NOT OR' => [
|
||||
'searchTerm' => '!project:"Project Two" OR !project:"Project Three"',
|
||||
'expectedEntities' => ['Point Alpha', 'Point Gamma', 'Point Delta'],
|
||||
'unexpectedEntities' => ['Point Beta'],
|
||||
];
|
||||
}
|
||||
|
||||
private function createPoint(string $name): Point
|
||||
{
|
||||
$point = new Point();
|
||||
$point->setName($name);
|
||||
$point->setType('url.hit');
|
||||
$this->em->persist($point);
|
||||
|
||||
return $point;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Tests\Functional\Controller;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\PointBundle\Entity\Trigger;
|
||||
use Mautic\ProjectBundle\Entity\Project;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
final class TriggerControllerTest extends MauticMysqlTestCase
|
||||
{
|
||||
public function testPointTriggerWithProject(): void
|
||||
{
|
||||
$trigger = new Trigger();
|
||||
$trigger->setName('test');
|
||||
$this->em->persist($trigger);
|
||||
|
||||
$project = new Project();
|
||||
$project->setName('Test Project');
|
||||
$this->em->persist($project);
|
||||
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$crawler = $this->client->request('GET', '/s/points/triggers/edit/'.$trigger->getId());
|
||||
$form = $crawler->selectButton('Save')->form();
|
||||
$form['pointtrigger[projects]']->setValue((string) $project->getId());
|
||||
|
||||
$this->client->submit($form);
|
||||
|
||||
$this->assertResponseIsSuccessful();
|
||||
|
||||
$savedAsset = $this->em->find(Trigger::class, $trigger->getId());
|
||||
Assert::assertSame($project->getId(), $savedAsset->getProjects()->first()->getId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Tests\Functional\Controller;
|
||||
|
||||
use Mautic\PointBundle\Entity\Trigger;
|
||||
use Mautic\ProjectBundle\Tests\Functional\AbstractProjectSearchTestCase;
|
||||
|
||||
final class TriggerProjectSearchFunctionalTest extends AbstractProjectSearchTestCase
|
||||
{
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('searchDataProvider')]
|
||||
public function testProjectSearch(string $searchTerm, array $expectedEntities, array $unexpectedEntities): void
|
||||
{
|
||||
$projectOne = $this->createProject('Project One');
|
||||
$projectTwo = $this->createProject('Project Two');
|
||||
$projectThree = $this->createProject('Project Three');
|
||||
|
||||
$triggerAlpha = $this->createTrigger('Trigger Alpha');
|
||||
$triggerBeta = $this->createTrigger('Trigger Beta');
|
||||
$this->createTrigger('Trigger Gamma');
|
||||
$this->createTrigger('Trigger Delta');
|
||||
|
||||
$triggerAlpha->addProject($projectOne);
|
||||
$triggerAlpha->addProject($projectTwo);
|
||||
$triggerBeta->addProject($projectTwo);
|
||||
$triggerBeta->addProject($projectThree);
|
||||
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$this->searchAndAssert($searchTerm, $expectedEntities, $unexpectedEntities, ['/api/points/triggers', '/s/points/triggers']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Generator<string, array{searchTerm: string, expectedEntities: array<string>, unexpectedEntities: array<string>}>
|
||||
*/
|
||||
public static function searchDataProvider(): \Generator
|
||||
{
|
||||
yield 'search by one project' => [
|
||||
'searchTerm' => 'project:"Project Two"',
|
||||
'expectedEntities' => ['Trigger Alpha', 'Trigger Beta'],
|
||||
'unexpectedEntities' => ['Trigger Gamma', 'Trigger Delta'],
|
||||
];
|
||||
|
||||
yield 'search by one project AND trigger name' => [
|
||||
'searchTerm' => 'project:"Project Two" AND Beta',
|
||||
'expectedEntities' => ['Trigger Beta'],
|
||||
'unexpectedEntities' => ['Trigger Alpha', 'Trigger Gamma', 'Trigger Delta'],
|
||||
];
|
||||
|
||||
yield 'search by one project OR trigger name' => [
|
||||
'searchTerm' => 'project:"Project Two" OR Gamma',
|
||||
'expectedEntities' => ['Trigger Alpha', 'Trigger Beta', 'Trigger Gamma'],
|
||||
'unexpectedEntities' => ['Trigger Delta'],
|
||||
];
|
||||
|
||||
yield 'search by NOT one project' => [
|
||||
'searchTerm' => '!project:"Project Two"',
|
||||
'expectedEntities' => ['Trigger Gamma', 'Trigger Delta'],
|
||||
'unexpectedEntities' => ['Trigger Alpha', 'Trigger Beta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with AND' => [
|
||||
'searchTerm' => 'project:"Project Two" AND project:"Project Three"',
|
||||
'expectedEntities' => ['Trigger Beta'],
|
||||
'unexpectedEntities' => ['Trigger Alpha', 'Trigger Gamma', 'Trigger Delta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with NOT AND' => [
|
||||
'searchTerm' => '!project:"Project Two" AND !project:"Project Three"',
|
||||
'expectedEntities' => ['Trigger Gamma', 'Trigger Delta'],
|
||||
'unexpectedEntities' => ['Trigger Alpha', 'Trigger Beta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with OR' => [
|
||||
'searchTerm' => 'project:"Project Two" OR project:"Project Three"',
|
||||
'expectedEntities' => ['Trigger Alpha', 'Trigger Beta'],
|
||||
'unexpectedEntities' => ['Trigger Gamma', 'Trigger Delta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with NOT OR' => [
|
||||
'searchTerm' => '!project:"Project Two" OR !project:"Project Three"',
|
||||
'expectedEntities' => ['Trigger Alpha', 'Trigger Gamma', 'Trigger Delta'],
|
||||
'unexpectedEntities' => ['Trigger Beta'],
|
||||
];
|
||||
}
|
||||
|
||||
private function createTrigger(string $name): Trigger
|
||||
{
|
||||
$trigger = new Trigger();
|
||||
$trigger->setName($name);
|
||||
$this->em->persist($trigger);
|
||||
|
||||
return $trigger;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Tests\Functional;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\EmailBundle\Entity\Email;
|
||||
use Mautic\PointBundle\Entity\Trigger;
|
||||
use Mautic\PointBundle\Entity\TriggerEvent;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use Symfony\Component\DomCrawler\Form;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class EmailTriggerTest extends MauticMysqlTestCase
|
||||
{
|
||||
#[\PHPUnit\Framework\Attributes\PreserveGlobalState(false)]
|
||||
#[\PHPUnit\Framework\Attributes\RunInSeparateProcess]
|
||||
public function testButtonsAreEnabledOnEditSendEmailToUserWhenEmailIsSelected(): void
|
||||
{
|
||||
$email = new Email();
|
||||
$email->setName('Some name');
|
||||
$email->setSubject('Some subject');
|
||||
$email->setTemplate('Blank');
|
||||
$email->setCustomHtml('Some html');
|
||||
$this->em->persist($email);
|
||||
$this->em->flush();
|
||||
|
||||
$trigger = $this->createTrigger();
|
||||
$triggerEvent = $this->createTriggerEvent($trigger);
|
||||
$triggerEvent->setProperties(['useremail' => ['email' => $email->getId()]]);
|
||||
|
||||
$this->em->flush();
|
||||
$this->em->detach($trigger);
|
||||
$this->em->detach($triggerEvent);
|
||||
|
||||
[$crawler, $form] = $this->fetchForm($trigger, $triggerEvent);
|
||||
|
||||
self::assertEquals($email->getId(), $form->get('pointtriggerevent[properties][useremail][email]')->getValue(), 'Current email should be selected.');
|
||||
self::assertNull($crawler->selectButton('Preview')->attr('disabled'), 'Preview button should not be disabled.');
|
||||
self::assertNull($crawler->selectButton('Edit Email')->attr('disabled'), 'Edit Email button should not be disabled.');
|
||||
self::assertStringContainsString('"origin":"#pointtriggerevent_properties_useremail_email"', $crawler->selectButton('Preview')->attr('onclick'), 'The origin value should be correct.');
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\PreserveGlobalState(false)]
|
||||
#[\PHPUnit\Framework\Attributes\RunInSeparateProcess]
|
||||
public function testButtonsAreDisabledWhenEmailIsNotSelected(): void
|
||||
{
|
||||
$trigger = $this->createTrigger();
|
||||
$triggerEvent = $this->createTriggerEvent($trigger);
|
||||
|
||||
$this->em->flush();
|
||||
$this->em->detach($trigger);
|
||||
$this->em->detach($triggerEvent);
|
||||
|
||||
[$crawler, $form] = $this->fetchForm($trigger, $triggerEvent);
|
||||
|
||||
self::assertEmpty($form->get('pointtriggerevent[properties][useremail][email]')->getValue(), 'No email should be selected.');
|
||||
self::assertNotNull($crawler->selectButton('Preview')->attr('disabled'), 'Preview button should be disabled.');
|
||||
self::assertNotNull($crawler->selectButton('Edit Email')->attr('disabled'), 'Edit Email button should be disabled.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{Crawler,Form}
|
||||
*/
|
||||
private function fetchForm(Trigger $trigger, TriggerEvent $triggerEvent): array
|
||||
{
|
||||
$this->client->request(Request::METHOD_GET, '/s/points/triggers/edit/'.$trigger->getId());
|
||||
self::assertTrue($this->client->getResponse()->isSuccessful());
|
||||
|
||||
$uri = sprintf('/s/points/triggers/events/edit/%s?triggerId=%s', $triggerEvent->getId(), $trigger->getId());
|
||||
$this->client->xmlHttpRequest(Request::METHOD_GET, $uri);
|
||||
self::assertTrue($this->client->getResponse()->isSuccessful());
|
||||
|
||||
$responseData = json_decode($this->client->getResponse()->getContent(), true);
|
||||
$crawler = new Crawler($responseData['newContent'], $this->client->getInternalRequest()->getUri());
|
||||
|
||||
$form = $crawler->filterXPath('//form[@name="pointtriggerevent"]')->form();
|
||||
|
||||
return [$crawler, $form];
|
||||
}
|
||||
|
||||
private function createTrigger(): Trigger
|
||||
{
|
||||
$trigger = new Trigger();
|
||||
$trigger->setName('Email Trigger');
|
||||
$this->em->persist($trigger);
|
||||
|
||||
return $trigger;
|
||||
}
|
||||
|
||||
private function createTriggerEvent(Trigger $trigger): TriggerEvent
|
||||
{
|
||||
$triggerEvent = new TriggerEvent();
|
||||
$triggerEvent->setTrigger($trigger);
|
||||
$triggerEvent->setName('Send email to user');
|
||||
$triggerEvent->setType('email.send_to_user');
|
||||
$triggerEvent->setProperties([]);
|
||||
$this->em->persist($triggerEvent);
|
||||
|
||||
return $triggerEvent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Tests\Functional;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\PointBundle\Entity\Group;
|
||||
use Mautic\PointBundle\Entity\GroupContactScore;
|
||||
use Mautic\PointBundle\Entity\GroupContactScoreRepository;
|
||||
|
||||
class GroupScoreRepositoryFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
protected $useCleanupRollback = false;
|
||||
|
||||
protected GroupContactScoreRepository $repository;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->repository = $this->em->getRepository(GroupContactScore::class);
|
||||
}
|
||||
|
||||
public function testCompareScore(): void
|
||||
{
|
||||
$contact = $this->createContact('score@example.com');
|
||||
|
||||
$group = $this->createGroup('A');
|
||||
$this->addGroupContactScore($contact, $group, 7);
|
||||
$this->em->flush();
|
||||
|
||||
$this->assertTrue($this->repository->compareScore($contact->getId(), $group->getId(), 7, 'eq'));
|
||||
$this->assertFalse($this->repository->compareScore($contact->getId(), $group->getId(), 8, 'eq'));
|
||||
|
||||
$this->assertTrue($this->repository->compareScore($contact->getId(), $group->getId(), 8, 'neq'));
|
||||
$this->assertFalse($this->repository->compareScore($contact->getId(), $group->getId(), 7, 'neq'));
|
||||
|
||||
$this->assertTrue($this->repository->compareScore($contact->getId(), $group->getId(), 6, 'gt'));
|
||||
$this->assertFalse($this->repository->compareScore($contact->getId(), $group->getId(), 7, 'gt'));
|
||||
|
||||
$this->assertTrue($this->repository->compareScore($contact->getId(), $group->getId(), 8, 'lt'));
|
||||
$this->assertFalse($this->repository->compareScore($contact->getId(), $group->getId(), 7, 'lt'));
|
||||
|
||||
$this->assertTrue($this->repository->compareScore($contact->getId(), $group->getId(), 7, 'gte'));
|
||||
$this->assertTrue($this->repository->compareScore($contact->getId(), $group->getId(), 6, 'gte'));
|
||||
$this->assertFalse($this->repository->compareScore($contact->getId(), $group->getId(), 8, 'gte'));
|
||||
|
||||
$this->assertTrue($this->repository->compareScore($contact->getId(), $group->getId(), 7, 'lte'));
|
||||
$this->assertTrue($this->repository->compareScore($contact->getId(), $group->getId(), 8, 'lte'));
|
||||
$this->assertFalse($this->repository->compareScore($contact->getId(), $group->getId(), 6, 'lte'));
|
||||
}
|
||||
|
||||
public function testCompareScoreContactWithoutScoreInGroup(): void
|
||||
{
|
||||
$contactWithoutScore = $this->createContact('no-score@example.com');
|
||||
$group = $this->createGroup('A');
|
||||
$this->em->flush();
|
||||
|
||||
$this->assertFalse($this->repository->compareScore($contactWithoutScore->getId(), $group->getId(), 0, 'eq'));
|
||||
$this->assertFalse($this->repository->compareScore($contactWithoutScore->getId(), $group->getId(), 1, 'eq'));
|
||||
}
|
||||
|
||||
private function createContact(
|
||||
string $email,
|
||||
): Lead {
|
||||
$lead = new Lead();
|
||||
$lead->setEmail($email);
|
||||
$this->em->persist($lead);
|
||||
|
||||
return $lead;
|
||||
}
|
||||
|
||||
private function createGroup(
|
||||
string $name,
|
||||
): Group {
|
||||
$group = new Group();
|
||||
$group->setName($name);
|
||||
$this->em->persist($group);
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
private function addGroupContactScore(
|
||||
Lead $lead,
|
||||
Group $group,
|
||||
int $score,
|
||||
): void {
|
||||
$groupContactScore = new GroupContactScore();
|
||||
$groupContactScore->setContact($lead);
|
||||
$groupContactScore->setGroup($group);
|
||||
$groupContactScore->setScore($score);
|
||||
$lead->addGroupScore($groupContactScore);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Tests\Functional;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\EmailBundle\Entity\Email;
|
||||
use Mautic\EmailBundle\Entity\Stat;
|
||||
use Mautic\EmailBundle\Entity\StatRepository;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\LeadBundle\Model\LeadModel;
|
||||
use Mautic\PointBundle\Entity\Group;
|
||||
use Mautic\PointBundle\Entity\Point;
|
||||
|
||||
class PointActionFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
public function testPointActionReadEmail(): void
|
||||
{
|
||||
$this->logoutUser();
|
||||
|
||||
/** @var LeadModel $leadModel */
|
||||
$leadModel = static::getContainer()->get('mautic.lead.model.lead');
|
||||
|
||||
$lead = $this->createLead('john@doe.email');
|
||||
$email = $this->createEmail();
|
||||
|
||||
$trackingHash = 'tracking_hash_123';
|
||||
$this->createEmailStat($lead, $email, $trackingHash);
|
||||
$pointAction = $this->createReadEmailAction(5);
|
||||
$this->client->request('GET', '/email/'.$trackingHash.'.gif');
|
||||
|
||||
$lead = $leadModel->getEntity($lead->getId());
|
||||
|
||||
$this->assertEquals($pointAction->getDelta(), $lead->getPoints());
|
||||
}
|
||||
|
||||
public function testPointActionWithGroupReadEmail(): void
|
||||
{
|
||||
$this->logoutUser();
|
||||
|
||||
/** @var LeadModel $leadModel */
|
||||
$leadModel = static::getContainer()->get('mautic.lead.model.lead');
|
||||
|
||||
$lead = $this->createLead('john@doe.email');
|
||||
$email = $this->createEmail();
|
||||
$group = $this->createGroup('Group A');
|
||||
|
||||
$trackingHash = 'tracking_hash_123';
|
||||
$this->createEmailStat($lead, $email, $trackingHash);
|
||||
$pointAction = $this->createReadEmailAction(5, $group);
|
||||
$this->client->request('GET', '/email/'.$trackingHash.'.gif');
|
||||
$this->em->clear(Lead::class);
|
||||
$lead = $leadModel->getEntity($lead->getId());
|
||||
$groupScore = $lead->getGroupScores()->first();
|
||||
|
||||
$this->assertEquals($pointAction->getDelta(), $groupScore->getScore());
|
||||
// group point action shouldn't update main contact points
|
||||
$this->assertEquals(0, $lead->getPoints());
|
||||
}
|
||||
|
||||
public function testPointActionEarlyReturnWhenNoPointsAvailable(): void
|
||||
{
|
||||
/** @var LeadModel $leadModel */
|
||||
$leadModel = static::getContainer()->get('mautic.lead.model.lead');
|
||||
|
||||
$lead = $this->createLead('jane@doe.email');
|
||||
$email = $this->createEmail();
|
||||
|
||||
$trackingHash = 'tracking_hash_no_points_456';
|
||||
$this->createEmailStat($lead, $email, $trackingHash);
|
||||
// Note: No point actions created for email.open type
|
||||
|
||||
$initialPoints = $lead->getPoints();
|
||||
$this->client->request('GET', '/email/'.$trackingHash.'.gif');
|
||||
|
||||
$lead = $leadModel->getEntity($lead->getId());
|
||||
|
||||
// Points should remain unchanged as no point actions are available
|
||||
$this->assertEquals($initialPoints, $lead->getPoints());
|
||||
$this->assertEquals(0, $lead->getPoints());
|
||||
}
|
||||
|
||||
private function createReadEmailAction(int $delta, ?Group $group = null): Point
|
||||
{
|
||||
$pointAction = new Point();
|
||||
$pointAction->setName('Read email action');
|
||||
$pointAction->setDelta($delta);
|
||||
$pointAction->setType('email.open');
|
||||
if ($group) {
|
||||
$pointAction->setGroup($group);
|
||||
}
|
||||
$this->em->persist($pointAction);
|
||||
$this->em->flush();
|
||||
|
||||
return $pointAction;
|
||||
}
|
||||
|
||||
private function createEmailStat(
|
||||
Lead $lead,
|
||||
Email $email,
|
||||
string $trackingHash,
|
||||
): Stat {
|
||||
/** @var StatRepository $statRepository */
|
||||
$statRepository = static::getContainer()->get('mautic.email.repository.stat');
|
||||
|
||||
$stat = new Stat();
|
||||
$stat->setTrackingHash($trackingHash);
|
||||
$stat->setEmailAddress($lead->getEmail());
|
||||
$stat->setLead($lead);
|
||||
$stat->setDateSent(new \DateTime());
|
||||
$stat->setEmail($email);
|
||||
$statRepository->saveEntity($stat);
|
||||
|
||||
return $stat;
|
||||
}
|
||||
|
||||
private function createLead(
|
||||
string $email,
|
||||
): Lead {
|
||||
$lead = new Lead();
|
||||
$lead->setEmail($email);
|
||||
$this->em->persist($lead);
|
||||
|
||||
return $lead;
|
||||
}
|
||||
|
||||
private function createEmail(): Email
|
||||
{
|
||||
$email = new Email();
|
||||
$email->setName('Test email');
|
||||
$email->setSubject('Test email subject');
|
||||
$email->setEmailType('template');
|
||||
$email->setCustomHtml('<h1>Email content</h1><br>{signature}');
|
||||
$email->setIsPublished(true);
|
||||
$email->setFromAddress('from@api.test');
|
||||
$email->setFromName('API Test');
|
||||
$this->em->persist($email);
|
||||
|
||||
return $email;
|
||||
}
|
||||
|
||||
private function createGroup(
|
||||
string $name,
|
||||
): Group {
|
||||
$group = new Group();
|
||||
$group->setName($name);
|
||||
$this->em->persist($group);
|
||||
|
||||
return $group;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Tests\Functional;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\LeadBundle\Entity\Tag;
|
||||
use Mautic\LeadBundle\Model\LeadModel;
|
||||
use Mautic\PointBundle\Entity\Group;
|
||||
use Mautic\PointBundle\Model\PointGroupModel;
|
||||
use Mautic\PointBundle\Model\TriggerModel;
|
||||
|
||||
class PointTriggerFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
use TriggerTrait;
|
||||
|
||||
public function testPointsTriggerWithTagAction(): void
|
||||
{
|
||||
/** @var LeadModel $model */
|
||||
$model = self::getContainer()->get('mautic.lead.model.lead');
|
||||
|
||||
$trigger = $this->createTrigger('Trigger', 5);
|
||||
$this->createAddTagEvent('tag5', $trigger);
|
||||
$trigger = $this->createTrigger('Trigger', 6);
|
||||
$this->createAddTagEvent('tag6', $trigger);
|
||||
|
||||
$lead = new Lead();
|
||||
$data = ['email' => 'pointtest@example.com', 'points' => 5];
|
||||
$model->setFieldValues($lead, $data, false, true, true);
|
||||
$model->saveEntity($lead);
|
||||
|
||||
$this->em->clear(Lead::class);
|
||||
$lead = $model->getEntity($lead->getId());
|
||||
$this->assertFalse($lead->getTags()->isEmpty());
|
||||
$this->assertTrue($this->leadHasTag($lead, 'tag5'));
|
||||
$this->assertFalse($this->leadHasTag($lead, 'tag6'));
|
||||
}
|
||||
|
||||
public function testGroupPointsTriggerWithTagAction(): void
|
||||
{
|
||||
/** @var LeadModel $model */
|
||||
$model = self::getContainer()->get('mautic.lead.model.lead');
|
||||
|
||||
/** @var PointGroupModel $pointGroupModel */
|
||||
$pointGroupModel = self::getContainer()->get('mautic.point.model.group');
|
||||
|
||||
$groupA = $this->createGroup('Group A');
|
||||
$groupB = $this->createGroup('Group B');
|
||||
|
||||
$triggerA = $this->createTrigger('Group A Trigger (should trigger)', 5, $groupA);
|
||||
$this->createAddTagEvent('tagA', $triggerA);
|
||||
|
||||
$triggerB = $this->createTrigger('Group B Trigger (should not trigger)', 5, $groupB);
|
||||
$this->createAddTagEvent('tagB', $triggerB);
|
||||
|
||||
$lead = new Lead();
|
||||
$data = ['email' => 'pointtest@example.com', 'points' => 0];
|
||||
$model->setFieldValues($lead, $data, false, true, true);
|
||||
$model->saveEntity($lead);
|
||||
|
||||
$this->em->clear(Lead::class);
|
||||
$lead = $model->getEntity($lead->getId());
|
||||
$pointGroupModel->adjustPoints($lead, $groupA, 5);
|
||||
$lead = $model->getEntity($lead->getId());
|
||||
|
||||
$this->assertFalse($this->leadHasTag($lead, 'tagB'));
|
||||
$this->assertTrue($this->leadHasTag($lead, 'tagA'));
|
||||
}
|
||||
|
||||
public function testTriggerForExistingContacts(): void
|
||||
{
|
||||
/** @var LeadModel $leadModel */
|
||||
$leadModel = self::getContainer()->get('mautic.lead.model.lead');
|
||||
|
||||
/** @var TriggerModel $triggerModel */
|
||||
$triggerModel = self::getContainer()->get('mautic.point.model.trigger');
|
||||
|
||||
$lead = new Lead();
|
||||
$data = ['email' => 'pointtest@example.com', 'points' => 5];
|
||||
$leadModel->setFieldValues($lead, $data, false, true, true);
|
||||
$leadModel->saveEntity($lead);
|
||||
|
||||
$this->em->clear(Lead::class);
|
||||
|
||||
$triggerA = $this->createTrigger('Group A Trigger (should trigger)', 5, null, true);
|
||||
$triggerEventA = $this->createAddTagEvent('tagA', $triggerA);
|
||||
$triggerA->addTriggerEvent(0, $triggerEventA);
|
||||
$triggerModel->saveEntity($triggerA);
|
||||
|
||||
$triggerB = $this->createTrigger('Group B Trigger (should not trigger)', 6, null, true);
|
||||
$triggerEventB = $this->createAddTagEvent('tagB', $triggerB);
|
||||
$triggerB->addTriggerEvent(0, $triggerEventB);
|
||||
$triggerModel->saveEntity($triggerB);
|
||||
|
||||
$lead = $leadModel->getEntity($lead->getId());
|
||||
|
||||
$this->assertFalse($this->leadHasTag($lead, 'tagB'));
|
||||
$this->assertTrue($this->leadHasTag($lead, 'tagA'));
|
||||
}
|
||||
|
||||
public function testTriggerWithGroupForExistingContacts(): void
|
||||
{
|
||||
/** @var LeadModel $leadModel */
|
||||
$leadModel = self::getContainer()->get('mautic.lead.model.lead');
|
||||
|
||||
/** @var TriggerModel $triggerModel */
|
||||
$triggerModel = self::getContainer()->get('mautic.point.model.trigger');
|
||||
|
||||
/** @var PointGroupModel $pointGroupModel */
|
||||
$pointGroupModel = self::getContainer()->get('mautic.point.model.group');
|
||||
|
||||
$groupA = $this->createGroup('Group A');
|
||||
$groupB = $this->createGroup('Group B');
|
||||
|
||||
$lead = new Lead();
|
||||
$data = ['email' => 'pointtest@example.com'];
|
||||
$leadModel->setFieldValues($lead, $data, false, true, true);
|
||||
$leadModel->saveEntity($lead);
|
||||
$pointGroupModel->adjustPoints($lead, $groupA, 5);
|
||||
|
||||
$triggerA = $this->createTrigger('Group A Trigger (should trigger)', 5, $groupA, true);
|
||||
$triggerEventA = $this->createAddTagEvent('tagA', $triggerA);
|
||||
$triggerA->addTriggerEvent(0, $triggerEventA);
|
||||
$triggerModel->saveEntity($triggerA);
|
||||
|
||||
$triggerB = $this->createTrigger('Group B Trigger (should not trigger)', 5, $groupB, true);
|
||||
$triggerEventB = $this->createAddTagEvent('tagB', $triggerB);
|
||||
$triggerB->addTriggerEvent(0, $triggerEventB);
|
||||
$triggerModel->saveEntity($triggerB);
|
||||
$lead = $leadModel->getEntity($lead->getId());
|
||||
|
||||
$triggerC = $this->createTrigger('General Trigger (should not trigger)', 5, $groupB, true);
|
||||
$triggerEventB = $this->createAddTagEvent('tagC', $triggerC);
|
||||
$triggerC->addTriggerEvent(0, $triggerEventB);
|
||||
$triggerModel->saveEntity($triggerC);
|
||||
$lead = $leadModel->getEntity($lead->getId());
|
||||
|
||||
$this->assertFalse($this->leadHasTag($lead, 'tagC'));
|
||||
$this->assertFalse($this->leadHasTag($lead, 'tagB'));
|
||||
$this->assertTrue($this->leadHasTag($lead, 'tagA'));
|
||||
}
|
||||
|
||||
private function createGroup(
|
||||
string $name,
|
||||
): Group {
|
||||
$group = new Group();
|
||||
$group->setName($name);
|
||||
$this->em->persist($group);
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
private function leadHasTag(
|
||||
Lead $lead,
|
||||
string $tagName,
|
||||
): bool {
|
||||
/** @var Tag $tag */
|
||||
foreach ($lead->getTags() as $tag) {
|
||||
if ($tag->getTag() === $tagName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\PointBundle\Tests\Functional;
|
||||
|
||||
use Mautic\CoreBundle\Entity\IpAddress;
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\PointBundle\Entity\Group;
|
||||
use Mautic\PointBundle\Entity\GroupContactScore;
|
||||
use Mautic\ReportBundle\Entity\Report;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class ReportSubscriberFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->useCleanupRollback = false;
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testContactPointLogReportWithGroup(): void
|
||||
{
|
||||
$this->createTestContactWithGroupPoints();
|
||||
$report = new Report();
|
||||
$report->setName('Contact point log');
|
||||
$report->setSource('lead.pointlog');
|
||||
$report->setColumns(['lp.type', 'lp.event_name', 'l.email', 'lp.delta', 'pl.name']);
|
||||
$report->setTableOrder([[
|
||||
'column' => 'lp.delta',
|
||||
'direction' => 'DESC',
|
||||
]]);
|
||||
$this->em->persist($report);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
// -- test report table in mautic panel
|
||||
$crawler = $this->client->request(Request::METHOD_GET, "/s/reports/view/{$report->getId()}");
|
||||
$crawlerReportTable = $crawler->filterXPath('//table[@id="reportTable"]')->first();
|
||||
|
||||
// convert html table to php array
|
||||
$crawlerReportTable = $this->domTableToArray($crawlerReportTable);
|
||||
|
||||
$this->assertSame([
|
||||
// no., event_type, event_name, email, points_delta, group_name
|
||||
['1', 'test type', 'Adjust points', 'test2@example.com', '15', 'Group A'],
|
||||
['2', 'test type', 'Adjust points', 'test3@example.com', '10', 'Group A'],
|
||||
['3', 'test type', 'Adjust points', 'test1@example.com', '5', 'Group A'],
|
||||
['4', 'test type', 'Adjust points', 'test3@example.com', '2', 'Group B'],
|
||||
['5', 'test type', 'Adjust points', 'test2@example.com', '1', 'Group B'],
|
||||
], array_slice($crawlerReportTable, 1, 5));
|
||||
|
||||
// -- test API report data
|
||||
$this->client->request(Request::METHOD_GET, "/api/reports/{$report->getId()}");
|
||||
$clientResponse = $this->client->getResponse();
|
||||
$result = json_decode($clientResponse->getContent(), true);
|
||||
$this->assertSame([
|
||||
[
|
||||
'type' => 'test type',
|
||||
'event_name' => 'Adjust points',
|
||||
'email' => 'test2@example.com',
|
||||
'delta' => '15',
|
||||
'group_name' => 'Group A',
|
||||
],
|
||||
[
|
||||
'type' => 'test type',
|
||||
'event_name' => 'Adjust points',
|
||||
'email' => 'test3@example.com',
|
||||
'delta' => '10',
|
||||
'group_name' => 'Group A',
|
||||
],
|
||||
[
|
||||
'type' => 'test type',
|
||||
'event_name' => 'Adjust points',
|
||||
'email' => 'test1@example.com',
|
||||
'delta' => '5',
|
||||
'group_name' => 'Group A',
|
||||
],
|
||||
[
|
||||
'type' => 'test type',
|
||||
'event_name' => 'Adjust points',
|
||||
'email' => 'test3@example.com',
|
||||
'delta' => '2',
|
||||
'group_name' => 'Group B',
|
||||
],
|
||||
[
|
||||
'type' => 'test type',
|
||||
'event_name' => 'Adjust points',
|
||||
'email' => 'test2@example.com',
|
||||
'delta' => '1',
|
||||
'group_name' => 'Group B',
|
||||
],
|
||||
], $result['data']);
|
||||
}
|
||||
|
||||
public function testGroupScoreReport(): void
|
||||
{
|
||||
$this->createTestContactWithGroupPoints();
|
||||
$report = new Report();
|
||||
$report->setName('Group score report');
|
||||
$report->setSource('group.score');
|
||||
$report->setColumns(['pl.name', 'ls.score', 'l.email']);
|
||||
$report->setTableOrder([[
|
||||
'column' => 'ls.score',
|
||||
'direction' => 'DESC',
|
||||
]]);
|
||||
$this->em->persist($report);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
// -- test report table in mautic panel
|
||||
$crawler = $this->client->request(Request::METHOD_GET, "/s/reports/view/{$report->getId()}");
|
||||
$crawlerReportTable = $crawler->filterXPath('//table[@id="reportTable"]')->first();
|
||||
|
||||
// convert html table to php array
|
||||
$crawlerReportTable = $this->domTableToArray($crawlerReportTable);
|
||||
|
||||
$this->assertSame([
|
||||
// no., group_name, group_score, email
|
||||
['1', 'Group A', '15', 'test2@example.com'],
|
||||
['2', 'Group A', '10', 'test3@example.com'],
|
||||
['3', 'Group A', '5', 'test1@example.com'],
|
||||
['4', 'Group B', '2', 'test3@example.com'],
|
||||
['5', 'Group B', '1', 'test2@example.com'],
|
||||
], array_slice($crawlerReportTable, 1, 5));
|
||||
|
||||
// -- test API report data
|
||||
$this->client->request(Request::METHOD_GET, "/api/reports/{$report->getId()}");
|
||||
$clientResponse = $this->client->getResponse();
|
||||
$result = json_decode($clientResponse->getContent(), true);
|
||||
|
||||
$this->assertSame([
|
||||
[
|
||||
'group_name' => 'Group A',
|
||||
'group_score' => '15',
|
||||
'email' => 'test2@example.com',
|
||||
],
|
||||
[
|
||||
'group_name' => 'Group A',
|
||||
'group_score' => '10',
|
||||
'email' => 'test3@example.com',
|
||||
],
|
||||
[
|
||||
'group_name' => 'Group A',
|
||||
'group_score' => '5',
|
||||
'email' => 'test1@example.com',
|
||||
],
|
||||
[
|
||||
'group_name' => 'Group B',
|
||||
'group_score' => '2',
|
||||
'email' => 'test3@example.com',
|
||||
],
|
||||
[
|
||||
'group_name' => 'Group B',
|
||||
'group_score' => '1',
|
||||
'email' => 'test2@example.com',
|
||||
],
|
||||
], $result['data']);
|
||||
}
|
||||
|
||||
private function createTestContactWithGroupPoints(): void
|
||||
{
|
||||
$contactModel = static::getContainer()->get('mautic.lead.model.lead');
|
||||
|
||||
$groupA = $this->createGroup('Group A');
|
||||
$groupB = $this->createGroup('Group B');
|
||||
$this->em->flush();
|
||||
|
||||
$contacts = [
|
||||
$this->createContact('test1@example.com'),
|
||||
$this->createContact('test2@example.com'),
|
||||
$this->createContact('test3@example.com'),
|
||||
];
|
||||
$contactModel->saveEntities($contacts);
|
||||
|
||||
$this->adjustContactPoints($contacts[0], 5, $groupA);
|
||||
$this->adjustContactPoints($contacts[1], 15, $groupA);
|
||||
$this->adjustContactPoints($contacts[2], 10, $groupA);
|
||||
$this->adjustContactPoints($contacts[2], 2, $groupB);
|
||||
$this->adjustContactPoints($contacts[1], 1, $groupB);
|
||||
|
||||
$contactModel->saveEntities($contacts);
|
||||
}
|
||||
|
||||
private function createContact(string $email): Lead
|
||||
{
|
||||
$contact = new Lead();
|
||||
$contact->setEmail($email);
|
||||
$this->em->persist($contact);
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
private function adjustContactPoints(Lead $contact, int $points, Group $group): void
|
||||
{
|
||||
$ipAddress = new IpAddress();
|
||||
$ipAddress->setIpAddress('127.0.0.1');
|
||||
$contact->addPointsChangeLogEntry(
|
||||
'test type',
|
||||
'Adjust points',
|
||||
'test action',
|
||||
$points,
|
||||
$ipAddress,
|
||||
$group
|
||||
);
|
||||
$contact->adjustPoints($points);
|
||||
$groupContactScore = new GroupContactScore();
|
||||
$groupContactScore->setContact($contact);
|
||||
$groupContactScore->setGroup($group);
|
||||
$groupContactScore->setScore($points);
|
||||
$contact->addGroupScore($groupContactScore);
|
||||
}
|
||||
|
||||
private function createGroup(
|
||||
string $name,
|
||||
): Group {
|
||||
$group = new Group();
|
||||
$group->setName($name);
|
||||
$this->em->persist($group);
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int,array<int,mixed>>
|
||||
*/
|
||||
private function domTableToArray(Crawler $crawler): array
|
||||
{
|
||||
return $crawler->filter('tr')->each(fn ($tr) => $tr->filter('td')->each(fn ($td) => trim($td->text())));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Tests\Functional;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\LeadBundle\Entity\LeadList;
|
||||
use Mautic\PointBundle\Entity\Group;
|
||||
use Mautic\PointBundle\Entity\GroupContactScore;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Component\Console\Tester\ApplicationTester;
|
||||
|
||||
class SegmentFilterFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
protected $useCleanupRollback = false;
|
||||
|
||||
public function testGroupPointSegmentFilter(): void
|
||||
{
|
||||
$application = new Application(self::$kernel);
|
||||
$application->setAutoExit(false);
|
||||
$applicationTester = new ApplicationTester($application);
|
||||
|
||||
$contactA = $this->createContact('contact-a@example.com');
|
||||
$contactB = $this->createContact('contact-b@example.com');
|
||||
$contactC = $this->createContact('contact-c@example.com');
|
||||
$groupA = $this->createGroup('Group A');
|
||||
$this->em->flush();
|
||||
|
||||
$this->addGroupContactScore($contactA, $groupA, 1);
|
||||
$this->addGroupContactScore($contactB, $groupA, 0);
|
||||
$this->em->persist($contactA);
|
||||
$this->em->persist($contactB);
|
||||
$this->em->flush();
|
||||
|
||||
$segmentA = new LeadList();
|
||||
$segmentA->setName('Group A points >= 1');
|
||||
$segmentA->setPublicName('Group A points >= 1');
|
||||
$segmentA->setAlias('group-a-points-gte1');
|
||||
$segmentA->setIsPublished(true);
|
||||
$segmentA->setFilters([
|
||||
[
|
||||
'glue' => 'and',
|
||||
'field' => 'group_points_'.$groupA->getId(),
|
||||
'object' => 'groups',
|
||||
'type' => 'number',
|
||||
'operator' => 'gte',
|
||||
'properties' => [
|
||||
'filter' => '1',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->em->persist($segmentA);
|
||||
$this->em->flush();
|
||||
|
||||
// Force Doctrine to re-fetch the entities otherwise the campaign won't know about any events.
|
||||
$this->em->clear();
|
||||
|
||||
// Execute segment update command.
|
||||
$exitCode = $applicationTester->run(
|
||||
[
|
||||
'command' => 'mautic:segments:update',
|
||||
'-i' => $segmentA->getId(),
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertSame(0, $exitCode, $applicationTester->getDisplay());
|
||||
|
||||
$this->client->request('GET', '/api/contacts?search=segment:group-a-points-gte1');
|
||||
$clientResponse = $this->client->getResponse();
|
||||
$this->assertTrue($this->client->getResponse()->isOk());
|
||||
$response = json_decode($clientResponse->getContent(), true);
|
||||
$this->assertEquals(1, (int) $response['total']);
|
||||
$contactIds = array_column($response['contacts'], 'id');
|
||||
$this->assertContains((int) $contactA->getId(), $contactIds);
|
||||
$this->assertNotContains((int) $contactB->getId(), $contactIds);
|
||||
$this->assertNotContains((int) $contactC->getId(), $contactIds);
|
||||
}
|
||||
|
||||
private function createContact(
|
||||
string $email,
|
||||
): Lead {
|
||||
$lead = new Lead();
|
||||
$lead->setEmail($email);
|
||||
$this->em->persist($lead);
|
||||
|
||||
return $lead;
|
||||
}
|
||||
|
||||
private function createGroup(
|
||||
string $name,
|
||||
): Group {
|
||||
$group = new Group();
|
||||
$group->setName($name);
|
||||
$this->em->persist($group);
|
||||
|
||||
return $group;
|
||||
}
|
||||
|
||||
private function addGroupContactScore(
|
||||
Lead $lead,
|
||||
Group $group,
|
||||
int $score,
|
||||
): void {
|
||||
$groupContactScore = new GroupContactScore();
|
||||
$groupContactScore->setContact($lead);
|
||||
$groupContactScore->setGroup($group);
|
||||
$groupContactScore->setScore($score);
|
||||
$lead->addGroupScore($groupContactScore);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\PointBundle\Tests\Functional;
|
||||
|
||||
use Mautic\PointBundle\Entity\Group;
|
||||
use Mautic\PointBundle\Entity\Trigger;
|
||||
use Mautic\PointBundle\Entity\TriggerEvent;
|
||||
|
||||
trait TriggerTrait
|
||||
{
|
||||
private function createTrigger(
|
||||
string $name,
|
||||
int $points = 0,
|
||||
?Group $group = null,
|
||||
bool $triggerExistingLeads = false,
|
||||
): Trigger {
|
||||
$trigger = new Trigger();
|
||||
$trigger->setName($name);
|
||||
$trigger->setPoints($points);
|
||||
|
||||
if (isset($group)) {
|
||||
$trigger->setGroup($group);
|
||||
}
|
||||
if ($triggerExistingLeads) {
|
||||
$trigger->setTriggerExistingLeads($triggerExistingLeads);
|
||||
}
|
||||
$this->em->persist($trigger);
|
||||
|
||||
return $trigger;
|
||||
}
|
||||
|
||||
private function createAddTagEvent(
|
||||
string $tag,
|
||||
Trigger $trigger,
|
||||
): TriggerEvent {
|
||||
$triggerEvent = new TriggerEvent();
|
||||
$triggerEvent->setTrigger($trigger);
|
||||
$triggerEvent->setName('Add '.$tag);
|
||||
$triggerEvent->setType('lead.changetags');
|
||||
$triggerEvent->setProperties([
|
||||
'add_tags' => [$tag],
|
||||
'remove_tags' => [],
|
||||
]);
|
||||
$this->em->persist($triggerEvent);
|
||||
|
||||
return $triggerEvent;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user