Spaces:
No application file
No application file
declare(strict_types=1); | |
namespace Mautic\LeadBundle\Tests\Controller\Api; | |
use Mautic\CoreBundle\Test\MauticMysqlTestCase; | |
use Mautic\CoreBundle\Test\Session\FixedMockFileSessionStorage; | |
use Mautic\LeadBundle\Entity\Company; | |
use Mautic\LeadBundle\Entity\DoNotContact; | |
use Mautic\LeadBundle\Entity\Lead; | |
use PHPUnit\Framework\Assert; | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\HttpFoundation\Response; | |
use Symfony\Component\HttpFoundation\Session\Session; | |
class LeadApiControllerFunctionalTest extends MauticMysqlTestCase | |
{ | |
protected function setUp(): void | |
{ | |
// Disable API just for specific test. | |
$this->configParams['api_enabled'] = 'testDisabledApi' !== $this->getName(); | |
static::getContainer()->set( | |
'session', | |
new Session( | |
new class() extends FixedMockFileSessionStorage { | |
public function start() | |
{ | |
Assert::fail('Session cannot be started during API call. It must be stateless.'); | |
} | |
} | |
) | |
); | |
parent::setUp(); | |
} | |
public function testDisabledApi(): void | |
{ | |
$this->client->request('POST', '/api/contacts/new', ['email' => '[email protected]']); | |
$clientResponse = $this->client->getResponse(); | |
$this->assertEquals(Response::HTTP_FORBIDDEN, $clientResponse->getStatusCode(), $clientResponse->getContent()); | |
$this->assertEquals( | |
'{"errors":[{"message":"API disabled. You need to enable the API in the API settings of Mautic\u0027s Configuration.","code":403,"type":"api_disabled"}]}', | |
$clientResponse->getContent() | |
); | |
} | |
public function testActivityApi(): void | |
{ | |
$this->client->request('GET', '/api/contacts/activity'); | |
Assert::assertTrue($this->client->getResponse()->isOk(), $this->client->getResponse()->getContent()); | |
Assert::assertArrayHasKey('events', json_decode($this->client->getResponse()->getContent(), true)); | |
Assert::assertArrayHasKey('filters', json_decode($this->client->getResponse()->getContent(), true)); | |
Assert::assertArrayHasKey('order', json_decode($this->client->getResponse()->getContent(), true)); | |
Assert::assertArrayHasKey('types', json_decode($this->client->getResponse()->getContent(), true)); | |
Assert::assertArrayHasKey('total', json_decode($this->client->getResponse()->getContent(), true)); | |
Assert::assertArrayHasKey('page', json_decode($this->client->getResponse()->getContent(), true)); | |
Assert::assertArrayHasKey('limit', json_decode($this->client->getResponse()->getContent(), true)); | |
Assert::assertArrayHasKey('maxPages', json_decode($this->client->getResponse()->getContent(), true)); | |
} | |
public function testBatchNewEndpointDoesNotCreateDuplicates(): void | |
{ | |
$companyA = $this->createCompany('CompanyA corp'); | |
$companyB = $this->createCompany('CompanyB corp'); | |
$payload = [ | |
[ | |
'email' => '[email protected]', | |
'firstname' => 'BatchUpdate', | |
'points' => 4, | |
'tags' => ['batchtest', 'testbatch'], | |
'city' => 'Houston', | |
'state' => 'Texas', | |
'country' => 'United States', | |
'preferred_locale' => 'es_SV', | |
'timezone' => 'America/Chicago', | |
'owner' => 1, | |
'company' => $companyA->getId(), | |
], | |
[ | |
'email' => '[email protected]', | |
'firstname' => 'BatchUpdate2', | |
'tags' => ['batchtest', 'testbatch', 'batchremovetest'], | |
'city' => 'Boston', | |
'state' => 'Massachusetts', | |
'country' => 'United States', | |
'preferred_locale' => 'en_GB', | |
'timezone' => 'America/New_York', | |
], | |
[ | |
'email' => '[email protected]', | |
'firstname' => 'BatchUpdate3', | |
], | |
]; | |
$this->client->request(Request::METHOD_POST, '/api/contacts/batch/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
Assert::assertSame(Response::HTTP_CREATED, $clientResponse->getStatusCode(), $clientResponse->getContent()); | |
$response = json_decode($clientResponse->getContent(), true); | |
// Assert status codes | |
$this->assertEquals(Response::HTTP_CREATED, $response['statusCodes'][0]); | |
$contactId1 = $response['contacts'][0]['id']; | |
$this->assertEquals(Response::HTTP_CREATED, $response['statusCodes'][1]); | |
$contactId2 = $response['contacts'][1]['id']; | |
$this->assertEquals(Response::HTTP_CREATED, $response['statusCodes'][2]); | |
$contactId3 = $response['contacts'][2]['id']; | |
// Assert email | |
$this->assertEquals($payload[0]['email'], $response['contacts'][0]['fields']['all']['email']); | |
$this->assertEquals($payload[1]['email'], $response['contacts'][1]['fields']['all']['email']); | |
$this->assertEquals($payload[2]['email'], $response['contacts'][2]['fields']['all']['email']); | |
// Assert firstname | |
$this->assertEquals($payload[0]['firstname'], $response['contacts'][0]['fields']['all']['firstname']); | |
$this->assertEquals($payload[1]['firstname'], $response['contacts'][1]['fields']['all']['firstname']); | |
$this->assertEquals($payload[2]['firstname'], $response['contacts'][2]['fields']['all']['firstname']); | |
// Assert points while also testing empty precision as points is treated as a custom field | |
$this->assertSame(4, $response['contacts'][0]['points']); | |
$this->assertSame(4, $response['contacts'][0]['fields']['all']['points']); | |
$this->assertSame(0, $response['contacts'][1]['points']); | |
$this->assertSame(0, $response['contacts'][2]['points']); | |
$this->assertSame(0, $response['contacts'][2]['fields']['all']['points']); | |
// Assert tags | |
$this->assertEquals(2, count($response['contacts'][0]['tags'])); | |
$this->assertEquals(3, count($response['contacts'][1]['tags'])); | |
$this->assertEquals(0, count($response['contacts'][2]['tags'])); | |
// Assert city | |
$this->assertEquals($payload[0]['city'], $response['contacts'][0]['fields']['all']['city']); | |
$this->assertEquals($payload[1]['city'], $response['contacts'][1]['fields']['all']['city']); | |
$this->assertEquals('', $response['contacts'][2]['fields']['all']['city']); | |
// Assert state | |
$this->assertEquals($payload[0]['state'], $response['contacts'][0]['fields']['all']['state']); | |
$this->assertEquals($payload[1]['state'], $response['contacts'][1]['fields']['all']['state']); | |
$this->assertEquals('', $response['contacts'][2]['fields']['all']['state']); | |
// Assert country | |
$this->assertEquals($payload[0]['country'], $response['contacts'][0]['fields']['all']['country']); | |
$this->assertEquals($payload[1]['country'], $response['contacts'][1]['fields']['all']['country']); | |
$this->assertEquals('', $response['contacts'][2]['fields']['all']['country']); | |
// Assert preferred_locale | |
$this->assertEquals($payload[0]['preferred_locale'], $response['contacts'][0]['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload[1]['preferred_locale'], $response['contacts'][1]['fields']['all']['preferred_locale']); | |
$this->assertEquals('', $response['contacts'][2]['fields']['all']['preferred_locale']); | |
// Assert timezone | |
$this->assertEquals($payload[0]['timezone'], $response['contacts'][0]['fields']['all']['timezone']); | |
$this->assertEquals($payload[1]['timezone'], $response['contacts'][1]['fields']['all']['timezone']); | |
$this->assertEquals('', $response['contacts'][2]['fields']['all']['timezone']); | |
// Assert owner | |
$this->assertEquals($payload[0]['owner'], $response['contacts'][0]['owner']['id']); | |
$this->assertEquals(null, $response['contacts'][1]['owner']); | |
$this->assertEquals(null, $response['contacts'][2]['owner']); | |
// Assert company | |
$this->assertEquals($companyA->getId(), (int) $response['contacts'][0]['fields']['all']['company']); | |
$this->assertEquals(null, $response['contacts'][1]['fields']['all']['company']); | |
$this->assertEquals(null, $response['contacts'][2]['fields']['all']['company']); | |
// Emulate an unsanitized email to ensure that doesn't cause duplicates | |
$payload[0]['email'] = '[email protected],'; | |
// Set first name as null - Mautic should keep the value | |
$payload[0]['firstname'] = null; | |
// Remove tags from contact 1 to see if they will stick in the database | |
unset($payload[0]['tags']); | |
// Update others | |
$payload[0]['city'] = 'Sunnyvale'; | |
$payload[0]['state'] = 'California'; | |
$payload[0]['timezone'] = 'America/Los_Angeles'; | |
$payload[0]['preferred_locale'] = 'en_US'; | |
$payload[0]['company'] = $companyB->getId(); | |
// Update owner | |
$payload[0]['owner'] = null; | |
$payload[1]['owner'] = 1; | |
// Set some tags to contact 2 to see if tags update | |
$payload[1]['tags'] = ['testbatch1', 'testbatch2', '-batchremovetest']; | |
// Set some points to contact 2 to see if they update | |
$payload[1]['points'] = 3; | |
// Update the 3 contacts | |
$this->client->request(Request::METHOD_POST, '/api/contacts/batch/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
Assert::assertSame(Response::HTTP_CREATED, $clientResponse->getStatusCode(), $clientResponse->getContent()); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals(Response::HTTP_OK, $response['statusCodes'][0]); | |
$this->assertEquals($contactId1, $response['contacts'][0]['id']); | |
$this->assertEquals(Response::HTTP_OK, $response['statusCodes'][1]); | |
$this->assertEquals($contactId2, $response['contacts'][1]['id']); | |
$this->assertEquals(Response::HTTP_OK, $response['statusCodes'][2]); | |
$this->assertEquals($contactId3, $response['contacts'][2]['id']); | |
// Assert email | |
$this->assertEquals('[email protected]', $response['contacts'][0]['fields']['all']['email']); | |
$this->assertEquals($payload[1]['email'], $response['contacts'][1]['fields']['all']['email']); | |
$this->assertEquals($payload[2]['email'], $response['contacts'][2]['fields']['all']['email']); | |
// Assert firstname | |
$this->assertEquals('BatchUpdate', $response['contacts'][0]['fields']['all']['firstname']); | |
$this->assertEquals($payload[1]['firstname'], $response['contacts'][1]['fields']['all']['firstname']); | |
$this->assertEquals($payload[2]['firstname'], $response['contacts'][2]['fields']['all']['firstname']); | |
// Assert points | |
$this->assertSame(4, $response['contacts'][0]['points']); | |
$this->assertSame(4, $response['contacts'][0]['fields']['all']['points']); | |
$this->assertSame(3, $response['contacts'][1]['points']); | |
$this->assertSame(3, $response['contacts'][1]['fields']['all']['points']); | |
$this->assertSame(0, $response['contacts'][2]['points']); | |
$this->assertSame(0, $response['contacts'][2]['fields']['all']['points']); | |
// Assert tags | |
$this->assertEquals(2, count($response['contacts'][0]['tags'])); | |
$this->assertEquals(4, count($response['contacts'][1]['tags'])); | |
$this->assertEquals(0, count($response['contacts'][2]['tags'])); | |
// Assert city | |
$this->assertEquals($payload[0]['city'], $response['contacts'][0]['fields']['all']['city']); | |
$this->assertEquals($payload[1]['city'], $response['contacts'][1]['fields']['all']['city']); | |
$this->assertEquals('', $response['contacts'][2]['fields']['all']['city']); | |
// Assert state | |
$this->assertEquals($payload[0]['state'], $response['contacts'][0]['fields']['all']['state']); | |
$this->assertEquals($payload[1]['state'], $response['contacts'][1]['fields']['all']['state']); | |
$this->assertEquals('', $response['contacts'][2]['fields']['all']['state']); | |
// Assert country | |
$this->assertEquals($payload[0]['country'], $response['contacts'][0]['fields']['all']['country']); | |
$this->assertEquals($payload[1]['country'], $response['contacts'][1]['fields']['all']['country']); | |
$this->assertEquals('', $response['contacts'][2]['fields']['all']['country']); | |
// Assert preferred_locale | |
$this->assertEquals($payload[0]['preferred_locale'], $response['contacts'][0]['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload[1]['preferred_locale'], $response['contacts'][1]['fields']['all']['preferred_locale']); | |
$this->assertEquals('', $response['contacts'][2]['fields']['all']['preferred_locale']); | |
// Assert timezone | |
$this->assertEquals($payload[0]['timezone'], $response['contacts'][0]['fields']['all']['timezone']); | |
$this->assertEquals($payload[1]['timezone'], $response['contacts'][1]['fields']['all']['timezone']); | |
$this->assertEquals('', $response['contacts'][2]['fields']['all']['timezone']); | |
// Assert owner | |
$this->assertEquals(null, $response['contacts'][0]['owner']); | |
$this->assertEquals($payload[1]['owner'], $response['contacts'][1]['owner']['id']); | |
$this->assertEquals(null, $response['contacts'][2]['owner']); | |
// Assert company | |
$this->assertEquals($companyB->getId(), (int) $response['contacts'][0]['fields']['all']['company']); | |
$this->assertEquals(null, $response['contacts'][1]['fields']['all']['company']); | |
$this->assertEquals(null, $response['contacts'][2]['fields']['all']['company']); | |
} | |
/** | |
* If there are some entities to return then the response returns a hash table (JSON object), | |
* So for response with no entities we must also return a JSON object because some languages | |
* decode it differently then emtpty array. | |
*/ | |
public function testEmptyResponseReturnsJsonObject(): void | |
{ | |
$this->client->request('GET', '/api/contacts?where[0][val]=unicorn&where[0][col]=email&where[0][expr]=eq'); | |
$clientResponse = $this->client->getResponse(); | |
$this->assertTrue($this->client->getResponse()->isOk()); | |
$this->assertEquals('{"total":"0","contacts":{}}', $clientResponse->getContent()); | |
} | |
public function testBatchEditEndpoint(): void | |
{ | |
$contact = new Lead(); | |
$contact->setEmail('[email protected]'); | |
$this->em->persist($contact); | |
$this->em->flush(); | |
$this->em->clear(); | |
$payload = [ | |
['email' => '[email protected]', 'id' => $contact->getId()], | |
]; | |
$this->client->request('PUT', '/api/contacts/batch/edit', $payload); | |
$clientResponse = $this->client->getResponse(); | |
Assert::assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent()); | |
$response= json_decode($clientResponse->getContent(), true); | |
$this->assertEquals(Response::HTTP_OK, $response['statusCodes'][0]); | |
$this->assertEquals($contact->getId(), $response['contacts'][0]['id']); | |
$this->assertEquals('[email protected]', $response['contacts'][0]['fields']['all']['email']); | |
} | |
public function testBatchEditEndpointWithRubbishId(): void | |
{ | |
$payload = [ | |
['email' => '[email protected]', 'id' => 'rubbish'], | |
]; | |
$this->client->request('PUT', '/api/contacts/batch/edit', $payload); | |
$clientResponse = $this->client->getResponse(); | |
Assert::assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent()); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals(Response::HTTP_CREATED, $response['statusCodes'][0]); | |
$this->assertGreaterThanOrEqual(1, $response['contacts'][0]['id']); | |
$this->assertEquals('[email protected]', $response['contacts'][0]['fields']['all']['email']); | |
} | |
public function testSingleNewEndpointCreateAndUpdate(): void | |
{ | |
$payload = [ | |
'email' => '[email protected]', | |
'firstname' => 'API', | |
'lastname' => 'Update', | |
'points' => 4, | |
'tags' => ['apitest', 'testapi'], | |
'city' => 'Houston', | |
'state' => 'Texas', | |
'country' => 'United States', | |
'preferred_locale' => 'es_SV', | |
'timezone' => 'America/Chicago', | |
'owner' => 1, | |
]; | |
$this->client->request(Request::METHOD_POST, '/api/contacts/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$this->assertSame(Response::HTTP_CREATED, $clientResponse->getStatusCode(), $clientResponse->getContent()); | |
$response = json_decode($clientResponse->getContent(), true); | |
$contactId = $response['contact']['id']; | |
$this->assertEquals($payload['email'], $response['contact']['fields']['all']['email']); | |
$this->assertEquals($payload['firstname'], $response['contact']['fields']['all']['firstname']); | |
$this->assertEquals($payload['lastname'], $response['contact']['fields']['all']['lastname']); | |
$this->assertEquals(4, $response['contact']['points']); | |
$this->assertEquals(2, count($response['contact']['tags'])); | |
$this->assertEquals($payload['city'], $response['contact']['fields']['all']['city']); | |
$this->assertEquals($payload['state'], $response['contact']['fields']['all']['state']); | |
$this->assertEquals($payload['country'], $response['contact']['fields']['all']['country']); | |
$this->assertEquals($payload['preferred_locale'], $response['contact']['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload['timezone'], $response['contact']['fields']['all']['timezone']); | |
$this->assertEquals($payload['owner'], $response['contact']['owner']['id']); | |
// without overwriteWithBlank lastname is not set empty | |
$payload['lastname'] = ''; | |
// Lets try to create the same contact to see that the values are not re-setted | |
$this->client->request(Request::METHOD_POST, '/api/contacts/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contact']['id']); | |
$this->assertEquals($payload['email'], $response['contact']['fields']['all']['email']); | |
$this->assertEquals($payload['firstname'], $response['contact']['fields']['all']['firstname']); | |
$this->assertNotEmpty($response['contact']['fields']['all']['lastname']); | |
$this->assertEquals(4, $response['contact']['points']); | |
$this->assertEquals(2, count($response['contact']['tags'])); | |
// with overwriteWithBlank lastname is empty | |
$payload['overwriteWithBlank'] = true; | |
$payload['lastname'] = ''; | |
// Lets try to create the same contact to see that the values are not re-setted | |
$this->client->request(Request::METHOD_POST, '/api/contacts/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contact']['id']); | |
$this->assertEquals($payload['email'], $response['contact']['fields']['all']['email']); | |
$this->assertEquals($payload['firstname'], $response['contact']['fields']['all']['firstname']); | |
$this->assertEmpty($response['contact']['fields']['all']['lastname']); | |
$this->assertSame(4, $response['contact']['points']); | |
$this->assertSame(4, $response['contact']['fields']['all']['points']); | |
$this->assertEquals(2, count($response['contact']['tags'])); | |
$this->assertEquals($payload['city'], $response['contact']['fields']['all']['city']); | |
$this->assertEquals($payload['state'], $response['contact']['fields']['all']['state']); | |
$this->assertEquals($payload['country'], $response['contact']['fields']['all']['country']); | |
$this->assertEquals($payload['preferred_locale'], $response['contact']['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload['timezone'], $response['contact']['fields']['all']['timezone']); | |
$this->assertEquals($payload['owner'], $response['contact']['owner']['id']); | |
// Lets try to create the same contact and it should merge based on unique identifier (email) | |
$updatedValues = [ | |
'email' => '[email protected]', | |
'lastname' => 'Update', | |
'city' => 'Boston', | |
'state' => 'Massachusetts', | |
'owner' => 2, | |
]; | |
$this->client->request(Request::METHOD_POST, '/api/contacts/new', $updatedValues); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contact']['id']); | |
$this->assertEquals($updatedValues['email'], $response['contact']['fields']['all']['email']); | |
$this->assertEquals($payload['firstname'], $response['contact']['fields']['all']['firstname']); | |
$this->assertEquals($updatedValues['lastname'], $response['contact']['fields']['all']['lastname']); | |
$this->assertSame(4, $response['contact']['points']); | |
$this->assertSame(4, $response['contact']['fields']['all']['points']); | |
$this->assertEquals(2, count($response['contact']['tags'])); | |
$this->assertEquals($updatedValues['city'], $response['contact']['fields']['all']['city']); | |
$this->assertEquals($updatedValues['state'], $response['contact']['fields']['all']['state']); | |
$this->assertEquals($payload['country'], $response['contact']['fields']['all']['country']); | |
$this->assertEquals($payload['preferred_locale'], $response['contact']['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload['timezone'], $response['contact']['fields']['all']['timezone']); | |
$this->assertEquals($updatedValues['owner'], $response['contact']['owner']['id']); | |
// test: create the same contact, merge it based on unique identifier (email) - without loosing the owner and stage | |
unset($updatedValues['owner']); | |
$this->client->request('POST', '/api/contacts/new', $updatedValues); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contact']['id']); | |
$this->assertEquals($updatedValues['email'], $response['contact']['fields']['all']['email']); | |
$this->assertEquals($payload['firstname'], $response['contact']['fields']['all']['firstname']); | |
$this->assertEquals($updatedValues['lastname'], $response['contact']['fields']['all']['lastname']); | |
$this->assertSame(4, $response['contact']['points']); | |
$this->assertNull($response['contact']['stage']); // stage was not set on the contact | |
$this->assertSame(2, $response['contact']['owner']['id']); | |
// set the owner again for the other tests to work | |
$updatedValues['owner'] = 2; | |
// Test getting a contact | |
$this->client->request(Request::METHOD_GET, '/api/contacts/'.$contactId); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contact']['id']); | |
$this->assertEquals($payload['email'], $response['contact']['fields']['all']['email']); | |
$this->assertEquals($payload['firstname'], $response['contact']['fields']['all']['firstname']); | |
$this->assertSame(4, $response['contact']['points']); | |
$this->assertSame(4, $response['contact']['fields']['all']['points']); | |
$this->assertEquals(2, count($response['contact']['tags'])); | |
$this->assertEquals($updatedValues['city'], $response['contact']['fields']['all']['city']); | |
$this->assertEquals($updatedValues['state'], $response['contact']['fields']['all']['state']); | |
$this->assertEquals($payload['country'], $response['contact']['fields']['all']['country']); | |
$this->assertEquals($payload['preferred_locale'], $response['contact']['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload['timezone'], $response['contact']['fields']['all']['timezone']); | |
$this->assertEquals($updatedValues['owner'], $response['contact']['owner']['id']); | |
// Test fetching the batch of contacts | |
$this->client->request(Request::METHOD_GET, '/api/contacts'); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertTrue(isset($response['contacts'][$contactId])); | |
$contact = $response['contacts'][$contactId]; | |
$this->assertEquals($contactId, $contact['id']); | |
$this->assertEquals($payload['email'], $contact['fields']['all']['email']); | |
$this->assertEquals($payload['firstname'], $contact['fields']['all']['firstname']); | |
$this->assertSame(4, $contact['points']); | |
$this->assertSame(4, $contact['fields']['all']['points']); | |
$this->assertEquals(2, count($contact['tags'])); | |
$this->assertEquals($updatedValues['city'], $contact['fields']['all']['city']); | |
$this->assertEquals($updatedValues['state'], $contact['fields']['all']['state']); | |
$this->assertEquals($payload['country'], $contact['fields']['all']['country']); | |
$this->assertEquals($payload['preferred_locale'], $contact['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload['timezone'], $contact['fields']['all']['timezone']); | |
$this->assertEquals($updatedValues['owner'], $contact['owner']['id']); | |
// Test patch and values should be updated | |
$updatedValues = [ | |
'email' => '[email protected]', | |
'city' => 'Boston', | |
'state' => 'Massachusetts', | |
'owner' => 2, | |
'points' => 1, | |
]; | |
$this->client->request( | |
'PATCH', | |
sprintf('/api/contacts/%d/edit', $contactId), | |
$updatedValues | |
); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contact']['id']); | |
$this->assertEquals($updatedValues['email'], $response['contact']['fields']['all']['email']); | |
$this->assertEquals($payload['firstname'], $response['contact']['fields']['all']['firstname']); | |
$this->assertSame(1, $response['contact']['points']); | |
$this->assertSame(1, $response['contact']['fields']['all']['points']); | |
$this->assertEquals(2, count($response['contact']['tags'])); | |
$this->assertEquals($updatedValues['city'], $response['contact']['fields']['all']['city']); | |
$this->assertEquals($updatedValues['state'], $response['contact']['fields']['all']['state']); | |
$this->assertEquals($payload['country'], $response['contact']['fields']['all']['country']); | |
$this->assertEquals($payload['preferred_locale'], $response['contact']['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload['timezone'], $response['contact']['fields']['all']['timezone']); | |
$this->assertEquals($updatedValues['owner'], $response['contact']['owner']['id']); | |
} | |
/** | |
* Test creating a new contact with doNotContact information. | |
* The API response should include DNC information. | |
*/ | |
public function testSingleNewEndpointCreateAndDeleteWithDnc(): void | |
{ | |
$payload = [ | |
'email' => '[email protected]', | |
'firstname' => 'API', | |
'lastname' => 'DNC test', | |
'points' => 4, | |
'tags' => ['apitest', 'testapi'], | |
'city' => 'Houston', | |
'state' => 'Texas', | |
'country' => 'United States', | |
'preferred_locale' => 'es_SV', | |
'timezone' => 'America/Chicago', | |
'owner' => 1, | |
'doNotContact' => [ | |
[ | |
'channel' => 'email', | |
'reason' => DoNotContact::BOUNCED, | |
], | |
], | |
]; | |
$this->client->request(Request::METHOD_POST, '/api/contacts/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$contactId = $response['contact']['id']; | |
$this->assertEquals(1, count($response['contact']['doNotContact'])); | |
$this->assertEquals($payload['doNotContact'][0]['channel'], $response['contact']['doNotContact'][0]['channel']); | |
$this->assertEquals($payload['doNotContact'][0]['reason'], $response['contact']['doNotContact'][0]['reason']); | |
// Remove contact | |
$this->client->request(Request::METHOD_DELETE, "/api/contacts/$contactId/delete"); | |
$clientResponse = $this->client->getResponse(); | |
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode()); | |
} | |
public function testBatchNewEndpointCreateAndUpdate(): void | |
{ | |
$payload = [ | |
[ | |
'email' => '[email protected]', | |
'firstname' => 'API', | |
'lastname' => 'Update', | |
'points' => 4, | |
'tags' => ['apitest', 'testapi'], | |
'city' => 'Houston', | |
'state' => 'Texas', | |
'country' => 'United States', | |
'preferred_locale' => 'es_SV', | |
'timezone' => 'America/Chicago', | |
'owner' => 1, | |
], [ | |
'email' => '[email protected]', | |
'firstname' => 'API2', | |
'lastname' => 'Update2', | |
'points' => 3, | |
], | |
]; | |
$this->client->request('POST', '/api/contacts/batch/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$contactId = $response['contacts'][0]['id']; | |
$this->assertEquals($payload[0]['email'], $response['contacts'][0]['fields']['all']['email']); | |
$this->assertEquals($payload[0]['firstname'], $response['contacts'][0]['fields']['all']['firstname']); | |
$this->assertEquals($payload[0]['lastname'], $response['contacts'][0]['fields']['all']['lastname']); | |
$this->assertSame(4, $response['contacts'][0]['points']); | |
$this->assertSame(4, $response['contacts'][0]['fields']['all']['points']); | |
$this->assertEquals(2, count($response['contacts'][0]['tags'])); | |
$this->assertEquals($payload[0]['city'], $response['contacts'][0]['fields']['all']['city']); | |
$this->assertEquals($payload[0]['state'], $response['contacts'][0]['fields']['all']['state']); | |
$this->assertEquals($payload[0]['country'], $response['contacts'][0]['fields']['all']['country']); | |
$this->assertEquals($payload[0]['preferred_locale'], $response['contacts'][0]['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload[0]['timezone'], $response['contacts'][0]['fields']['all']['timezone']); | |
$this->assertEquals($payload[0]['owner'], $response['contacts'][0]['owner']['id']); | |
// without overwriteWithBlank lastname is not set empty | |
$payload[0]['lastname'] = ''; | |
// Lets try to create the same contact to see that the values are not re-setted | |
$this->client->request('POST', '/api/contacts/batch/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contacts'][0]['id']); | |
$this->assertEquals($payload[0]['email'], $response['contacts'][0]['fields']['all']['email']); | |
$this->assertEquals($payload[0]['firstname'], $response['contacts'][0]['fields']['all']['firstname']); | |
$this->assertNotEmpty($response['contacts'][0]['fields']['all']['lastname']); | |
$this->assertEquals(4, $response['contacts'][0]['points']); | |
$this->assertSame(4, $response['contacts'][0]['fields']['all']['points']); | |
$this->assertEquals(2, count($response['contacts'][0]['tags'])); | |
$this->assertEquals($payload[0]['city'], $response['contacts'][0]['fields']['all']['city']); | |
$this->assertEquals($payload[0]['state'], $response['contacts'][0]['fields']['all']['state']); | |
$this->assertEquals($payload[0]['country'], $response['contacts'][0]['fields']['all']['country']); | |
$this->assertEquals($payload[0]['preferred_locale'], $response['contacts'][0]['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload[0]['timezone'], $response['contacts'][0]['fields']['all']['timezone']); | |
$this->assertEquals($payload[0]['owner'], $response['contacts'][0]['owner']['id']); | |
// with overwriteWithBlank lastname is empty | |
$payload[0]['overwriteWithBlank'] = true; | |
$payload[0]['lastname'] = ''; | |
// Lets try to create the same contact to see that the values are not re-setted | |
$this->client->request('POST', '/api/contacts/batch/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contacts'][0]['id']); | |
$this->assertEquals($payload[0]['email'], $response['contacts'][0]['fields']['all']['email']); | |
$this->assertEquals($payload[0]['firstname'], $response['contacts'][0]['fields']['all']['firstname']); | |
$this->assertEmpty($response['contacts'][0]['fields']['all']['lastname']); | |
$this->assertEquals(4, $response['contacts'][0]['points']); | |
$this->assertSame(4, $response['contacts'][0]['fields']['all']['points']); | |
$this->assertEquals(2, count($response['contacts'][0]['tags'])); | |
// with overwriteWithBlank lastname is empty | |
$payload[0]['overwriteWithBlank'] = true; | |
$payload[0]['lastname'] = ''; | |
// Lets try to create the same contact to see that the values are not re-setted | |
$this->client->request('POST', '/api/contacts/batch/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contacts'][0]['id']); | |
$this->assertEquals($payload[0]['email'], $response['contacts'][0]['fields']['all']['email']); | |
$this->assertEquals($payload[0]['firstname'], $response['contacts'][0]['fields']['all']['firstname']); | |
$this->assertEmpty($response['contacts'][0]['fields']['all']['lastname']); | |
$this->assertSame(4, $response['contacts'][0]['points']); | |
$this->assertSame(4, $response['contacts'][0]['fields']['all']['points']); | |
$this->assertEquals(2, count($response['contacts'][0]['tags'])); | |
$this->assertEquals($payload[0]['city'], $response['contacts'][0]['fields']['all']['city']); | |
$this->assertEquals($payload[0]['state'], $response['contacts'][0]['fields']['all']['state']); | |
$this->assertEquals($payload[0]['country'], $response['contacts'][0]['fields']['all']['country']); | |
$this->assertEquals($payload[0]['preferred_locale'], $response['contacts'][0]['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload[0]['timezone'], $response['contacts'][0]['fields']['all']['timezone']); | |
$this->assertEquals($payload[0]['owner'], $response['contacts'][0]['owner']['id']); | |
// Lets try to create the same contact and it should merge based on unique identifier (email) | |
$updatedValues = [ | |
[ | |
'email' => '[email protected]', | |
'lastname' => 'Update', | |
'city' => 'Boston', | |
'state' => 'Massachusetts', | |
'owner' => 2, | |
], | |
]; | |
$this->client->request('POST', '/api/contacts/batch/new', $updatedValues); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contacts'][0]['id']); | |
$this->assertEquals($updatedValues[0]['email'], $response['contacts'][0]['fields']['all']['email']); | |
$this->assertEquals($payload[0]['firstname'], $response['contacts'][0]['fields']['all']['firstname']); | |
$this->assertEquals($updatedValues[0]['lastname'], $response['contacts'][0]['fields']['all']['lastname']); | |
$this->assertSame(4, $response['contacts'][0]['points']); | |
$this->assertSame(4, $response['contacts'][0]['fields']['all']['points']); | |
$this->assertEquals(2, count($response['contacts'][0]['tags'])); | |
$this->assertEquals($updatedValues[0]['city'], $response['contacts'][0]['fields']['all']['city']); | |
$this->assertEquals($updatedValues[0]['state'], $response['contacts'][0]['fields']['all']['state']); | |
$this->assertEquals($payload[0]['country'], $response['contacts'][0]['fields']['all']['country']); | |
$this->assertEquals($payload[0]['preferred_locale'], $response['contacts'][0]['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload[0]['timezone'], $response['contacts'][0]['fields']['all']['timezone']); | |
$this->assertEquals($updatedValues[0]['owner'], $response['contacts'][0]['owner']['id']); | |
// Test getting a contact | |
$this->client->request('GET', '/api/contacts/'.$contactId); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contact']['id']); | |
$this->assertEquals($payload[0]['email'], $response['contact']['fields']['all']['email']); | |
$this->assertEquals($payload[0]['firstname'], $response['contact']['fields']['all']['firstname']); | |
$this->assertSame(4, $response['contact']['points']); | |
$this->assertSame(4, $response['contact']['fields']['all']['points']); | |
$this->assertEquals(2, count($response['contact']['tags'])); | |
$this->assertEquals($updatedValues[0]['city'], $response['contact']['fields']['all']['city']); | |
$this->assertEquals($updatedValues[0]['state'], $response['contact']['fields']['all']['state']); | |
$this->assertEquals($payload[0]['country'], $response['contact']['fields']['all']['country']); | |
$this->assertEquals($payload[0]['preferred_locale'], $response['contact']['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload[0]['timezone'], $response['contact']['fields']['all']['timezone']); | |
$this->assertEquals($updatedValues[0]['owner'], $response['contact']['owner']['id']); | |
// Test fetching the batch of contacts | |
$this->client->request( | |
'GET', '/api/contacts'); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertTrue(isset($response['contacts'][$contactId])); | |
$contact = $response['contacts'][$contactId]; | |
$this->assertEquals($contactId, $contact['id']); | |
$this->assertEquals($payload[0]['email'], $contact['fields']['all']['email']); | |
$this->assertEquals($payload[0]['firstname'], $contact['fields']['all']['firstname']); | |
$this->assertSame(4, $contact['points']); | |
$this->assertSame(4, $contact['fields']['all']['points']); | |
$this->assertEquals(2, count($contact['tags'])); | |
$this->assertEquals($updatedValues[0]['city'], $contact['fields']['all']['city']); | |
$this->assertEquals($updatedValues[0]['state'], $contact['fields']['all']['state']); | |
$this->assertEquals($payload[0]['country'], $contact['fields']['all']['country']); | |
$this->assertEquals($payload[0]['preferred_locale'], $contact['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload[0]['timezone'], $contact['fields']['all']['timezone']); | |
$this->assertEquals($updatedValues[0]['owner'], $contact['owner']['id']); | |
// Test patch and values should be updated | |
$updatedValues = [ | |
[ | |
'id' => $contactId, | |
'email' => '[email protected]', | |
'city' => 'Boston', | |
'state' => 'Massachusetts', | |
'firstname' => '', // This will be ignored because overwriteWithBlank is false by default. | |
'owner' => 2, | |
'points' => 1, | |
], | |
]; | |
$this->client->request('PATCH', '/api/contacts/batch/edit', $updatedValues); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contacts'][0]['id']); | |
$this->assertEquals($updatedValues[0]['email'], $response['contacts'][0]['fields']['all']['email']); | |
$this->assertEquals($payload[0]['firstname'], $response['contacts'][0]['fields']['all']['firstname']); | |
$this->assertSame(1, $response['contacts'][0]['points']); | |
$this->assertSame(1, $response['contacts'][0]['fields']['all']['points']); | |
$this->assertEquals(2, count($response['contacts'][0]['tags'])); | |
$this->assertEquals($updatedValues[0]['city'], $response['contacts'][0]['fields']['all']['city']); | |
$this->assertEquals($updatedValues[0]['state'], $response['contacts'][0]['fields']['all']['state']); | |
$this->assertEquals($payload[0]['country'], $response['contacts'][0]['fields']['all']['country']); | |
$this->assertEquals($payload[0]['preferred_locale'], $response['contacts'][0]['fields']['all']['preferred_locale']); | |
$this->assertEquals($payload[0]['timezone'], $response['contacts'][0]['fields']['all']['timezone']); | |
$this->assertEquals($updatedValues[0]['owner'], $response['contacts'][0]['owner']['id']); | |
// with overwriteWithBlank lastname is empty | |
$updatedValues = [ | |
[ | |
'id' => $contactId, | |
'lastname' => '', | |
'overwriteWithBlank' => true, | |
], | |
]; | |
$this->client->request('PATCH', '/api/contacts/batch/edit', $updatedValues); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEquals($contactId, $response['contacts'][0]['id']); | |
$this->assertEquals($payload[0]['email'], $response['contacts'][0]['fields']['all']['email']); | |
$this->assertEquals($payload[0]['firstname'], $response['contacts'][0]['fields']['all']['firstname']); | |
$this->assertEmpty($response['contacts'][0]['fields']['all']['lastname']); | |
} | |
public function testBatchDncAddAndRemove(): void | |
{ | |
// Create contact | |
$emailAddress = uniqid('', false).'@mautic.com'; | |
$payload = [ | |
'id' => 80, | |
'email' => $emailAddress, | |
]; | |
$this->client->request(Request::METHOD_POST, '/api/contacts/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$contactId = $response['contact']['id']; | |
// Batch update contact with new DNC record | |
$payload = [ | |
[ | |
'id' => $contactId, | |
'email' => $emailAddress, | |
'doNotContact' => [ | |
[ | |
'reason' => DoNotContact::MANUAL, | |
'comments' => 'manually', | |
'channel' => 'email', | |
'channelId' => null, | |
], | |
], | |
], | |
]; | |
$this->client->request(Request::METHOD_PUT, '/api/contacts/batch/edit', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertSame(3, $response['contacts'][0]['doNotContact'][0]['reason']); | |
// Batch update contact and remove DNC record | |
$payload = [ | |
[ | |
'id' => $contactId, | |
'email' => $emailAddress, | |
'doNotContact' => [ | |
[ | |
'reason' => DoNotContact::IS_CONTACTABLE, | |
'comments' => 'manually', | |
'channel' => 'email', | |
'channelId' => null, | |
], | |
], | |
], | |
]; | |
$this->client->request(Request::METHOD_PUT, '/api/contacts/batch/edit', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$this->assertEmpty($response['contacts'][0]['doNotContact']); | |
// Remove contact | |
$this->client->request(Request::METHOD_DELETE, "/api/contacts/$contactId/delete"); | |
$clientResponse = $this->client->getResponse(); | |
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode()); | |
} | |
public function testAddAndRemoveDncToExistingContact(): void | |
{ | |
// Create contact | |
$payload = ['email' => '[email protected]']; | |
$this->client->request(Request::METHOD_POST, '/api/contacts/new', $payload); | |
$clientResponse = $this->client->getResponse(); | |
$response = json_decode($clientResponse->getContent(), true); | |
$contactId = $response['contact']['id']; | |
// Ensure that doNotContact is empty after creating the contact | |
$this->assertSame([], $response['contact']['doNotContact']); | |
// Check with a DNC payload that has an empty reasoncode in it, this should throw a 400 Bad Request error | |
$dncPayload = ['reason' => 0]; | |
$dncChannel = 'email'; | |
$this->client->request(Request::METHOD_POST, "/api/contacts/$contactId/dnc/$dncChannel/add", $dncPayload); | |
$clientResponse = $this->client->getResponse(); | |
$this->assertSame(Response::HTTP_BAD_REQUEST, $clientResponse->getStatusCode()); | |
// Leave the DNC payload empty to ensure it takes default values for channel and reason. | |
$dncPayload = []; | |
// Add DNC to the contact. | |
$this->client->request(Request::METHOD_POST, "/api/contacts/$contactId/dnc/$dncChannel/add", $dncPayload); | |
$clientResponse = $this->client->getResponse(); | |
$dncResponse = json_decode($clientResponse->getContent(), true); | |
// MANUAL (3) is the default value according to the dev docs: https://developer.mautic.org/#add-do-not-contact | |
$this->assertSame(DoNotContact::MANUAL, $dncResponse['contact']['doNotContact'][0]['reason']); | |
$this->assertSame($dncChannel, $dncResponse['contact']['doNotContact'][0]['channel']); | |
// Check DNC is recorded in the contact activity. | |
$this->client->request('GET', "/api/contacts/{$contactId}/activity"); | |
$clientResponse = $this->client->getResponse(); | |
self::assertSame(Response::HTTP_OK, $clientResponse->getStatusCode(), $clientResponse->getContent()); | |
$activityResponse = json_decode($clientResponse->getContent(), true); | |
Assert::assertCount(2, $activityResponse['events']); // identified and dnc added events | |
$dncEvents = array_values(array_filter($activityResponse['events'], fn ($event) => 'lead.donotcontact' === $event['event'])); | |
Assert::assertCount(1, $dncEvents); | |
Assert::assertSame('Email', $dncEvents[0]['eventLabel']); | |
Assert::assertSame('Contact was manually set as do not contact for this channel.', $dncEvents[0]['details']['dnc']['reason']); | |
// Remove DNC from the contact. | |
$this->client->request(Request::METHOD_POST, "/api/contacts/$contactId/dnc/$dncChannel/remove"); | |
$clientResponse = $this->client->getResponse(); | |
self::assertSame(Response::HTTP_OK, $clientResponse->getStatusCode()); | |
$dncRemoveResponse = json_decode($clientResponse->getContent(), true); | |
$this->assertArrayHasKey('contact', $dncRemoveResponse, $clientResponse->getContent()); | |
$this->assertSame([], $dncRemoveResponse['contact']['doNotContact']); | |
// Remove the contact. | |
$this->client->request(Request::METHOD_DELETE, "/api/contacts/$contactId/delete"); | |
$clientResponse = $this->client->getResponse(); | |
$this->assertSame(Response::HTTP_OK, $clientResponse->getStatusCode()); | |
} | |
private function createCompany(string $name): Company | |
{ | |
$company = new Company(); | |
$company->setName($name); | |
$this->em->persist($company); | |
$this->em->flush(); | |
return $company; | |
} | |
} | |