mautic / app /bundles /LeadBundle /Tests /Controller /LeadControllerTest.php
chrisbryan17's picture
Upload folder using huggingface_hub
d2897cd verified
<?php
namespace Mautic\LeadBundle\Tests\Controller;
use Mautic\CampaignBundle\Entity\Campaign;
use Mautic\CoreBundle\Entity\AuditLog;
use Mautic\CoreBundle\Helper\CoreParametersHelper;
use Mautic\CoreBundle\Helper\UserHelper;
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
use Mautic\LeadBundle\DataFixtures\ORM\LoadCategorizedLeadListData;
use Mautic\LeadBundle\DataFixtures\ORM\LoadCategoryData;
use Mautic\LeadBundle\DataFixtures\ORM\LoadCompanyData;
use Mautic\LeadBundle\DataFixtures\ORM\LoadLeadData;
use Mautic\LeadBundle\Entity\Company;
use Mautic\LeadBundle\Entity\CompanyLead;
use Mautic\LeadBundle\Entity\ContactExportScheduler;
use Mautic\LeadBundle\Entity\Lead;
use Mautic\LeadBundle\Entity\PointsChangeLog;
use Mautic\LeadBundle\Form\Type\ContactGroupPointsType;
use Mautic\LeadBundle\Model\CompanyModel;
use Mautic\LeadBundle\Model\FieldModel;
use Mautic\LeadBundle\Model\LeadModel;
use Mautic\PointBundle\Entity\Group;
use PHPUnit\Framework\Assert;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\DomCrawler\Field\ChoiceFormField;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Tightenco\Collect\Support\Collection;
class LeadControllerTest extends MauticMysqlTestCase
{
protected function setUp(): void
{
$this->configParams['mailer_from_email'] = '[email protected]';
$this->configParams['messenger_dsn_email'] = 'testEmailSendToContactSync' === $this->getName() ? 'sync://' : 'in-memory://default';
parent::setUp();
}
/**
* @throws \Doctrine\ORM\ORMException
*/
protected function createLeadCompany(Lead $contactA, Company $company): CompanyLead
{
$leadCompany = new CompanyLead();
$leadCompany->setLead($contactA);
$leadCompany->setCompany($company);
$leadCompany->setDateAdded(new \DateTime());
$this->em->persist($leadCompany);
return $leadCompany;
}
protected function beforeBeginTransaction(): void
{
$this->resetAutoincrement([
'leads',
'companies',
'campaigns',
'categories',
'lead_lists',
]);
}
/**
* Assert there is an option to set the new Category type to 'segment'.
*/
public function testSegmentTypeOptionAvailableOnNewCategoryForm(): void
{
$this->client->request(Request::METHOD_GET, '/s/categories/category/new?show_bundle_select=1');
$clientResponse = $this->client->getResponse();
$responseContent = json_decode($clientResponse->getContent(), true);
$contentDom = new \DOMDocument();
$contentDom->loadHTML($responseContent['newContent']);
$xpath = new \DOMXPath($contentDom);
$this->assertEquals(Response::HTTP_OK, $clientResponse->getStatusCode());
$this->assertEquals(1, $xpath->query("//option[@value='segment']")->count());
}
public function testAddCategorizedLeadList(): void
{
$this->loadFixtures([LoadCategoryData::class]);
$crawler = $this->client->request(Request::METHOD_GET, '/s/segments/new');
$clientResponse = $this->client->getResponse();
$this->assertEquals(Response::HTTP_OK, $clientResponse->getStatusCode());
$form = $crawler->filterXPath('//form[@name="leadlist"]')->form();
$form->setValues(
[
'leadlist[name]' => 'Segment 1',
'leadlist[alias]' => 'segment-1',
'leadlist[isGlobal]' => '0',
'leadlist[isPreferenceCenter]' => '0',
'leadlist[isPublished]' => '1',
'leadlist[publicName]' => 'Segment 1',
'leadlist[category]' => '1',
]
);
$this->client->submit($form);
$this->assertEquals(
[
[
'id' => '1',
'name' => 'Segment 1',
'category_id' => '1',
],
],
$this->getLeadLists()
);
}
public function testRetrieveLeadListsBasedOnCategory(): void
{
$this->loadFixtures(
[
LoadCategoryData::class,
LoadCategorizedLeadListData::class,
]
);
$crawler = $this->client->request(Request::METHOD_GET, '/s/segments');
$leadListsTableRows = $crawler->filterXPath("//table[@id='leadListTable']//tbody//tr");
$this->assertEquals(Response::HTTP_OK, $this->client->getResponse()->getStatusCode());
$this->assertEquals(7, $leadListsTableRows->count());
$crawler = $this->client->request(Request::METHOD_GET, '/s/segments?filters=["category:1"]');
$leadListsTableRows = $crawler->filterXPath("//table[@id='leadListTable']//tbody//tr");
$this->assertEquals(4, $leadListsTableRows->count());
$firstLeadListLinkTest = trim($leadListsTableRows->first()->filterXPath('//td[2]//div//a')->text(null, false));
$this->assertEquals('Lead List 1 - Segment Category 1 (lead-list-1)', $firstLeadListLinkTest);
$crawler = $this->client->request(Request::METHOD_GET, '/s/segments?filters=["category:2"]');
$leadListsTableRows = $crawler->filterXPath("//table[@id='leadListTable']//tbody//tr");
$this->assertEquals(2, $leadListsTableRows->count());
$crawler = $this->client->request(Request::METHOD_GET, '/s/segments?filters=["category:2","category:1"]');
$leadListsTableRows = $crawler->filterXPath("//table[@id='leadListTable']//tbody//tr");
$this->assertEquals(6, $leadListsTableRows->count());
$crawler = $this->client->request(Request::METHOD_GET, '/s/segments?filters=["category:4"]');
$leadListsTableRows = $crawler->filterXPath("//table[@id='leadListTable']//tbody//tr");
$this->assertEquals(0, $leadListsTableRows->count());
}
public function testContactsAreAddedToThenRemovedFromCampaignsInBatch(): void
{
$contactA = $this->createContact('[email protected]');
$contactB = $this->createContact('[email protected]');
$contactC = $this->createContact('[email protected]');
$campaign = $this->createCampaign();
$payload = [
'lead_batch' => [
'add' => [$campaign->getId()],
'ids' => json_encode([$contactA->getId(), $contactB->getId(), $contactC->getId()]),
],
];
$this->client->request(Request::METHOD_POST, '/s/contacts/batchCampaigns', $payload);
$clientResponse = $this->client->getResponse();
$this->assertEquals(Response::HTTP_OK, $clientResponse->getStatusCode());
$this->assertSame(
[
[
'lead_id' => (string) $contactA->getId(),
'manually_added' => '1',
'manually_removed' => '0',
'date_last_exited' => null,
],
[
'lead_id' => (string) $contactB->getId(),
'manually_added' => '1',
'manually_removed' => '0',
'date_last_exited' => null,
],
[
'lead_id' => (string) $contactC->getId(),
'manually_added' => '1',
'manually_removed' => '0',
'date_last_exited' => null,
],
],
$this->getMembersForCampaign($campaign->getId())
);
$response = json_decode($clientResponse->getContent(), true);
$this->assertTrue(isset($response['closeModal']), 'The response does not contain the `closeModal` param.');
$this->assertTrue($response['closeModal']);
$this->assertStringContainsString('3 contacts affected', $response['flashes']);
$payload = [
'lead_batch' => [
'remove' => [$campaign->getId()],
'ids' => json_encode([$contactA->getId(), $contactB->getId(), $contactC->getId()]),
],
];
$this->client->request(Request::METHOD_POST, '/s/contacts/batchCampaigns', $payload);
$clientResponse = $this->client->getResponse();
$this->assertEquals(Response::HTTP_OK, $clientResponse->getStatusCode());
$this->assertSame(
[
[
'lead_id' => (string) $contactA->getId(),
'manually_added' => '0',
'manually_removed' => '1',
'date_last_exited' => null,
],
[
'lead_id' => (string) $contactB->getId(),
'manually_added' => '0',
'manually_removed' => '1',
'date_last_exited' => null,
],
[
'lead_id' => (string) $contactC->getId(),
'manually_added' => '0',
'manually_removed' => '1',
'date_last_exited' => null,
],
],
$this->getMembersForCampaign($campaign->getId())
);
$response = json_decode($clientResponse->getContent(), true);
$this->assertTrue(isset($response['closeModal']), 'The response does not contain the `closeModal` param.');
$this->assertTrue($response['closeModal']);
$this->assertStringContainsString('3 contacts affected', $response['flashes']);
}
public function testCompanyChangesAreTrackedWhenContactAddedViaUI(): void
{
$company = new Company();
$company->setName('Doe Corp');
$this->em->persist($company);
$this->em->flush();
$crawler = $this->client->request('GET', 's/contacts/new/');
$form = $crawler->filterXPath('//form[@name="lead"]')->form();
$form->setValues(
[
'lead[firstname]' => 'John',
'lead[lastname]' => 'Doe',
'lead[email]' => '[email protected]',
'lead[companies]' => [$company->getId()],
'lead[points]' => 20,
]
);
$this->client->submit($form);
$clientResponse = $this->client->getResponse();
Assert::assertTrue($clientResponse->isOk(), $clientResponse->getContent());
/** @var Lead $contact */
$contact = $this->em->getRepository(Lead::class)->findOneBy(['email' => '[email protected]']);
/** @var AuditLog $auditLog */
$auditLog = $this->em->getRepository(AuditLog::class)->findOneBy(['object' => 'lead', 'objectId' => $contact, 'userId' => 1]);
Assert::assertTrue(isset($auditLog->getDetails()['fields']), json_encode($auditLog, JSON_PRETTY_PRINT));
Assert::assertSame(
[
'firstname' => [null, 'John'],
'lastname' => [null, 'Doe'],
'email' => [null, '[email protected]'],
'points' => [0, 20.0],
'company' => ['', 'Doe Corp'],
],
$auditLog->getDetails()['fields']
);
}
/**
* Only tests if a contact export is scheduled for CSV file.
*/
public function testCsvIsScheduledForExport(): void
{
$this->loadFixtures([LoadLeadData::class]);
$this->client->request(Request::METHOD_GET, '/s/contacts/batchExport?filetype=csv');
$clientResponse = $this->client->getResponse();
Assert::assertTrue($this->client->getResponse()->isOk());
Assert::assertStringContainsString(
'Contact export scheduled for CSV file type.',
$clientResponse->getContent()
);
$contactExportScheduler = $this->em->getRepository(ContactExportScheduler::class)->findOneBy([]);
$data = $contactExportScheduler->getData();
/** @var CoreParametersHelper $coreParametersHelper */
$coreParametersHelper = static::getContainer()->get('mautic.helper.core_parameters');
Assert::assertSame(
[
'start' => 0,
'limit' => $coreParametersHelper->get('contact_export_batch_size', 1000),
'filter' => [
'string' => '',
'force' => [
[
'column' => 'l.dateIdentified',
'expr' => 'isNotNull',
],
],
],
'orderBy' => 'l.last_active',
'orderByDir' => 'DESC',
'withTotalCount' => true,
'fileType' => 'csv',
],
$data
);
}
/**
* Only tests if an actual Excel file is returned and if the content size isn't suspiciously small.
* We do more in-depth tests in \Mautic\CoreBundle\Tests\Unit\Helper\ExportHelperTest.
*/
public function testExcelIsExportedCorrectly(): void
{
$this->loadFixtures([LoadLeadData::class]);
ob_start();
$this->client->request(Request::METHOD_GET, '/s/contacts/batchExport?filetype=xlsx');
$content = ob_get_contents();
ob_end_clean();
$clientResponse = $this->client->getResponse();
$this->assertEquals(Response::HTTP_OK, $clientResponse->getStatusCode());
$this->assertEquals($this->client->getInternalResponse()->getHeader('content-type'), 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
$this->assertEquals(true, strlen($content) > 10000);
}
public function testContactsAreAddedAndRemovedFromCompanies(): void
{
// Running all these in one test to avoid having to re-load fixtures multiple time
$this->loadFixtures([LoadLeadData::class, LoadCompanyData::class]);
$this->client->catchExceptions(false);
// Delete all company associations for this test because the fixures have mismatching data to start with
$this->connection->createQueryBuilder()
->delete(MAUTIC_TABLE_PREFIX.'companies_leads')
->executeStatement();
// Test a single company is added and is set as primary
$this->assertCompanyAssociation([1], 1);
// Test that a company a contact is already part of does not change anything
$this->assertCompanyAssociation([1], 1);
// Test that multiple companies are added and one primary is set
$this->assertCompanyAssociation([1, 2, 3], 1);
// Test that removing a company will leave the two remaining with one set as primary
$this->assertCompanyAssociation([1, 3], 1);
// Test that adding a company in addition to others will set it as primary
$this->assertCompanyAssociation([1, 2, 3], 1);
// Test that removing all companies will empty the lead's primary company
$crawler = $this->client->request(Request::METHOD_GET, '/s/contacts/edit/1');
$saveButton = $crawler->selectButton('lead[buttons][save]');
$form = $saveButton->form();
/** @var ChoiceFormField $companyField */
$companyField = &$form['lead[companies]'];
$companyField->setValue([]);
$this->client->submit($form);
$companies = $this->getCompanyLeads(1);
$collection = new Collection($companies);
// Should have no companies associated
$this->assertCount(0, $collection);
// Primary company name should match
$primaryCompanyName = $this->getLeadPrimaryCompany(1);
$this->assertEmpty($primaryCompanyName);
}
private function getMembersForCampaign(int $campaignId): array
{
return $this->connection->createQueryBuilder()
->select('cl.lead_id, cl.manually_added, cl.manually_removed, cl.date_last_exited')
->from(MAUTIC_TABLE_PREFIX.'campaign_leads', 'cl')
->where("cl.campaign_id = {$campaignId}")
->executeQuery()
->fetchAllAssociative();
}
private function getLeadLists(): array
{
return $this->connection->createQueryBuilder()
->select('ll.id', 'll.name', 'll.category_id')
->from(MAUTIC_TABLE_PREFIX.'lead_lists', 'll')
->executeQuery()
->fetchAllAssociative();
}
/**
* @testdox Ensure correct Preferred Timezone placeholder on add/edit contact page
*/
public function testEnsureCorrectPreferredTimeZonePlaceHolderOnContactPage(): void
{
$crawler = $this->client->request('GET', '/s/contacts/new');
$elementPlaceholder = $crawler->filter('#lead_timezone')->filter('select')->attr('data-placeholder');
$expectedPlaceholder = static::getContainer()->get('translator')->trans('mautic.lead.field.timezone');
$this->assertEquals($expectedPlaceholder, $elementPlaceholder);
// Test that a locale option is present correctly.
$this->assertStringContainsString(
'<option value="cs_CZ">Czech (Czechia)</option>',
$this->client->getResponse()->getContent()
);
}
public function testAddContactsErrorMessage(): void
{
/** @var FieldModel $fieldModel */
$fieldModel = self::getContainer()->get('mautic.lead.model.field');
$firstnameField = $fieldModel->getEntity(2);
$firstnameField->setIsRequired(true);
$fieldModel->getRepository()->saveEntity($firstnameField);
$crawler = $this->client->request('GET', 's/contacts/new/');
$form = $crawler->filterXPath('//form[@name="lead"]')->form();
$form->setValues(
[
]
);
$this->client->submit($form);
$clientResponse = $this->client->getResponse();
$this->assertStringContainsString('firstname: This field is required.', $clientResponse->getContent());
}
public function testAddContactsErrorMessageForEmailWithTwoDots(): void
{
$crawler = $this->client->request('GET', 's/contacts/new/');
$form = $crawler->filterXPath('//form[@name="lead"]')->form();
$form->setValues(
[
'lead[email]' => '[email protected]',
]
);
$this->client->submit($form);
$clientResponse = $this->client->getResponse();
$this->assertStringContainsString('email: [email protected] is invalid.', $clientResponse->getContent());
}
public function testCompanyIdSearchCommand(): void
{
$contactA = $this->createContact('[email protected]');
$contactB = $this->createContact('[email protected]');
$contactC = $this->createContact('[email protected]');
$companyName = 'Doe Corp';
$company = new Company();
$company->setName($companyName);
$this->em->persist($company);
$this->em->flush();
$this->createLeadCompany($contactA, $company);
$this->createLeadCompany($contactB, $company);
$this->em->flush();
$crawler = $this->client->request(Request::METHOD_GET, '/s/contacts?search=company_id:'.$company->getId());
$leadsTableRows = $crawler->filterXPath("//table[@id='leadTable']//tbody//tr");
$this->assertEquals(2, $leadsTableRows->count(), $crawler->html());
}
public function testEmailSendToContactSync(): void
{
$contact = $this->createContact('[email protected]');
$replyTo = '[email protected]';
$this->client->request(Request::METHOD_GET, "/s/contacts/email/{$contact->getId()}");
Assert::assertTrue($this->client->getResponse()->isOk());
$crawler = new Crawler(json_decode($this->client->getResponse()->getContent(), true)['newContent'], $this->client->getInternalRequest()->getUri());
$form = $crawler->selectButton('Send')->form();
$form->setValues(
[
'lead_quickemail[subject]' => 'Ahoy {contactfield=email}',
'lead_quickemail[body]' => 'Your email is <b>{contactfield=email}</b>',
'lead_quickemail[replyToAddress]' => $replyTo,
]
);
$crawler = $this->client->submit($form);
$this->assertTrue($this->client->getResponse()->isOk(), $this->client->getResponse()->getContent());
$this->assertQueuedEmailCount(1);
$email = $this->getMailerMessage();
$userHelper = static::getContainer()->get(UserHelper::class);
$user = $userHelper->getUser();
Assert::assertSame('Ahoy [email protected]', $email->getSubject());
Assert::assertMatchesRegularExpression('#Your email is <b>contact@an\.email<\/b><img height="1" width="1" src="https:\/\/localhost\/email\/[a-z0-9]+\.gif" alt="" \/>#', $email->getHtmlBody());
Assert::assertSame('Your email is [email protected]', $email->getTextBody());
Assert::assertCount(1, $email->getFrom());
Assert::assertSame($user->getName(), $email->getFrom()[0]->getName());
Assert::assertSame($user->getEmail(), $email->getFrom()[0]->getAddress());
Assert::assertCount(1, $email->getTo());
Assert::assertSame('', $email->getTo()[0]->getName());
Assert::assertSame($contact->getEmail(), $email->getTo()[0]->getAddress());
Assert::assertCount(1, $email->getReplyTo());
Assert::assertSame('', $email->getReplyTo()[0]->getName());
Assert::assertSame($replyTo, $email->getReplyTo()[0]->getAddress());
}
public function testEmailSendToContactAsync(): void
{
// This test should behave the same as sending it via Sync. Just with different settings. See setUp().
$this->testEmailSendToContactSync();
}
private function createContact(string $email): Lead
{
$lead = new Lead();
$lead->setEmail($email);
$this->em->persist($lead);
$this->em->flush();
return $lead;
}
public function testLookupTypeFieldOnError(): void
{
$crawler = $this->client->request('GET', 's/contacts/new/');
$form = $crawler->filterXPath('//form[@name="lead"]')->form();
$form->setValues(
[
'lead[title]' => 'Custom title longer like 191 characters Custom title longer like 191 characters Custom title longer like 191 characters Custom title longer like 191 characters Custom title longer like 191 characters Custom title longer like 191 characters ',
]
);
$this->client->submit($form);
$clientResponse = $this->client->getResponse();
$this->assertStringContainsString('title: This value is too long. It should have 191 characters or less', $clientResponse->getContent());
}
public function testQuickAddRendersErrorOnEmailDuplicate(): void
{
$email = '[email protected]';
$this->createContact($email);
$crawler = $this->client->request('GET', 's/contacts/quickAdd');
$form = $crawler->filter('form[name="lead"]')->form([
'lead' => [
'email' => $email,
],
]);
$crawler = $this->client->submit($form);
self::assertResponseStatusCodeSame(Response::HTTP_OK);
$errorContainer = $crawler->filter('form[name="lead"] .has-error .help-block');
self::assertCount(1, $errorContainer);
self::assertSame('This field must be unique.', $errorContainer->text(null, true));
}
public function testEditRendersErrorOnEmailDuplicate(): void
{
$email = '[email protected]';
$this->createContact($email);
$crawler = $this->client->request('GET', 's/contacts/new');
$form = $crawler->filter('form[name="lead"]')->form([
'lead' => [
'email' => $email,
],
]);
$this->client->submit($form);
self::assertResponseStatusCodeSame(Response::HTTP_OK);
$clientResponse = $this->client->getResponse();
Assert::assertStringContainsString('email: This field must be unique.', $clientResponse->getContent());
}
private function createCampaign(): Campaign
{
$campaign = new Campaign();
$campaign->setName('Campaign A');
$campaign->setCanvasSettings(
[
'nodes' => [
[
'id' => '148',
'positionX' => '760',
'positionY' => '155',
],
[
'id' => 'lists',
'positionX' => '860',
'positionY' => '50',
],
],
'connections' => [
[
'sourceId' => 'lists',
'targetId' => '148',
'anchors' => [
'source' => 'leadsource',
'target' => 'top',
],
],
],
]
);
$this->em->persist($campaign);
$this->em->flush();
return $campaign;
}
/**
* @return array<int, array<string, mixed>>
*/
private function getCompanyLeads(int $leadId): array
{
return $this->connection->createQueryBuilder()
->select('cl.lead_id, cl.company_id, cl.is_primary, c.companyname')
->from(MAUTIC_TABLE_PREFIX.'companies_leads', 'cl')
->join('cl', MAUTIC_TABLE_PREFIX.'companies', 'c', 'c.id = cl.company_id')
->where("cl.lead_id = {$leadId}")
->orderBy('cl.company_id')
->executeQuery()
->fetchAllAssociative();
}
private function getLeadPrimaryCompany(int $leadId): ?string
{
return $this->connection->createQueryBuilder()
->select('l.company')
->from(MAUTIC_TABLE_PREFIX.'leads', 'l')
->where("l.id = {$leadId}")
->executeQuery()
->fetchOne();
}
/**
* @param int[] $expectedCompanies
*/
private function assertCompanyAssociation(array $expectedCompanies, int $leadId): void
{
$crawler = $this->client->request(Request::METHOD_GET, '/s/contacts/edit/1');
$saveButton = $crawler->selectButton('lead[buttons][save]');
$form = $saveButton->form();
/** @var ChoiceFormField $companyField */
$companyField = &$form['lead[companies]'];
$companyField->setValue($expectedCompanies);
$crawler = $this->client->submit($form);
$companies = $this->getCompanyLeads($leadId);
$collection = (new Collection($companies))->keyBy('company_id');
// Should have only one company associated
$this->assertCount(count($expectedCompanies), $collection);
$this->assertEquals($expectedCompanies, $collection->keys()->toArray());
// Only one should be primary
$primary = $collection->reject(
fn (array $company) => empty($company['is_primary'])
);
$this->assertCount(1, $primary);
// Primary company name should match
$primaryCompanyName = $this->getLeadPrimaryCompany($leadId);
$this->assertEquals($primary->first()['companyname'], $primaryCompanyName);
// Primary company should be in the UI of the details dropdown tray
$details = $crawler->filter('#lead-details')->html();
$this->assertStringContainsString($primaryCompanyName, $details);
}
public function testContactCompanyEditShowsOldCompanyNameInAuditLog(): void
{
/** @var CompanyModel $companyModel */
$companyModel = static::getContainer()->get('mautic.lead.model.company');
/** @var LeadModel $contactModel */
$contactModel = static::getContainer()->get('mautic.lead.model.lead');
// Create companies
$company = (new Company())
->setName('Co.');
$newCompany = (new Company())
->setName('New Co.');
$companyModel->saveEntities([$company, $newCompany]);
$companyId = $company->getId();
$newCompanyId = $newCompany->getId();
// Create contact with first 'Co.' company
$contact = (new Lead())
->setFirstname('C1')
->setCompany($company);
$contactModel->saveEntity($contact);
// Check contact detail view audit log
$createAuditLog = $this->getContactAuditLogForSpecificAction($contact, 'create');
$createAuditLogDetails = $createAuditLog->getDetails();
// `dateIdentified` is added to the audit log when contact is identified, we want to remove this for easier comparison
unset($createAuditLogDetails['dateIdentified']);
Assert::assertSame(
[
'firstname' => [null, 'C1'],
'company' => [null, $companyId],
],
$createAuditLogDetails
);
// Edit contact with second 'New Co.' company
$contact->setCompany($newCompany);
$contactModel->saveEntity($contact);
// Check contact detail view audit log for old value
$updateAuditLog = $this->getContactAuditLogForSpecificAction($contact, 'update');
Assert::assertSame(
[
'company' => [$companyId, $newCompanyId],
],
$updateAuditLog->getDetails()
);
}
public function testSetNullCompanyToContact(): void
{
/** @var LeadModel $contactModel */
$contactModel = static::getContainer()->get('mautic.lead.model.lead');
$company = new Company();
$company->setName('Doe Corp');
$this->em->persist($company);
$this->em->flush();
$crawler = $this->client->request('GET', 's/contacts/new/');
$form = $crawler->filterXPath('//form[@name="lead"]')->form();
$form->setValues(
[
'lead[firstname]' => 'John',
'lead[lastname]' => 'Doe',
'lead[email]' => '[email protected]',
'lead[companies]' => [$company->getId()],
]
);
$this->client->submit($form);
$clientResponse = $this->client->getResponse();
Assert::assertTrue($clientResponse->isOk(), $clientResponse->getContent());
/** @var Lead $contact */
$contact = $this->em->getRepository(Lead::class)->findOneBy(['email' => '[email protected]']);
$companies = $this->getCompanyLeads($contact->getId());
$collection = new Collection($companies);
// Should have no companies associated
$this->assertCount(1, $collection);
$this->em->flush();
$contact->addUpdatedField('company', null);
$contactModel->saveEntity($contact);
$companies = $this->getCompanyLeads($contact->getId());
$collection = new Collection($companies);
// Should have no companies associated
$this->assertCount(0, $collection);
}
private function getContactAuditLogForSpecificAction(Lead $contact, string $action): AuditLog
{
return $this->em->getRepository(AuditLog::class)->findOneBy([
'bundle' => 'lead',
'object' => 'lead',
'objectId' => $contact->getId(),
'action' => $action,
]);
}
public function testAllAssociatedCompaniesShouldBeFetchedOnContactEditAction(): void
{
$contact = $this->createContact('[email protected]');
// Create more than 100 companies and attached to lead
$companyLimit = 102;
$counter = 1;
while ($companyLimit >= $counter) {
$company = new Company();
$company->setName('TestCompany'.$counter);
$this->em->persist($company);
++$counter;
$this->createLeadCompany($contact, $company);
}
$this->em->flush();
// verify that all companies are attached to contact
$companies = $this->getCompanyLeads($contact->getId());
Assert::assertCount($companyLimit, $companies);
$crawler = $this->client->request(Request::METHOD_GET, '/s/contacts/edit/'.$contact->getId());
$saveButton = $crawler->selectButton('lead[buttons][save]');
$form = $saveButton->form();
$leadCompanies = $form['lead[companies]']->getValue();
Assert::assertCount($companyLimit, $leadCompanies);
}
public function testNonExitingContactIsRedirected(): void
{
$this->client->followRedirects(false);
$this->client->request(
Request::METHOD_GET,
's/contacts/view/1000',
);
$this->assertEquals(true, $this->client->getResponse()->isRedirect('/s/contacts/1'));
}
public function testContactGroupPointsEdit(): void
{
$contact = $this->createContact('[email protected]');
$groupA = new Group();
$groupA->setName('Group A');
$groupB = new Group();
$groupB->setName('Group B');
$groupC = new Group();
$groupC->setName('Group C');
$this->em->persist($groupA);
$this->em->persist($groupB);
$this->em->persist($groupC);
$this->em->flush();
$scoresMap = [
$groupA->getId() => 1,
$groupB->getId() => 5,
];
$uri = "/s/contacts/contactGroupPoints/{$contact->getId()}";
$this->client->request('GET', $uri, [], [], $this->createAjaxHeaders());
$response = $this->client->getResponse();
$this->assertTrue($response->isOk(), $response->getContent());
// Get the form HTML element out of the response, fill it in and submit.
$responseData = json_decode($response->getContent(), true);
$crawler = new Crawler($responseData['newContent'], $this->client->getInternalRequest()->getUri());
$form = $crawler->filterXPath('//form[@name="contact_group_points"]')->form();
$groupAKey = ContactGroupPointsType::getFieldKey($groupA->getId());
$groupBKey = ContactGroupPointsType::getFieldKey($groupB->getId());
$form->setValues(
[
"contact_group_points[{$groupAKey}]" => $scoresMap[$groupA->getId()],
"contact_group_points[{$groupBKey}]" => $scoresMap[$groupB->getId()],
]
);
$this->client->request($form->getMethod(), $form->getUri(), $form->getPhpValues(), [], $this->createAjaxHeaders());
$response = $this->client->getResponse();
$this->assertTrue($response->isOk(), $response->getContent());
$scores = $contact->getGroupScores();
$this->assertCount(2, $scores);
foreach ($scores as $score) {
$this->assertEquals($scoresMap[$score->getGroup()->getId()], $score->getScore());
}
$logs = $this->em->getRepository(PointsChangeLog::class)->findBy(['lead' => $contact->getId()]);
$this->assertCount(2, $logs);
foreach ($logs as $log) {
$this->assertEquals($scoresMap[$log->getGroup()->getId()], $log->getDelta());
}
}
public function testMultipleCompanyFeature(): void
{
$crawler = $this->client->request('GET', 's/contacts/new/');
$multiple = $crawler->filterXPath('//*[@id="lead_companies"]')->attr('multiple');
self::assertSame('multiple', $multiple);
}
}