Spaces:
No application file
No application file
File size: 9,105 Bytes
d2897cd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Controller;
use Doctrine\Bundle\DoctrineBundle\DataCollector\DoctrineDataCollector;
use Doctrine\Bundle\DoctrineBundle\Twig\DoctrineExtension;
use Doctrine\ORM\ORMException;
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
use Mautic\LeadBundle\Entity\Lead;
use Mautic\LeadBundle\Entity\LeadList;
use Mautic\LeadBundle\Entity\ListLead;
use PHPUnit\Framework\Assert;
use Symfony\Component\HttpFoundation\Request;
final class LeadListSearchFunctionalTest extends MauticMysqlTestCase
{
/**
* @var mixed[]
*/
protected array $clientOptions = ['debug' => true];
/** @noinspection SqlResolve */
public function testSegmentSearch(): void
{
// create some leads
$leadOne = $this->createLead('one');
$leadTwo = $this->createLead('two');
$leadThree = $this->createLead('three');
$leadFour = $this->createLead('four');
$leadFive = $this->createLead('five');
$leadSix = $this->createLead('six');
// add some leads in lists
$listOne = $this->createLeadList('first-list', $leadOne, $leadTwo, $leadThree);
$listTwo = $this->createLeadList('second-list', $leadOne, $leadFour, $leadFive, $leadSix);
$this->em->flush();
$this->em->clear();
$this->client->enableProfiler();
$prefix = static::getContainer()->getParameter('mautic.db_table_prefix');
$previousQueries = [];
// non-existent segment search
$this->assertSearchResult('segment%3AnonExistent', [], [$leadOne, $leadTwo, $leadThree, $leadFour, $leadFive, $leadSix]);
$this->assertQueries([
"SELECT list.id FROM {$prefix}lead_lists list WHERE list.alias = 'nonexistent'",
"SELECT COUNT(l.id) as count FROM {$prefix}leads l USE INDEX FOR JOIN ({$prefix}lead_date_added) WHERE (EXISTS(SELECT 1 FROM {$prefix}lead_lists_leads lla WHERE (l.id = lla.lead_id) AND (lla.manually_removed = 0) AND (lla.leadlist_id IN (0)))) AND (l.date_identified IS NOT NULL)",
], $previousQueries);
// first-list segment search
$this->assertSearchResult('segment%3A'.$listOne->getAlias(), [$leadOne, $leadTwo, $leadThree], [$leadFour, $leadFive, $leadSix]);
$this->assertQueries([
"SELECT list.id FROM {$prefix}lead_lists list WHERE list.alias = '{$listOne->getAlias()}'",
"SELECT COUNT(l.id) as count FROM {$prefix}leads l USE INDEX FOR JOIN ({$prefix}lead_date_added) WHERE (EXISTS(SELECT 1 FROM {$prefix}lead_lists_leads lla WHERE (l.id = lla.lead_id) AND (lla.manually_removed = 0) AND (lla.leadlist_id IN ('{$listOne->getId()}')))) AND (l.date_identified IS NOT NULL)",
"SELECT l.* FROM {$prefix}leads l USE INDEX FOR JOIN ({$prefix}lead_date_added) WHERE (EXISTS(SELECT 1 FROM {$prefix}lead_lists_leads lla WHERE (l.id = lla.lead_id) AND (lla.manually_removed = 0) AND (lla.leadlist_id IN ('{$listOne->getId()}')))) AND (l.date_identified IS NOT NULL) ORDER BY l.last_active DESC, l.id DESC LIMIT 30",
], $previousQueries);
$this->assertSearchResult('!segment%3A'.$listOne->getAlias(), [$leadFour, $leadFive, $leadSix], [$leadOne, $leadTwo, $leadThree]);
$this->assertQueries([
"SELECT list.id FROM {$prefix}lead_lists list WHERE list.alias = '{$listOne->getAlias()}'",
"SELECT COUNT(l.id) as count FROM {$prefix}leads l USE INDEX FOR JOIN ({$prefix}lead_date_added) WHERE (NOT EXISTS(SELECT 1 FROM {$prefix}lead_lists_leads lla WHERE (l.id = lla.lead_id) AND (lla.manually_removed = 0) AND (lla.leadlist_id IN ('{$listOne->getId()}')))) AND (l.date_identified IS NOT NULL)",
"SELECT l.* FROM {$prefix}leads l USE INDEX FOR JOIN ({$prefix}lead_date_added) WHERE (NOT EXISTS(SELECT 1 FROM {$prefix}lead_lists_leads lla WHERE (l.id = lla.lead_id) AND (lla.manually_removed = 0) AND (lla.leadlist_id IN ('{$listOne->getId()}')))) AND (l.date_identified IS NOT NULL) ORDER BY l.last_active DESC, l.id DESC LIMIT 30",
], $previousQueries);
// second-list segment search
$this->assertSearchResult('segment%3A'.$listTwo->getAlias(), [$leadOne, $leadFour, $leadFive, $leadSix], [$leadTwo, $leadThree]);
$this->assertQueries([
"SELECT list.id FROM {$prefix}lead_lists list WHERE list.alias = '{$listTwo->getAlias()}'",
"SELECT COUNT(l.id) as count FROM {$prefix}leads l USE INDEX FOR JOIN ({$prefix}lead_date_added) WHERE (EXISTS(SELECT 1 FROM {$prefix}lead_lists_leads lla WHERE (l.id = lla.lead_id) AND (lla.manually_removed = 0) AND (lla.leadlist_id IN ('{$listTwo->getId()}')))) AND (l.date_identified IS NOT NULL)",
"SELECT l.* FROM {$prefix}leads l USE INDEX FOR JOIN ({$prefix}lead_date_added) WHERE (EXISTS(SELECT 1 FROM {$prefix}lead_lists_leads lla WHERE (l.id = lla.lead_id) AND (lla.manually_removed = 0) AND (lla.leadlist_id IN ('{$listTwo->getId()}')))) AND (l.date_identified IS NOT NULL) ORDER BY l.last_active DESC, l.id DESC LIMIT 30",
], $previousQueries);
$this->assertSearchResult('!segment%3A'.$listTwo->getAlias(), [$leadTwo, $leadThree], [$leadOne, $leadFour, $leadFive, $leadSix]);
$this->assertQueries([
"SELECT list.id FROM {$prefix}lead_lists list WHERE list.alias = '{$listTwo->getAlias()}'",
"SELECT COUNT(l.id) as count FROM {$prefix}leads l USE INDEX FOR JOIN ({$prefix}lead_date_added) WHERE (NOT EXISTS(SELECT 1 FROM {$prefix}lead_lists_leads lla WHERE (l.id = lla.lead_id) AND (lla.manually_removed = 0) AND (lla.leadlist_id IN ('{$listTwo->getId()}')))) AND (l.date_identified IS NOT NULL)",
"SELECT l.* FROM {$prefix}leads l USE INDEX FOR JOIN ({$prefix}lead_date_added) WHERE (NOT EXISTS(SELECT 1 FROM {$prefix}lead_lists_leads lla WHERE (l.id = lla.lead_id) AND (lla.manually_removed = 0) AND (lla.leadlist_id IN ('{$listTwo->getId()}')))) AND (l.date_identified IS NOT NULL) ORDER BY l.last_active DESC, l.id DESC LIMIT 30",
], $previousQueries);
}
/**
* @param Lead[] $expectedLeads
* @param Lead[] $notExpectedLeads
*/
private function assertSearchResult(string $search, array $expectedLeads, array $notExpectedLeads): void
{
$responseText = $this->client->request(Request::METHOD_GET, '/s/contacts?search='.$search)->text();
foreach ($expectedLeads as $expectedLead) {
Assert::assertStringContainsString($expectedLead->getEmail(), $responseText, sprintf('Lead with the email "%s" should be in the result.', $expectedLead->getEmail()));
}
foreach ($notExpectedLeads as $notExpectedLead) {
Assert::assertStringNotContainsString($notExpectedLead->getEmail(), $responseText, sprintf('Lead with the email "%s" should not be in the result.', $notExpectedLead->getEmail()));
}
}
/**
* @param string[] $expectedQueries
* @param string[] $previousQueries
*/
private function assertQueries(array $expectedQueries, array &$previousQueries): void
{
/** @var DoctrineDataCollector $dbCollector */
$dbCollector = $this->client->getProfile()->getCollector('db');
$allQueries = $dbCollector->getQueries()['default'];
$queries = array_diff_key($allQueries, $previousQueries);
$previousQueries = $allQueries;
$doctrineExtension = new DoctrineExtension();
$queries = array_map(function (array $query) use ($doctrineExtension) {
return $doctrineExtension->replaceQueryParameters($query['sql'], $query['params']);
}, $queries);
foreach ($expectedQueries as $expectedQuery) {
$matchedQueries = array_filter($queries, function (string $query) use ($expectedQuery) {
return $expectedQuery === $query;
});
Assert::assertCount(1, $matchedQueries, sprintf('The query "%s" was expected to be executed once.', $expectedQuery));
}
}
/**
* @throws ORMException
*/
private function createLead(string $lastName): Lead
{
$lead = new Lead();
$lead->setLastname($lastName);
$lead->setEmail(sprintf('%[email protected]', $lastName));
$this->em->persist($lead);
return $lead;
}
/**
* @param Lead ...$leads
*
* @throws ORMException
*/
private function createLeadList(string $name, ...$leads): LeadList
{
$leadList = new LeadList();
$leadList->setName($name);
$leadList->setPublicName($name);
$leadList->setAlias(mb_strtolower($name));
$this->em->persist($leadList);
foreach ($leads as $lead) {
$this->addLeadToList($lead, $leadList);
}
return $leadList;
}
private function addLeadToList(Lead $leadOne, LeadList $sourceList): void
{
$listLead = new ListLead();
$listLead->setLead($leadOne);
$listLead->setList($sourceList);
$listLead->setDateAdded(new \DateTime());
$this->em->persist($listLead);
}
}
|