Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Api;
|
||||
|
||||
use MauticPlugin\MauticCrmBundle\Api\ConnectwiseApi;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\ConnectwiseIntegration;
|
||||
use MauticPlugin\MauticCrmBundle\Tests\Integration\DataGeneratorTrait;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(ConnectwiseApi::class)]
|
||||
class ConnectwiseApiTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
use DataGeneratorTrait;
|
||||
|
||||
/**
|
||||
* @throws \Mautic\PluginBundle\Exception\ApiErrorException
|
||||
*/
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Tests that fetchAllRecords loops until all records are obtained')]
|
||||
public function testResultPagination(): void
|
||||
{
|
||||
$integration = $this->getMockBuilder(ConnectwiseIntegration::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['makeRequest', 'getApiUrl'])
|
||||
->getMock();
|
||||
|
||||
$page = 0;
|
||||
$integration->expects($this->exactly(3))
|
||||
->method('makeRequest')
|
||||
->willReturnCallback(
|
||||
function ($endpoint, $parameters) use (&$page) {
|
||||
++$page;
|
||||
|
||||
// Page should be incremented 3 times by fetchAllRecords method
|
||||
$this->assertEquals(['page' => $page, 'pageSize' => ConnectwiseIntegration::PAGESIZE], $parameters);
|
||||
|
||||
return $this->generateData(3);
|
||||
}
|
||||
);
|
||||
|
||||
$api = new ConnectwiseApi($integration);
|
||||
|
||||
$records = $api->fetchAllRecords('test');
|
||||
|
||||
$this->assertEquals($this->generatedRecords, $records);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Api;
|
||||
|
||||
use Mautic\PluginBundle\Exception\ApiErrorException;
|
||||
use MauticPlugin\MauticCrmBundle\Api\HubspotApi;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\HubspotIntegration;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class HubspotApiTest extends TestCase
|
||||
{
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test Hubspot api when the api-key is invalid')]
|
||||
public function testHubspotWhenKeyIsInvalid(): void
|
||||
{
|
||||
$integration = $this->createMock(HubspotIntegration::class);
|
||||
$message = 'The API key provided is invalid. View or manage your API key here: https://app-eu1.hubspot.com/l/api-key/';
|
||||
$code = 401;
|
||||
$response = [
|
||||
'status' => 'error',
|
||||
'message' => $message,
|
||||
'correlationId' => '00000000-0000-0000-0000-000000000000',
|
||||
'category' => 'INVALID_AUTHENTICATION',
|
||||
'links' => [
|
||||
'api key' => 'https://app-eu1.hubspot.com/l/api-key/',
|
||||
],
|
||||
];
|
||||
|
||||
$integration->expects(self::once())
|
||||
->method('makeRequest')
|
||||
->willReturn(
|
||||
[
|
||||
'error' => [
|
||||
'code' => $code,
|
||||
'message' => json_encode($response),
|
||||
],
|
||||
]
|
||||
);
|
||||
$integration->expects(self::once())
|
||||
->method('getAuthenticationType')
|
||||
->willReturn('crm');
|
||||
|
||||
$this->expectException(ApiErrorException::class);
|
||||
$this->expectExceptionMessage($message);
|
||||
$this->expectExceptionCode($code);
|
||||
|
||||
$api = new HubspotApi($integration);
|
||||
$api->getLeadFields();
|
||||
|
||||
self::fail('ApiErrorException not thrown');
|
||||
}
|
||||
|
||||
public function testHubspotWhenKeyIsInvalidIfOauth(): void
|
||||
{
|
||||
$integration = $this->createMock(HubspotIntegration::class);
|
||||
$message = 'The API key provided is invalid. View or manage your API key here: https://app-eu1.hubspot.com/l/api-key/';
|
||||
$response = [
|
||||
'error' => 'error',
|
||||
'code' => 402,
|
||||
'message' => $message,
|
||||
'correlationId' => '00000000-0000-0000-0000-000000000000',
|
||||
'category' => 'INVALID_AUTHENTICATION',
|
||||
'links' => [
|
||||
'api key' => 'https://app-eu1.hubspot.com/l/api-key/',
|
||||
],
|
||||
];
|
||||
|
||||
$integration->expects(self::once())
|
||||
->method('makeRequest')
|
||||
->willReturn(['error' => $response]);
|
||||
$integration->expects(self::once())
|
||||
->method('getAuthenticationType')
|
||||
->willReturn('oauth2');
|
||||
|
||||
$this->expectException(ApiErrorException::class);
|
||||
$this->expectExceptionMessage($message);
|
||||
$this->expectExceptionCode(0);
|
||||
|
||||
$api = new HubspotApi($integration);
|
||||
$api->getLeadFields();
|
||||
|
||||
self::fail('ApiErrorException not thrown');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,522 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Api;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Mautic\CoreBundle\Helper\CacheStorageHelper;
|
||||
use Mautic\PluginBundle\Entity\Integration;
|
||||
use Mautic\PluginBundle\Exception\ApiErrorException;
|
||||
use MauticPlugin\MauticCrmBundle\Api\SalesforceApi;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\SalesforceIntegration;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(SalesforceApi::class)]
|
||||
class SalesforceApiTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that a locked record request is retried up to 3 times')]
|
||||
public function testRecordLockedErrorIsRetriedThreeTimes(): void
|
||||
{
|
||||
$integration = $this->createMock(SalesforceIntegration::class);
|
||||
$message = 'unable to obtain exclusive access to this record or 1 records: 70137000000Ugy3AAC';
|
||||
|
||||
$integration->expects($this->exactly(3))
|
||||
->method('makeRequest')
|
||||
->willReturn(
|
||||
[
|
||||
[
|
||||
'errorCode' => 'UNABLE_TO_LOCK_ROW',
|
||||
'message' => $message,
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
try {
|
||||
$api->request('/test');
|
||||
|
||||
$this->fail('ApiErrorException not thrown');
|
||||
} catch (ApiErrorException $exception) {
|
||||
$this->assertEquals($message, $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that a locked record request is retried up to 3 times with last one being successful so no exception should be thrown')]
|
||||
public function testRecordLockedErrorIsRetriedThreeTimesWithLastOneSuccessful(): void
|
||||
{
|
||||
$integration = $this->createMock(SalesforceIntegration::class);
|
||||
$message = 'unable to obtain exclusive access to this record or 1 records: 70137000000Ugy3AAC';
|
||||
|
||||
$integration->expects($this->exactly(3))
|
||||
->method('makeRequest')
|
||||
->willReturnOnConsecutiveCalls(
|
||||
[
|
||||
[
|
||||
'errorCode' => 'UNABLE_TO_LOCK_ROW',
|
||||
'message' => $message,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
'errorCode' => 'UNABLE_TO_LOCK_ROW',
|
||||
'message' => $message,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
'success' => true,
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
try {
|
||||
$api->request('/test');
|
||||
} catch (ApiErrorException) {
|
||||
$this->fail('ApiErrorException thrown');
|
||||
}
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that a locked record request is retried 2 times with 3rd being successful')]
|
||||
public function testRecordLockedErrorIsRetriedTwoTimesWithThirdSuccess(): void
|
||||
{
|
||||
$integration = $this->createMock(SalesforceIntegration::class);
|
||||
$message = 'unable to obtain exclusive access to this record or 1 records: 70137000000Ugy3AAC';
|
||||
|
||||
$integration->expects($this->exactly(2))
|
||||
->method('makeRequest')
|
||||
->willReturnOnConsecutiveCalls(
|
||||
[
|
||||
[
|
||||
'errorCode' => 'UNABLE_TO_LOCK_ROW',
|
||||
'message' => $message,
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
['success' => true],
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
try {
|
||||
$api->request('/test');
|
||||
} catch (ApiErrorException) {
|
||||
$this->fail('ApiErrorException should not have been thrown');
|
||||
}
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that a session expired should attempt a refresh before failing')]
|
||||
public function testSessionExpiredIsRefreshed(): void
|
||||
{
|
||||
$integration = $this->createMock(SalesforceIntegration::class);
|
||||
$message = '["errorCode":"INVALID_SESSION_ID","body":"Session expired or invalid"]';
|
||||
|
||||
$integration->expects($this->exactly(2))
|
||||
->method('authCallback');
|
||||
|
||||
$integration->expects($this->exactly(2))
|
||||
->method('makeRequest')
|
||||
->willReturn(
|
||||
[
|
||||
[
|
||||
'message' => $message,
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
try {
|
||||
$api->request('/test');
|
||||
$this->fail('ApiErrorException not thrown');
|
||||
} catch (ApiErrorException $exception) {
|
||||
$this->assertEquals($message, $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that a session expired should attempt a refresh but not throw an exception if successful on second request')]
|
||||
public function testSessionExpiredIsRefreshedWithoutThrowingExceptionOnSecondRequestWithSuccess(): void
|
||||
{
|
||||
$integration = $this->createMock(SalesforceIntegration::class);
|
||||
$message = 'Session expired';
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('authCallback');
|
||||
|
||||
// Test again but both attempts should fail resulting in
|
||||
$integration->expects($this->exactly(2))
|
||||
->method('makeRequest')
|
||||
->willReturnOnConsecutiveCalls(
|
||||
[
|
||||
[
|
||||
'errorCode' => 'INVALID_SESSION_ID',
|
||||
'message' => $message,
|
||||
],
|
||||
],
|
||||
[
|
||||
['success' => true],
|
||||
]
|
||||
);
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
try {
|
||||
$api->request('/test');
|
||||
} catch (ApiErrorException) {
|
||||
$this->fail('ApiErrorException thrown');
|
||||
}
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that an exception is thrown for all other errors')]
|
||||
public function testErrorDoesNotRetryRequest(): void
|
||||
{
|
||||
$integration = $this->createMock(SalesforceIntegration::class);
|
||||
$message = 'Fatal error';
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('makeRequest')
|
||||
->willReturn(
|
||||
[
|
||||
[
|
||||
'errorCode' => 'FATAL_ERROR',
|
||||
'message' => $message,
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
try {
|
||||
$api->request('/test');
|
||||
|
||||
$this->fail('ApiErrorException not thrown');
|
||||
} catch (ApiErrorException $exception) {
|
||||
$this->assertEquals($message, $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that a backslash and a single quote are escaped for SF queries')]
|
||||
public function testCompanyQueryIsEscapedCorrectly(): void
|
||||
{
|
||||
$integration = $this->getMockBuilder(SalesforceIntegration::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['mergeConfigToFeatureSettings', 'makeRequest', 'getQueryUrl', 'getIntegrationSettings', 'getFieldsForQuery', 'getApiUrl'])
|
||||
->getMock();
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('mergeConfigToFeatureSettings')
|
||||
->willReturn(
|
||||
[
|
||||
'objects' => [
|
||||
'company',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('makeRequest')
|
||||
->willReturnCallback(
|
||||
function ($url, $parameters = [], $method = 'GET', $settings = []): void {
|
||||
$this->assertEquals(
|
||||
[
|
||||
'q' => 'select Id from Account where Name = \'Some\\\\thing E\\\'lse\' and BillingCountry = \'Some\\\\Where E\\\'lse\' and BillingCity = \'Some\\\\Where E\\\'lse\' and BillingState = \'Some\\\\Where E\\\'lse\'',
|
||||
],
|
||||
$parameters
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
$api->getCompany(
|
||||
[
|
||||
'company' => [
|
||||
'BillingCountry' => 'Some\\Where E\'lse',
|
||||
'BillingCity' => 'Some\\Where E\'lse',
|
||||
'BillingState' => 'Some\\Where E\'lse',
|
||||
'Name' => 'Some\\thing E\'lse',
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that a backslash and an html entity of single quote are escaped for SF queries')]
|
||||
public function testCompanyQueryWithHtmlEntitiesIsEscapedCorrectly(): void
|
||||
{
|
||||
$integration = $this->getMockBuilder(SalesforceIntegration::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['mergeConfigToFeatureSettings', 'makeRequest', 'getQueryUrl', 'getIntegrationSettings', 'getFieldsForQuery', 'getApiUrl'])
|
||||
->getMock();
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('mergeConfigToFeatureSettings')
|
||||
->willReturn(
|
||||
[
|
||||
'objects' => [
|
||||
'company',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('makeRequest')
|
||||
->willReturnCallback(
|
||||
function ($url, $parameters = [], $method = 'GET', $settings = []): void {
|
||||
$this->assertEquals(
|
||||
[
|
||||
'q' => 'select Id from Account where Name = \'Some\\\\thing\\\' E\\\'lse\' and BillingCountry = \'Some\\\\Where\\\' E\\\'lse\' and BillingCity = \'Some\\\\Where\\\' E\\\'lse\' and BillingState = \'Some\\\\Where\\\' E\\\'lse\'',
|
||||
],
|
||||
$parameters
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
$api->getCompany(
|
||||
[
|
||||
'company' => [
|
||||
'BillingCountry' => 'Some\\Where' E\'lse',
|
||||
'BillingCity' => 'Some\\Where' E\'lse',
|
||||
'BillingState' => 'Some\\Where' E\'lse',
|
||||
'Name' => 'Some\\thing' E\'lse',
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that a backslash and a single quote are escaped for SF queries')]
|
||||
public function testContactQueryIsEscapedCorrectly(): void
|
||||
{
|
||||
$integration = $this->getMockBuilder(SalesforceIntegration::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['mergeConfigToFeatureSettings', 'makeRequest', 'getQueryUrl', 'getIntegrationSettings', 'getFieldsForQuery', 'getApiUrl'])
|
||||
->getMock();
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('mergeConfigToFeatureSettings')
|
||||
->willReturn(
|
||||
[
|
||||
'objects' => [
|
||||
'Contact',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('getFieldsForQuery')
|
||||
->willReturn([]);
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('makeRequest')
|
||||
->willReturnCallback(
|
||||
function ($url, $parameters = [], $method = 'GET', $settings = []): void {
|
||||
$this->assertEquals(
|
||||
[
|
||||
'q' => 'select Id from Contact where email = \'con\\\\tact\\\'email@email.com\'',
|
||||
],
|
||||
$parameters
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
$integration->method('getFieldsForQuery')
|
||||
->willReturn([]);
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
$api->getPerson([
|
||||
'Contact' => [
|
||||
'Email' => 'con\\tact\'email@email.com',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that a backslash and a single quote are escaped for SF queries')]
|
||||
public function testLeadQueryIsEscapedCorrectly(): void
|
||||
{
|
||||
$integration = $this->getMockBuilder(SalesforceIntegration::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['mergeConfigToFeatureSettings', 'makeRequest', 'getQueryUrl', 'getIntegrationSettings', 'getFieldsForQuery', 'getApiUrl'])
|
||||
->getMock();
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('mergeConfigToFeatureSettings')
|
||||
->willReturn(
|
||||
[
|
||||
'objects' => [
|
||||
'Lead',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('getFieldsForQuery')
|
||||
->willReturn([]);
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('makeRequest')
|
||||
->willReturnCallback(
|
||||
function ($url, $parameters = [], $method = 'GET', $settings = []): void {
|
||||
$this->assertEquals(
|
||||
[
|
||||
'q' => 'select Id from Lead where email = \'con\\\\tact\\\'email@email.com\' and ConvertedContactId = NULL',
|
||||
],
|
||||
$parameters
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
$integration->method('getFieldsForQuery')
|
||||
->willReturn([]);
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
$api->getPerson([
|
||||
'Lead' => [
|
||||
'Email' => 'con\\tact\'email@email.com',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function testHandleDeletesGracefullyWithHasOptedOutOfEmailAsMissingField(): void
|
||||
{
|
||||
/**
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
$cache = $this->createMock(CacheStorageHelper::class);
|
||||
|
||||
$cache
|
||||
->method('get')
|
||||
->withAnyParameters()
|
||||
->willReturn('2019-05-22 19:36:30');
|
||||
|
||||
$integration = $this->getMockBuilder(SalesforceIntegration::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods([
|
||||
'mergeConfigToFeatureSettings',
|
||||
'makeRequest',
|
||||
'getQueryUrl',
|
||||
'getIntegrationSettings',
|
||||
'getFieldsForQuery',
|
||||
'getApiUrl',
|
||||
'getCache',
|
||||
'getTranslator',
|
||||
'upsertUnreadAdminsNotification',
|
||||
])
|
||||
->getMock();
|
||||
|
||||
$integration
|
||||
->expects($this->atLeastOnce())
|
||||
->method('getCache')
|
||||
->willReturn($cache);
|
||||
|
||||
$integration->method('getFieldsForQuery')
|
||||
->with('Lead')
|
||||
->willReturn(['firstname', 'lastname', 'HasOptedOutOfEmail']);
|
||||
|
||||
$translator = $this->createMock(TranslatorInterface::class);
|
||||
|
||||
$integration->method('getTranslator')->willReturn($translator);
|
||||
|
||||
$this->expectException(ApiErrorException::class);
|
||||
$integration->expects($this->atLeastOnce())
|
||||
->method('makeRequest')
|
||||
->willReturn(
|
||||
[
|
||||
[
|
||||
'errorCode' => 'FATAL_ERROR',
|
||||
'message' => "ERROR at Row1\nNo such column 'HasOptedOutOfEmail' on entity 'Lead'",
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$params['start'] = '2019-05-22 19:36:30';
|
||||
$params['end'] = '2030-05-22 19:36:30';
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
self::assertEquals('2019-05-22 19:36:30', $api->getOrganizationCreatedDate());
|
||||
|
||||
$api->getLeads($params, 'Lead');
|
||||
}
|
||||
|
||||
public function testHandleDeletesGracefully(): void
|
||||
{
|
||||
/**
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
$cache = $this->createMock(CacheStorageHelper::class);
|
||||
|
||||
$cache
|
||||
->method('get')
|
||||
->withAnyParameters()
|
||||
->willReturn('2019-05-22 19:36:30');
|
||||
|
||||
$integration = $this->getMockBuilder(SalesforceIntegration::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods([
|
||||
'mergeConfigToFeatureSettings',
|
||||
'makeRequest',
|
||||
'getQueryUrl',
|
||||
'getIntegrationSettings',
|
||||
'getFieldsForQuery',
|
||||
'getApiUrl',
|
||||
'getCache',
|
||||
'getTranslator',
|
||||
'upsertUnreadAdminsNotification',
|
||||
'getEntityManager',
|
||||
])
|
||||
->getMock();
|
||||
|
||||
$integration
|
||||
->expects($this->atLeastOnce())
|
||||
->method('getCache')
|
||||
->willReturn($cache);
|
||||
|
||||
$integration->method('getFieldsForQuery')
|
||||
->with('Lead')
|
||||
->willReturn(['firstname', 'lastname', 'extraField']);
|
||||
|
||||
$integration->expects($this->never())->method('upsertUnreadAdminsNotification');
|
||||
|
||||
$entityManager = $this->createMock(EntityManager::class);
|
||||
|
||||
$entity = $this
|
||||
->getMockBuilder(Integration::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['getFeatureSettings', 'setFeatureSettings'])
|
||||
->getMock();
|
||||
|
||||
$integration->method('getEntityManager')->willReturn($entityManager);
|
||||
$integration->method('getIntegrationSettings')->willReturn($entity);
|
||||
$entity->method('getFeatureSettings')->willReturn(['leadFields' => ['extraField__Lead' => '']]);
|
||||
|
||||
$this->expectException(ApiErrorException::class);
|
||||
$integration->expects($this->atLeastOnce())
|
||||
->method('makeRequest')
|
||||
->willReturn(
|
||||
[
|
||||
[
|
||||
'errorCode' => 'FATAL_ERROR',
|
||||
'message' => "ERROR at Row1\nNo such column 'extraField' on entity 'Lead'",
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$params['start'] = '2019-05-22 19:36:30';
|
||||
$params['end'] = '2030-05-22 19:36:30';
|
||||
|
||||
$api = new SalesforceApi($integration);
|
||||
|
||||
self::assertEquals('2019-05-22 19:36:30', $api->getOrganizationCreatedDate());
|
||||
|
||||
$api->getLeads($params, 'Lead');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Api\Zoho;
|
||||
|
||||
use MauticPlugin\MauticCrmBundle\Api\Zoho\Exception\MatchingKeyNotFoundException;
|
||||
use MauticPlugin\MauticCrmBundle\Api\Zoho\Mapper;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(Mapper::class)]
|
||||
class MapperTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $availableFields = [
|
||||
'Leads' => [
|
||||
'Company' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Company',
|
||||
'api_name' => 'Company',
|
||||
'required' => true,
|
||||
],
|
||||
'FirstName' => [
|
||||
'type' => 'string',
|
||||
'label' => 'First Name',
|
||||
'api_name' => 'First Name',
|
||||
'required' => false,
|
||||
],
|
||||
'LastName' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Last Name',
|
||||
'api_name' => 'Last Name',
|
||||
'required' => true,
|
||||
],
|
||||
'Email' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Email',
|
||||
'api_name' => 'Email',
|
||||
'required' => false,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $mappedFields = [
|
||||
'Company' => 'company',
|
||||
'Email' => 'email',
|
||||
'Country' => 'country',
|
||||
'FirstName' => 'firstname',
|
||||
'LastName' => 'lastname',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $contacts = [
|
||||
[
|
||||
'firstname' => 'FirstName1',
|
||||
'lastname' => 'LastName1',
|
||||
'email' => 'zoho1@email.com',
|
||||
'integration_entity' => 'Leads',
|
||||
'integration_entity_id' => 'abc',
|
||||
'internal_entity' => 'lead',
|
||||
'internal_entity_id' => 1,
|
||||
],
|
||||
[
|
||||
'firstname' => 'FirstName2',
|
||||
'lastname' => 'LastName2',
|
||||
'email' => 'zoho2@email.com',
|
||||
'integration_entity' => 'Leads',
|
||||
'integration_entity_id' => 'def',
|
||||
'internal_entity' => 'lead',
|
||||
'internal_entity_id' => 2,
|
||||
],
|
||||
[
|
||||
'firstname' => 'FirstName3',
|
||||
'lastname' => 'LastName3',
|
||||
'email' => 'zoho3@email.com',
|
||||
'integration_entity' => 'Leads',
|
||||
'integration_entity_id' => 'ghi',
|
||||
'internal_entity' => 'lead',
|
||||
'internal_entity_id' => 3,
|
||||
],
|
||||
];
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that array is generated according to the mapping')]
|
||||
public function testArrayIsGeneratedBasedOnMapping(): void
|
||||
{
|
||||
$mapper = new Mapper($this->availableFields);
|
||||
$mapper->setObject('Leads');
|
||||
|
||||
foreach ($this->contacts as $contact) {
|
||||
$mapper->setMappedFields($this->mappedFields)
|
||||
->setContact($contact)
|
||||
->map($contact['internal_entity_id']);
|
||||
}
|
||||
|
||||
$expected = [
|
||||
[
|
||||
'Email' => 'zoho1@email.com',
|
||||
'First Name' => 'FirstName1',
|
||||
'Last Name' => 'LastName1',
|
||||
],
|
||||
[
|
||||
'Email' => 'zoho2@email.com',
|
||||
'First Name' => 'FirstName2',
|
||||
'Last Name' => 'LastName2',
|
||||
],
|
||||
[
|
||||
'Email' => 'zoho3@email.com',
|
||||
'First Name' => 'FirstName3',
|
||||
'Last Name' => 'LastName3',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $mapper->getArray());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that contacts do not inherit previous contact information')]
|
||||
public function testContactDoesNotInheritPreviousContactData(): void
|
||||
{
|
||||
$mapper = new Mapper($this->availableFields);
|
||||
$mapper->setObject('Leads');
|
||||
|
||||
$contacts = $this->contacts;
|
||||
$contacts[1]['firstname'] = null;
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
$mapper->setMappedFields($this->mappedFields)
|
||||
->setContact($contact)
|
||||
->map($contact['internal_entity_id'], $contact['integration_entity_id']);
|
||||
}
|
||||
|
||||
$expected = [
|
||||
[
|
||||
'id' => 'abc',
|
||||
'Email' => 'zoho1@email.com',
|
||||
'First Name' => 'FirstName1',
|
||||
'Last Name' => 'LastName1',
|
||||
],
|
||||
[
|
||||
'id' => 'def',
|
||||
'Email' => 'zoho2@email.com',
|
||||
'Last Name' => 'LastName2',
|
||||
],
|
||||
[
|
||||
'id' => 'ghi',
|
||||
'Email' => 'zoho3@email.com',
|
||||
'First Name' => 'FirstName3',
|
||||
'Last Name' => 'LastName3',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $mapper->getArray());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that array is generated according to the mapping')]
|
||||
public function testArrayIsGeneratedBasedOnMappingWithId(): void
|
||||
{
|
||||
$mapper = new Mapper($this->availableFields);
|
||||
$mapper->setObject('Leads');
|
||||
|
||||
foreach ($this->contacts as $contact) {
|
||||
$mapper->setMappedFields($this->mappedFields)
|
||||
->setContact($contact)
|
||||
->map($contact['internal_entity_id'], $contact['integration_entity_id']);
|
||||
}
|
||||
|
||||
$expected = [
|
||||
[
|
||||
'id' => 'abc',
|
||||
'Email' => 'zoho1@email.com',
|
||||
'First Name' => 'FirstName1',
|
||||
'Last Name' => 'LastName1',
|
||||
],
|
||||
[
|
||||
'id' => 'def',
|
||||
'First Name' => 'FirstName2',
|
||||
'Email' => 'zoho2@email.com',
|
||||
'Last Name' => 'LastName2',
|
||||
],
|
||||
[
|
||||
'id' => 'ghi',
|
||||
'Email' => 'zoho3@email.com',
|
||||
'First Name' => 'FirstName3',
|
||||
'Last Name' => 'LastName3',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $mapper->getArray());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test asking for a key returns the correct contact')]
|
||||
public function testThatContactIdMatchesGivenKey(): void
|
||||
{
|
||||
$mapper = new Mapper($this->availableFields);
|
||||
$mapper->setObject('Leads');
|
||||
|
||||
foreach ($this->contacts as $contact) {
|
||||
$mapper->setMappedFields($this->mappedFields)
|
||||
->setContact($contact)
|
||||
->map($contact['internal_entity_id'], $contact['integration_entity_id']);
|
||||
}
|
||||
|
||||
$this->assertEquals(3, $mapper->getContactIdByKey(2));
|
||||
$this->assertEquals(2, $mapper->getContactIdByKey(1));
|
||||
$this->assertEquals(1, $mapper->getContactIdByKey(0));
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox("Test asking for a key that doesn't exist throws exception")]
|
||||
public function testThatExceptionIsThrownIfKeyNotFound(): void
|
||||
{
|
||||
$this->expectException(MatchingKeyNotFoundException::class);
|
||||
|
||||
$mapper = new Mapper($this->availableFields);
|
||||
$mapper->setObject('Leads');
|
||||
|
||||
foreach ($this->contacts as $contact) {
|
||||
$mapper->setMappedFields($this->mappedFields)
|
||||
->setContact($contact)
|
||||
->map($contact['internal_entity_id'], $contact['integration_entity_id']);
|
||||
}
|
||||
|
||||
$mapper->getContactIdByKey(4);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests;
|
||||
|
||||
use Mautic\EmailBundle\Helper\EmailValidator;
|
||||
use Mautic\LeadBundle\Deduplicate\CompanyDeduper;
|
||||
use Mautic\PluginBundle\Tests\Integration\AbstractIntegrationTestCase;
|
||||
use MauticPlugin\MauticCrmBundle\Tests\Fixtures\Model\CompanyModelStub;
|
||||
use MauticPlugin\MauticCrmBundle\Tests\Stubs\StubIntegration;
|
||||
use PHPUnit\Framework\MockObject\MockBuilder;
|
||||
|
||||
class CrmAbstractIntegrationTest extends AbstractIntegrationTestCase
|
||||
{
|
||||
public function testFieldMatchingPriority(): void
|
||||
{
|
||||
$config = [
|
||||
'update_mautic' => [
|
||||
'email' => '1',
|
||||
'first_name' => '0',
|
||||
'last_name' => '0',
|
||||
'address_1' => '1',
|
||||
'address_2' => '1',
|
||||
],
|
||||
];
|
||||
|
||||
/** @var MockBuilder $mockBuilder */
|
||||
$mockBuilder = $this->getMockBuilder(StubIntegration::class);
|
||||
$mockBuilder->disableOriginalConstructor();
|
||||
|
||||
/** @var StubIntegration $integration */
|
||||
$integration = $mockBuilder->getMock();
|
||||
|
||||
$methodMautic = new \ReflectionMethod(StubIntegration::class, 'getPriorityFieldsForMautic');
|
||||
$methodMautic->setAccessible(true);
|
||||
|
||||
$methodIntegration = new \ReflectionMethod(StubIntegration::class, 'getPriorityFieldsForIntegration');
|
||||
$methodIntegration->setAccessible(true);
|
||||
|
||||
$fieldsForMautic = $methodMautic->invokeArgs($integration, [$config]);
|
||||
|
||||
$this->assertSame(
|
||||
['email', 'address_1', 'address_2'],
|
||||
$fieldsForMautic,
|
||||
'Fields to update in Mautic should return fields marked as 1 in the integration priority config.'
|
||||
);
|
||||
|
||||
$fieldsForIntegration = $methodIntegration->invokeArgs($integration, [$config]);
|
||||
|
||||
$this->assertSame(
|
||||
['first_name', 'last_name'],
|
||||
$fieldsForIntegration,
|
||||
'Fields to update in the integration should return fields marked as 0 in the integration priority config.'
|
||||
);
|
||||
}
|
||||
|
||||
public function testCompanyDataIsMappedForNewCompanies(): void
|
||||
{
|
||||
$data = [
|
||||
'custom_company_name' => 'Some Business',
|
||||
'some_custom_field' => 'some value',
|
||||
];
|
||||
|
||||
$emailValidator = $this->createMock(EmailValidator::class);
|
||||
|
||||
$companyDeduper = $this->createMock(CompanyDeduper::class);
|
||||
|
||||
$companyModel = $this->getMockBuilder(CompanyModelStub::class)
|
||||
->onlyMethods(['fetchCompanyFields', 'organizeFieldsByGroup', 'saveEntity'])
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$companyModel->setFieldModel($this->fieldModel);
|
||||
$companyModel->setEmailValidator($emailValidator);
|
||||
$companyModel->setCompanyDeduper($companyDeduper);
|
||||
|
||||
$companyModel->expects($this->any())
|
||||
->method('fetchCompanyFields')
|
||||
->willReturn([]);
|
||||
$companyModel->expects($this->once())
|
||||
->method('organizeFieldsByGroup')
|
||||
->willReturn([
|
||||
'core' => [
|
||||
'companyname' => [
|
||||
'alias' => 'companyname',
|
||||
'type' => 'text',
|
||||
],
|
||||
'custom_company_name' => [
|
||||
'alias' => 'custom_company_name',
|
||||
'type' => 'text',
|
||||
],
|
||||
'some_custom_field' => [
|
||||
'alias' => 'some_custom_field',
|
||||
'type' => 'text',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$integration = $this->getMockBuilder(StubIntegration::class)
|
||||
->setConstructorArgs([
|
||||
$this->dispatcher,
|
||||
$this->cache,
|
||||
$this->em,
|
||||
$this->request,
|
||||
$this->router,
|
||||
$this->translator,
|
||||
$this->logger,
|
||||
$this->encryptionHelper,
|
||||
$this->leadModel,
|
||||
$companyModel,
|
||||
$this->pathsHelper,
|
||||
$this->notificationModel,
|
||||
$this->fieldModel,
|
||||
$this->integrationEntityModel,
|
||||
$this->doNotContact,
|
||||
$this->fieldsWithUniqueIdentifier,
|
||||
])
|
||||
->onlyMethods(['populateMauticLeadData', 'mergeConfigToFeatureSettings'])
|
||||
->getMock();
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('populateMauticLeadData')
|
||||
->willReturn($data);
|
||||
|
||||
$company = $integration->getMauticCompany($data);
|
||||
|
||||
$this->assertEquals('Some Business', $company->getName());
|
||||
$this->assertEquals('Some Business', $company->getFieldValue('custom_company_name'));
|
||||
$this->assertEquals('some value', $company->getFieldValue('some_custom_field'));
|
||||
}
|
||||
|
||||
public function testLimitString(): void
|
||||
{
|
||||
$integration = $this->createMock(StubIntegration::class);
|
||||
|
||||
$methodLimitString = new \ReflectionMethod(StubIntegration::class, 'limitString');
|
||||
$methodLimitString->setAccessible(true);
|
||||
|
||||
$string = 'SomeRandomString';
|
||||
|
||||
$result = $methodLimitString->invokeArgs($integration, [str_repeat($string, 100), 'text']);
|
||||
$this->assertSame(strlen($result), 255);
|
||||
|
||||
$result = $methodLimitString->invokeArgs($integration, [$string, 'text']);
|
||||
$this->assertSame(strlen($result), strlen($string));
|
||||
$this->assertSame($result, $string);
|
||||
|
||||
$result = $methodLimitString->invokeArgs($integration, [true, 'text']);
|
||||
$this->assertSame($result, true);
|
||||
|
||||
$result = $methodLimitString->invokeArgs($integration, [false, 'text']);
|
||||
$this->assertSame($result, false);
|
||||
|
||||
$result = $methodLimitString->invokeArgs($integration, [[1, 2, 3]]);
|
||||
$this->assertSame($result, [1, 2, 3]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests;
|
||||
|
||||
use Mautic\PluginBundle\Tests\Integration\AbstractIntegrationTestCase;
|
||||
use MauticPlugin\MauticCrmBundle\Api\DynamicsApi;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\DynamicsIntegration;
|
||||
|
||||
class DynamicsApiTest extends AbstractIntegrationTestCase
|
||||
{
|
||||
private DynamicsApi $api;
|
||||
|
||||
private DynamicsIntegration $integration;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->integration = new DynamicsIntegration(
|
||||
$this->dispatcher,
|
||||
$this->cache,
|
||||
$this->em,
|
||||
$this->request,
|
||||
$this->router,
|
||||
$this->translator,
|
||||
$this->logger,
|
||||
$this->encryptionHelper,
|
||||
$this->leadModel,
|
||||
$this->companyModel,
|
||||
$this->pathsHelper,
|
||||
$this->notificationModel,
|
||||
$this->fieldModel,
|
||||
$this->integrationEntityModel,
|
||||
$this->doNotContact,
|
||||
$this->fieldsWithUniqueIdentifier
|
||||
);
|
||||
|
||||
$this->api = new DynamicsApi($this->integration);
|
||||
}
|
||||
|
||||
public function testIntegration(): void
|
||||
{
|
||||
$this->assertSame('Dynamics', $this->integration->getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests;
|
||||
|
||||
use Mautic\PluginBundle\Tests\Integration\AbstractIntegrationTestCase;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\DynamicsIntegration;
|
||||
|
||||
class DynamicsIntegrationTest extends AbstractIntegrationTestCase
|
||||
{
|
||||
private DynamicsIntegration $integration;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->integration = new DynamicsIntegration(
|
||||
$this->dispatcher,
|
||||
$this->cache,
|
||||
$this->em,
|
||||
$this->request,
|
||||
$this->router,
|
||||
$this->translator,
|
||||
$this->logger,
|
||||
$this->encryptionHelper,
|
||||
$this->leadModel,
|
||||
$this->companyModel,
|
||||
$this->pathsHelper,
|
||||
$this->notificationModel,
|
||||
$this->fieldModel,
|
||||
$this->integrationEntityModel,
|
||||
$this->doNotContact,
|
||||
$this->fieldsWithUniqueIdentifier
|
||||
);
|
||||
}
|
||||
|
||||
public function testIntegration(): void
|
||||
{
|
||||
$this->assertSame('Dynamics', $this->integration->getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Fixtures\Model;
|
||||
|
||||
use Mautic\EmailBundle\Helper\EmailValidator;
|
||||
use Mautic\LeadBundle\Deduplicate\CompanyDeduper;
|
||||
use Mautic\LeadBundle\Model\CompanyModel;
|
||||
use Mautic\LeadBundle\Model\FieldModel;
|
||||
|
||||
class CompanyModelStub extends CompanyModel
|
||||
{
|
||||
public function setFieldModel(FieldModel $fieldModel): void
|
||||
{
|
||||
$this->leadFieldModel = $fieldModel;
|
||||
}
|
||||
|
||||
public function setEmailValidator(EmailValidator $validator): void
|
||||
{
|
||||
$this->emailValidator = $validator;
|
||||
}
|
||||
|
||||
public function setCompanyDeduper(CompanyDeduper $companyDeduper): void
|
||||
{
|
||||
$this->companyDeduper = $companyDeduper;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Integration;
|
||||
|
||||
use Mautic\PluginBundle\Model\IntegrationEntityModel;
|
||||
use Mautic\PluginBundle\Tests\Integration\AbstractIntegrationTestCase;
|
||||
use MauticPlugin\MauticCrmBundle\Api\ConnectwiseApi;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\ConnectwiseIntegration;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(ConnectwiseIntegration::class)]
|
||||
class ConnectwiseIntegrationTest extends AbstractIntegrationTestCase
|
||||
{
|
||||
use DataGeneratorTrait;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that all records are fetched till last page of results are consumed')]
|
||||
public function testMultiplePagesOfRecordsAreFetched(): void
|
||||
{
|
||||
$this->reset();
|
||||
|
||||
$apiHelper = $this->createMock(ConnectwiseApi::class);
|
||||
|
||||
$apiHelper->expects($this->exactly(2))
|
||||
->method('getContacts')
|
||||
->willReturnCallback(
|
||||
fn () => $this->generateData(2)
|
||||
);
|
||||
|
||||
$integration = $this->getMockBuilder(ConnectwiseIntegration::class)
|
||||
->disableOriginalConstructor()
|
||||
->onlyMethods(['isAuthorized', 'getApiHelper', 'getMauticLead'])
|
||||
->getMock();
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('isAuthorized')
|
||||
->willReturn(true);
|
||||
|
||||
$integration
|
||||
->method('getApiHelper')
|
||||
->willReturn($apiHelper);
|
||||
|
||||
$integration->getRecords([], 'Contact');
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\TestDox('Test that all records are fetched till last page of results are consumed')]
|
||||
public function testMultiplePagesOfCampaignMemberRecordsAreFetched(): void
|
||||
{
|
||||
$this->reset();
|
||||
|
||||
$apiHelper = $this->createMock(ConnectwiseApi::class);
|
||||
|
||||
$apiHelper->expects($this->exactly(2))
|
||||
->method('getCampaignMembers')
|
||||
->willReturnCallback(
|
||||
fn () => $this->generateData(2)
|
||||
);
|
||||
|
||||
$integrationEntityModel = $this->createMock(IntegrationEntityModel::class);
|
||||
|
||||
$integration = $this->getMockBuilder(ConnectwiseIntegration::class)
|
||||
->setConstructorArgs([
|
||||
$this->dispatcher,
|
||||
$this->cache,
|
||||
$this->em,
|
||||
$this->request,
|
||||
$this->router,
|
||||
$this->translator,
|
||||
$this->logger,
|
||||
$this->encryptionHelper,
|
||||
$this->leadModel,
|
||||
$this->companyModel,
|
||||
$this->pathsHelper,
|
||||
$this->notificationModel,
|
||||
$this->fieldModel,
|
||||
$integrationEntityModel,
|
||||
$this->doNotContact,
|
||||
$this->fieldsWithUniqueIdentifier,
|
||||
])
|
||||
->onlyMethods(['isAuthorized', 'getApiHelper', 'getRecords', 'saveCampaignMembers'])
|
||||
->getMock();
|
||||
|
||||
$integration->expects($this->once())
|
||||
->method('isAuthorized')
|
||||
->willReturn(true);
|
||||
|
||||
$integration
|
||||
->method('getApiHelper')
|
||||
->willReturn($apiHelper);
|
||||
|
||||
$integration->getCampaignMembers(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Integration;
|
||||
|
||||
use MauticPlugin\MauticCrmBundle\Integration\ConnectwiseIntegration;
|
||||
|
||||
trait DataGeneratorTrait
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $page = 1;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $id = 0;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $generatedRecords = [];
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function generateData($maxPages)
|
||||
{
|
||||
$pageSize = ($this->page === $maxPages) ? ConnectwiseIntegration::PAGESIZE / 2 : ConnectwiseIntegration::PAGESIZE;
|
||||
$fakeData = [];
|
||||
$counter = 0;
|
||||
while ($counter < $pageSize) {
|
||||
$data = [
|
||||
'id' => $this->id,
|
||||
];
|
||||
$fakeData[] = $data;
|
||||
$this->generatedRecords[] = $data;
|
||||
|
||||
++$counter;
|
||||
++$this->id;
|
||||
}
|
||||
++$this->page;
|
||||
|
||||
return $fakeData;
|
||||
}
|
||||
|
||||
protected function reset()
|
||||
{
|
||||
$this->id = 0;
|
||||
$this->page = 1;
|
||||
$this->generatedRecords = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Integration;
|
||||
|
||||
use Mautic\CoreBundle\Helper\UserHelper;
|
||||
use Mautic\PluginBundle\Entity\Integration;
|
||||
use Mautic\PluginBundle\Event\PluginIntegrationKeyEvent;
|
||||
use Mautic\PluginBundle\PluginEvents;
|
||||
use Mautic\PluginBundle\Tests\Integration\AbstractIntegrationTestCase;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\HubspotIntegration;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class HubspotIntegrationTest extends AbstractIntegrationTestCase
|
||||
{
|
||||
/**
|
||||
* @var MockObject&UserHelper
|
||||
*/
|
||||
private MockObject $userHelper;
|
||||
|
||||
private HubspotIntegration $integration;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->userHelper = $this->createMock(UserHelper::class);
|
||||
$this->integration = new HubspotIntegration(
|
||||
$this->dispatcher,
|
||||
$this->cache,
|
||||
$this->em,
|
||||
$this->request,
|
||||
$this->router,
|
||||
$this->translator,
|
||||
$this->logger,
|
||||
$this->encryptionHelper,
|
||||
$this->leadModel,
|
||||
$this->companyModel,
|
||||
$this->pathsHelper,
|
||||
$this->notificationModel,
|
||||
$this->fieldModel,
|
||||
$this->integrationEntityModel,
|
||||
$this->doNotContact,
|
||||
$this->fieldsWithUniqueIdentifier,
|
||||
$this->userHelper
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetRequiredKeyFields(): void
|
||||
{
|
||||
self::assertSame([], $this->integration->getRequiredKeyFields());
|
||||
}
|
||||
|
||||
public function testGetBearerTokenEmpty(): void
|
||||
{
|
||||
$event = $this->createMock(PluginIntegrationKeyEvent::class);
|
||||
$event->expects(self::once())
|
||||
->method('getKeys')
|
||||
->willReturn(['other' => 'data']);
|
||||
$this->dispatcher->expects(self::once())
|
||||
->method('dispatch')
|
||||
->with(
|
||||
new PluginIntegrationKeyEvent($this->integration, [HubspotIntegration::ACCESS_KEY]),
|
||||
PluginEvents::PLUGIN_ON_INTEGRATION_KEYS_ENCRYPT
|
||||
)
|
||||
->willReturn($event);
|
||||
|
||||
$this->integration->encryptAndSetApiKeys([HubspotIntegration::ACCESS_KEY], $this->createMock(Integration::class));
|
||||
self::assertNull($this->integration->getBearerToken());
|
||||
}
|
||||
|
||||
public function testGetBearerTokenSet(): void
|
||||
{
|
||||
$token = 'token';
|
||||
|
||||
$event = $this->createMock(PluginIntegrationKeyEvent::class);
|
||||
$event->expects(self::once())
|
||||
->method('getKeys')
|
||||
->willReturn(['other' => 'data', HubspotIntegration::ACCESS_KEY => $token]);
|
||||
$this->dispatcher->expects(self::once())
|
||||
->method('dispatch')
|
||||
->with(
|
||||
new PluginIntegrationKeyEvent($this->integration, [HubspotIntegration::ACCESS_KEY]),
|
||||
PluginEvents::PLUGIN_ON_INTEGRATION_KEYS_ENCRYPT
|
||||
)
|
||||
->willReturn($event);
|
||||
|
||||
$this->integration->encryptAndSetApiKeys([HubspotIntegration::ACCESS_KEY], $this->createMock(Integration::class));
|
||||
self::assertSame($token, $this->integration->getBearerToken());
|
||||
}
|
||||
|
||||
public function testGetFormSettings(): void
|
||||
{
|
||||
self::assertSame(
|
||||
[
|
||||
'requires_callback' => false,
|
||||
'requires_authorization' => false,
|
||||
],
|
||||
$this->integration->getFormSettings()
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetAuthenticationTypeNoOauthToken(): void
|
||||
{
|
||||
$event = $this->createMock(PluginIntegrationKeyEvent::class);
|
||||
$event->expects(self::once())
|
||||
->method('getKeys')
|
||||
->willReturn(['other' => 'data']);
|
||||
$this->dispatcher->expects(self::once())
|
||||
->method('dispatch')
|
||||
->with(
|
||||
new PluginIntegrationKeyEvent($this->integration, [HubspotIntegration::ACCESS_KEY]),
|
||||
PluginEvents::PLUGIN_ON_INTEGRATION_KEYS_ENCRYPT
|
||||
)
|
||||
->willReturn($event);
|
||||
|
||||
$this->integration->encryptAndSetApiKeys([HubspotIntegration::ACCESS_KEY], $this->createMock(Integration::class));
|
||||
self::assertSame('key', $this->integration->getAuthenticationType());
|
||||
}
|
||||
|
||||
public function testGetAuthenticationTypeWithOauthToken(): void
|
||||
{
|
||||
$event = $this->createMock(PluginIntegrationKeyEvent::class);
|
||||
$event->expects(self::once())
|
||||
->method('getKeys')
|
||||
->willReturn(['other' => 'data', HubspotIntegration::ACCESS_KEY => 'token']);
|
||||
$this->dispatcher->expects(self::once())
|
||||
->method('dispatch')
|
||||
->with(
|
||||
new PluginIntegrationKeyEvent($this->integration, [HubspotIntegration::ACCESS_KEY]),
|
||||
PluginEvents::PLUGIN_ON_INTEGRATION_KEYS_ENCRYPT
|
||||
)
|
||||
->willReturn($event);
|
||||
|
||||
$this->integration->encryptAndSetApiKeys([HubspotIntegration::ACCESS_KEY], $this->createMock(Integration::class));
|
||||
self::assertSame('oauth2', $this->integration->getAuthenticationType());
|
||||
}
|
||||
|
||||
public function testIsAuthorizedNoOauthToken(): void
|
||||
{
|
||||
$event = $this->createMock(PluginIntegrationKeyEvent::class);
|
||||
$event->expects(self::once())
|
||||
->method('getKeys')
|
||||
->willReturn(['other' => 'data']);
|
||||
$this->dispatcher->expects(self::once())
|
||||
->method('dispatch')
|
||||
->with(
|
||||
new PluginIntegrationKeyEvent($this->integration, [HubspotIntegration::ACCESS_KEY]),
|
||||
PluginEvents::PLUGIN_ON_INTEGRATION_KEYS_ENCRYPT
|
||||
)
|
||||
->willReturn($event);
|
||||
|
||||
$this->integration->encryptAndSetApiKeys([HubspotIntegration::ACCESS_KEY], $this->createMock(Integration::class));
|
||||
self::assertFalse($this->integration->isAuthorized());
|
||||
}
|
||||
|
||||
public function testIsAuthorizedWithOauthToken(): void
|
||||
{
|
||||
$event = $this->createMock(PluginIntegrationKeyEvent::class);
|
||||
$event->expects(self::once())
|
||||
->method('getKeys')
|
||||
->willReturn(['other' => 'data', HubspotIntegration::ACCESS_KEY => 'token']);
|
||||
$this->dispatcher->expects(self::once())
|
||||
->method('dispatch')
|
||||
->with(
|
||||
new PluginIntegrationKeyEvent($this->integration, [HubspotIntegration::ACCESS_KEY]),
|
||||
PluginEvents::PLUGIN_ON_INTEGRATION_KEYS_ENCRYPT
|
||||
)
|
||||
->willReturn($event);
|
||||
|
||||
$this->integration->encryptAndSetApiKeys([HubspotIntegration::ACCESS_KEY], $this->createMock(Integration::class));
|
||||
self::assertTrue($this->integration->isAuthorized());
|
||||
}
|
||||
|
||||
public function testAppendToFormKeys(): void
|
||||
{
|
||||
$builder = $this->createMock(FormBuilderInterface::class);
|
||||
$matcher = self::exactly(2);
|
||||
$builder->expects($matcher)
|
||||
->method('add')->willReturnCallback(function (...$parameters) use ($matcher) {
|
||||
if (1 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame(HubspotIntegration::ACCESS_KEY, $parameters[0]);
|
||||
$this->assertSame(TextType::class, $parameters[1]);
|
||||
}
|
||||
if (2 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame($this->integration->getApiKey(), $parameters[0]);
|
||||
$this->assertSame(TextType::class, $parameters[1]);
|
||||
}
|
||||
})->willReturnSelf();
|
||||
|
||||
$this->integration->appendToForm($builder, [], 'keys');
|
||||
}
|
||||
|
||||
public function testAppendToFormFeatures(): void
|
||||
{
|
||||
$builder = $this->createMock(FormBuilderInterface::class);
|
||||
$builder->expects(self::once())
|
||||
->method('add')
|
||||
->with('objects', ChoiceType::class);
|
||||
|
||||
$this->integration->appendToForm($builder, [], 'features');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Integration\Salesforce\CampaignMember;
|
||||
|
||||
use Mautic\PluginBundle\Entity\IntegrationEntityRepository;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\Salesforce\CampaignMember\Fetcher;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\Salesforce\CampaignMember\Organizer;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\Salesforce\Object\CampaignMember;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\Salesforce\Object\Contact;
|
||||
use MauticPlugin\MauticCrmBundle\Integration\Salesforce\Object\Lead;
|
||||
|
||||
class FetcherTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testEntitiesAreFetchedFromOrganizerResults(): void
|
||||
{
|
||||
$organizer = $this->getOrgnanizer();
|
||||
$repo = $this->createMock(IntegrationEntityRepository::class);
|
||||
$matcher = $this->exactly(2);
|
||||
|
||||
$repo->expects($matcher)
|
||||
->method('getIntegrationsEntityId')->willReturnCallback(function (...$parameters) use ($matcher, $organizer) {
|
||||
if (1 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame('Salesforce', $parameters[0]);
|
||||
$this->assertSame(Lead::OBJECT, $parameters[1]);
|
||||
$this->assertSame('lead', $parameters[2]);
|
||||
$this->assertNull($parameters[3]);
|
||||
$this->assertNull($parameters[4]);
|
||||
$this->assertNull($parameters[5]);
|
||||
$this->assertFalse($parameters[6]);
|
||||
$this->assertSame(0, $parameters[7]);
|
||||
$this->assertSame(0, $parameters[8]);
|
||||
$this->assertSame($organizer->getLeadIds(), $parameters[9]);
|
||||
}
|
||||
if (2 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame('Salesforce', $parameters[0]);
|
||||
$this->assertSame(Contact::OBJECT, $parameters[1]);
|
||||
$this->assertSame('lead', $parameters[2]);
|
||||
$this->assertNull($parameters[3]);
|
||||
$this->assertNull($parameters[4]);
|
||||
$this->assertNull($parameters[5]);
|
||||
$this->assertFalse($parameters[6]);
|
||||
$this->assertSame(0, $parameters[7]);
|
||||
$this->assertSame(0, $parameters[8]);
|
||||
$this->assertSame($organizer->getContactIds(), $parameters[9]);
|
||||
}
|
||||
|
||||
return [];
|
||||
});
|
||||
|
||||
new Fetcher($repo, $organizer, '701f10000021UnkAAE');
|
||||
}
|
||||
|
||||
public function testThatCampaignMembersAreFetched(): void
|
||||
{
|
||||
$organizer = $this->getOrgnanizer();
|
||||
$repo = $this->createMock(IntegrationEntityRepository::class);
|
||||
$matcher = $this->exactly(4);
|
||||
|
||||
$repo->expects($matcher)
|
||||
->method('getIntegrationsEntityId')->willReturnCallback(function (...$parameters) use ($matcher, $organizer) {
|
||||
if (1 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame('Salesforce', $parameters[0]);
|
||||
$this->assertSame(Lead::OBJECT, $parameters[1]);
|
||||
$this->assertSame('lead', $parameters[2]);
|
||||
$this->assertNull($parameters[3]);
|
||||
$this->assertNull($parameters[4]);
|
||||
$this->assertNull($parameters[5]);
|
||||
$this->assertFalse($parameters[6]);
|
||||
$this->assertSame(0, $parameters[7]);
|
||||
$this->assertSame(0, $parameters[8]);
|
||||
$this->assertSame($organizer->getLeadIds(), $parameters[9]);
|
||||
|
||||
return [
|
||||
[
|
||||
'integration_entity_id' => '00Qf100000YjYvEEAV',
|
||||
'internal_entity_id' => 1,
|
||||
],
|
||||
[
|
||||
'integration_entity_id' => '00Qf100000YjYvJEAV',
|
||||
'internal_entity_id' => 2,
|
||||
],
|
||||
[
|
||||
'integration_entity_id' => '00Qf100000YjYvOEAV',
|
||||
'internal_entity_id' => 3,
|
||||
],
|
||||
];
|
||||
}
|
||||
if (2 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame('Salesforce', $parameters[0]);
|
||||
$this->assertSame(Contact::OBJECT, $parameters[1]);
|
||||
$this->assertSame('lead', $parameters[2]);
|
||||
$this->assertNull($parameters[3]);
|
||||
$this->assertNull($parameters[4]);
|
||||
$this->assertNull($parameters[5]);
|
||||
$this->assertFalse($parameters[6]);
|
||||
$this->assertSame(0, $parameters[7]);
|
||||
$this->assertSame(0, $parameters[8]);
|
||||
$this->assertSame($organizer->getContactIds(), $parameters[9]);
|
||||
|
||||
return [
|
||||
[
|
||||
'integration_entity_id' => '00Qf100000YjYvYEAV',
|
||||
'internal_entity_id' => 4,
|
||||
],
|
||||
[
|
||||
'integration_entity_id' => '00Qf100000YjYvdEAF',
|
||||
'internal_entity_id' => 5,
|
||||
],
|
||||
[
|
||||
'integration_entity_id' => '00Qf100000YjYviEAF',
|
||||
'internal_entity_id' => 6,
|
||||
],
|
||||
];
|
||||
}
|
||||
if (3 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame('Salesforce', $parameters[0]);
|
||||
$this->assertSame(CampaignMember::OBJECT, $parameters[1]);
|
||||
$this->assertSame('lead', $parameters[2]);
|
||||
$this->assertSame([1, 2, 3, 4, 5, 6], $parameters[3]);
|
||||
$this->assertNull($parameters[4]);
|
||||
$this->assertNull($parameters[5]);
|
||||
$this->assertFalse($parameters[6]);
|
||||
$this->assertSame(0, $parameters[7]);
|
||||
$this->assertSame(0, $parameters[8]);
|
||||
$this->assertSame('701f10000021UnkAAE', $parameters[9]);
|
||||
|
||||
return [
|
||||
[
|
||||
'integration_entity' => CampaignMember::OBJECT,
|
||||
'integration_entity_id' => '701f10000021UnkAAE',
|
||||
'internal_entity_id' => 1,
|
||||
],
|
||||
[
|
||||
'integration_entity' => CampaignMember::OBJECT,
|
||||
'integration_entity_id' => '701f10000021UnkAAE',
|
||||
'internal_entity_id' => 4,
|
||||
],
|
||||
];
|
||||
}
|
||||
if (4 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame('Salesforce', $parameters[0]);
|
||||
$this->assertNull($parameters[1]);
|
||||
$this->assertSame('lead', $parameters[2]);
|
||||
$this->assertNull($parameters[3]);
|
||||
$this->assertNull($parameters[4]);
|
||||
$this->assertNull($parameters[5]);
|
||||
$this->assertFalse($parameters[6]);
|
||||
$this->assertSame(0, $parameters[7]);
|
||||
$this->assertSame(0, $parameters[8]);
|
||||
$this->assertSame(['00Qf100000YjYv4EAF', '00Qf100000YjYv9EAF', '00Qf100000YjYvTEAV', '00Qf100000X1NR5EAN'], $parameters[9]);
|
||||
|
||||
return [
|
||||
[
|
||||
'integration_entity_id' => '00Qf100000YjYv4EAF',
|
||||
'internal_entity_id' => 7,
|
||||
],
|
||||
[
|
||||
'integration_entity_id' => '00Qf100000YjYv9EAF',
|
||||
'internal_entity_id' => 8,
|
||||
],
|
||||
[
|
||||
'integration_entity_id' => '00Qf100000YjYvTEAV',
|
||||
'internal_entity_id' => 9,
|
||||
],
|
||||
[
|
||||
'integration_entity_id' => '00Qf100000X1NR5EAN',
|
||||
'internal_entity_id' => 10,
|
||||
],
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
$fetcher = new Fetcher($repo, $organizer, '701f10000021UnkAAE');
|
||||
|
||||
// The query to fetch unknown members should be the 2 Leads not returned by at(0)
|
||||
$this->assertEquals(
|
||||
"SELECT Test, Id from Lead where Id in ('00Qf100000YjYv4EAF','00Qf100000YjYv9EAF') and ConvertedContactId = NULL",
|
||||
$fetcher->getQueryForUnknownObjects(['Test'], Lead::OBJECT)
|
||||
);
|
||||
|
||||
// The query to fetch unknown members should be the 2 Contacts not returned by at(1)
|
||||
$this->assertEquals(
|
||||
"SELECT Test, Id from Contact where Id in ('00Qf100000YjYvTEAV','00Qf100000X1NR5EAN')",
|
||||
$fetcher->getQueryForUnknownObjects(['Test'], Contact::OBJECT)
|
||||
);
|
||||
|
||||
// Should include all but the two we are already tracking as campaign members
|
||||
$unknown = $fetcher->getUnknownCampaignMembers();
|
||||
|
||||
$this->assertEquals(
|
||||
[2, 3, 5, 6, 7, 8, 9, 10],
|
||||
$unknown
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Organizer
|
||||
*/
|
||||
private function getOrgnanizer()
|
||||
{
|
||||
$records = [
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQe2AAG',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => null,
|
||||
'LeadId' => '00Qf100000YjYv4EAF',
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQe7AAG',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => null,
|
||||
'LeadId' => '00Qf100000YjYv9EAF',
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQeCAAW',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => null,
|
||||
'LeadId' => '00Qf100000YjYvEEAV',
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQeHAAW',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => null,
|
||||
'LeadId' => '00Qf100000YjYvJEAV',
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQeMAAW',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => null,
|
||||
'LeadId' => '00Qf100000YjYvOEAV',
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQeRAAW',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => '00Qf100000YjYvTEAV',
|
||||
'LeadId' => null,
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQeWAAW',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => '00Qf100000X1NR5EAN',
|
||||
'LeadId' => null,
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQebAAG',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => '00Qf100000YjYvYEAV',
|
||||
'LeadId' => null,
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQegAAG',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => '00Qf100000YjYvdEAF',
|
||||
'LeadId' => null,
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQelAAG',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => '00Qf100000YjYviEAF',
|
||||
'LeadId' => null,
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
];
|
||||
|
||||
return new Organizer($records);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Integration\Salesforce\CampaignMember;
|
||||
|
||||
use MauticPlugin\MauticCrmBundle\Integration\Salesforce\CampaignMember\Organizer;
|
||||
|
||||
class OrganizerTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testRecordsAreOrganizedIntoLeadsAndContacts(): void
|
||||
{
|
||||
$records = [
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQe2AAG',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => null,
|
||||
'LeadId' => '00Qf100000YjYv4EAF',
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQe7AAG',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => null,
|
||||
'LeadId' => '00Qf100000YjYv9EAF',
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQeCAAW',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => null,
|
||||
'LeadId' => '00Qf100000YjYvEEAV',
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQeHAAW',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => null,
|
||||
'LeadId' => '00Qf100000YjYvJEAV',
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQeMAAW',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => null,
|
||||
'LeadId' => '00Qf100000YjYvOEAV',
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQeRAAW',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => '00Qf100000YjYvTEAV',
|
||||
'LeadId' => null,
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQeWAAW',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => '00Qf100000X1NR5EAN',
|
||||
'LeadId' => null,
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQebAAG',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => '00Qf100000YjYvYEAV',
|
||||
'LeadId' => null,
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQegAAG',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => '00Qf100000YjYvdEAF',
|
||||
'LeadId' => null,
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
[
|
||||
'attributes' => [
|
||||
'type' => 'CampaignMember',
|
||||
'url' => '/services/data/v34.0/sobjects/CampaignMember/00vf100000gFQelAAG',
|
||||
],
|
||||
'CampaignId' => '701f10000021UnkAAE',
|
||||
'ContactId' => '00Qf100000YjYviEAF',
|
||||
'LeadId' => null,
|
||||
'IsDeleted' => false,
|
||||
],
|
||||
];
|
||||
|
||||
$organizer = new Organizer($records);
|
||||
|
||||
$leads = ['00Qf100000YjYv4EAF', '00Qf100000YjYv9EAF', '00Qf100000YjYvEEAV', '00Qf100000YjYvJEAV', '00Qf100000YjYvOEAV'];
|
||||
$this->assertEquals($leads, $organizer->getLeadIds());
|
||||
|
||||
$organizedLeads = $organizer->getLeads();
|
||||
foreach ($leads as $id) {
|
||||
$this->assertArrayHasKey($id, $organizedLeads);
|
||||
$this->assertEquals($id, $organizedLeads[$id]->getId());
|
||||
}
|
||||
|
||||
$contacts = ['00Qf100000YjYvTEAV', '00Qf100000X1NR5EAN', '00Qf100000YjYvYEAV', '00Qf100000YjYvdEAF', '00Qf100000YjYviEAF'];
|
||||
$this->assertEquals($contacts, $organizer->getContactIds());
|
||||
|
||||
$organizedContacts = $organizer->getContacts();
|
||||
foreach ($contacts as $id) {
|
||||
$this->assertArrayHasKey($id, $organizedContacts);
|
||||
$this->assertEquals($id, $organizedContacts[$id]->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Integration\Salesforce\Helper;
|
||||
|
||||
use MauticPlugin\MauticCrmBundle\Integration\Salesforce\Helper\StateValidationHelper;
|
||||
|
||||
class StateValidationHelperTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testStateIsRemovedWhenCountryIsUnknown(): void
|
||||
{
|
||||
$payload = [
|
||||
'State' => 'Paris',
|
||||
];
|
||||
|
||||
$this->assertEquals([], StateValidationHelper::validate($payload));
|
||||
}
|
||||
|
||||
public function testStateIsRemovedWhenCountryIsNotSupported(): void
|
||||
{
|
||||
$payload = [
|
||||
'Country' => 'France',
|
||||
'State' => 'Paris',
|
||||
];
|
||||
|
||||
$this->assertEquals(['Country' => 'France'], StateValidationHelper::validate($payload));
|
||||
}
|
||||
|
||||
public function testStateIsLeftWhenCountryIsSupported(): void
|
||||
{
|
||||
$payload = [
|
||||
'Country' => 'United States',
|
||||
'State' => 'Texas',
|
||||
];
|
||||
|
||||
$this->assertEquals($payload, StateValidationHelper::validate($payload));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticCrmBundle\Tests\Stubs;
|
||||
|
||||
use MauticPlugin\MauticCrmBundle\Integration\CrmAbstractIntegration;
|
||||
|
||||
class StubIntegration extends CrmAbstractIntegration
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'Stub';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user