marketo_ma-8.x-2.x-dev/tests/src/Unit/Service/MarketoMaApiClientTest.php
tests/src/Unit/Service/MarketoMaApiClientTest.php
<?php
namespace Drupal\Tests\marketo_ma\Unit\Service;
use Drupal\marketo_ma\Lead;
use Drupal\marketo_ma\Service\MarketoMaApiClient;
use Drupal\Tests\UnitTestCase;
use NecLimDul\MarketoRest\Hacks\API\ActivitiesApi;
use NecLimDul\MarketoRest\Hacks\Model\FormResponse;
use NecLimDul\MarketoRest\Hacks\Model\ResponseOfActivity;
use NecLimDul\MarketoRest\Hacks\Model\ResponseOfSubmitForm;
use NecLimDul\MarketoRest\Lead\Api\LeadsApi;
use NecLimDul\MarketoRest\Lead\Model\ActivityType;
use NecLimDul\MarketoRest\Lead\Model\ActivityTypeAttribute;
use NecLimDul\MarketoRest\Lead\Model\Form;
use NecLimDul\MarketoRest\Lead\Model\Lead as ApiLead;
use NecLimDul\MarketoRest\Lead\Model\Lead as MarketoLead;
use NecLimDul\MarketoRest\Lead\Model\LeadAttribute;
use NecLimDul\MarketoRest\Lead\Model\LeadFormFields;
use NecLimDul\MarketoRest\Lead\Model\LeadMapAttribute;
use NecLimDul\MarketoRest\Lead\Model\PushLeadToMarketoRequest;
use NecLimDul\MarketoRest\Lead\Model\ResponseOfActivityType;
use NecLimDul\MarketoRest\Lead\Model\ResponseOfLead;
use NecLimDul\MarketoRest\Lead\Model\ResponseOfLeadAttribute;
use NecLimDul\MarketoRest\Lead\Model\ResponseOfPushLeadToMarketo;
use NecLimDul\MarketoRest\Lead\Model\ResponseOfVoid;
use NecLimDul\MarketoRest\Lead\Model\SubmitFormRequest;
use NecLimDul\MarketoRest\Lead\Model\VisitorData;
use Prophecy\Argument;
use Psr\Log\LoggerInterface;
/**
* Test default Marketo REST client.
*
* @group marketo_ma
* @coversDefaultClass \Drupal\marketo_ma\Service\MarketoMaApiClient
*/
class MarketoMaApiClientTest extends UnitTestCase {
/**
* The Marketo Leads service prophecy.
*
* @var \NecLimDul\MarketoRest\Lead\Api\LeadsApi|\Prophecy\Prophecy\ObjectProphecy
*/
protected $leadsApi;
/**
* The Marketo Activity service prophecy.
*
* @var \NecLimDul\MarketoRest\Lead\Api\ActivitiesApi|\Prophecy\Prophecy\ObjectProphecy
*/
protected $activitiesApi;
/**
* {@inheritDoc}
*/
public function setUp(): void {
parent::setUp();
// Get the API client service.
$this->leadsApi = $this->prophesize(LeadsApi::class);
$this->activitiesApi = $this->prophesize(ActivitiesApi::class);
}
/**
* @covers ::canConnect
* @dataProvider provideConnect
*/
public function testApiClientCanConnect($config, $expect) {
$this->assertEquals($expect, $this->getClient()->canConnect());
}
/**
* @covers ::getFields
*/
public function testGetFields() {
$rest_only = [
'dataType' => 'string',
'displayName' => 'rest_only',
'length' => NULL,
'rest' => ['name' => 'foo'],
'soap' => ['name' => NULL],
];
$soap_only = [
'dataType' => 'string',
'displayName' => 'soap_only',
'length' => NULL,
'rest' => ['name' => NULL],
'soap' => ['name' => 'biz'],
];
$both_fields = [
'dataType' => 'string',
'displayName' => 'both_api_types',
'length' => NULL,
'rest' => ['name' => 'bar'],
'soap' => ['name' => 'baz'],
];
$convert = function (array $data): LeadAttribute {
return new LeadAttribute([
'data_type' => $data['dataType'],
'display_name' => $data['displayName'],
'length' => $data['length'],
'rest' => !empty($data['rest']['name']) ? new LeadMapAttribute(['name' => $data['rest']['name']]) : NULL,
'soap' => !empty($data['soap']['name']) ? new LeadMapAttribute(['name' => $data['soap']['name']]) : NULL,
]);
};
$response = new ResponseOfLeadAttribute([
'success' => TRUE,
'result' => [
$convert($rest_only),
$convert($soap_only),
$convert($both_fields),
],
]);
$this->leadsApi->describeUsingGET2()
->shouldBeCalledOnce()
->willReturn($response);
$fields = $this->getClient()->getFields();
// Assert fields match original fields plus default name. Why?
$this->assertEquals([
'foo' => $rest_only,
'bar' => $both_fields,
], $fields);
}
/**
* @covers ::getActivityTypes
*/
public function testGetActivityTypes() {
$this->activitiesApi->getAllActivityTypesUsingGET()
->shouldBeCalledOnce()
->willReturn(new ResponseOfActivityType([
'success' => TRUE,
'result' => [
new ActivityType([
'id' => 2,
'name' => 'testname',
'description' => 'this is a description',
'primary_attribute' => new ActivityTypeAttribute(['name' => 'primary_attribute']),
]),
],
]));
$activity_types = $this->getClient()->getActivityTypes();
$this->assertCount(1, $activity_types);
$this->assertEquals(2, $activity_types[2]->id());
$this->assertEquals('testname', $activity_types[2]->getName());
$this->assertEquals('this is a description', $activity_types[2]->getDescription());
$this->assertEquals('primary_attribute', $activity_types[2]->getPrimaryAttributeName());
}
/**
* @covers ::getLeadById
*/
public function testGetLeadById() {
$lead_data = $this->getLeadData()[0];
$this->leadsApi->getLeadByIdUsingGET($lead_data['id'])
->shouldBeCalledOnce()
->willReturn($this->getLeadResponse([$lead_data]));
$lead = $this->getClient()->getLeadById($lead_data['id']);
// Assert fields match original fields plus default name. Why?
$this->assertEquals(new Lead($lead_data), $lead);
}
/**
* @covers ::getLeadByEmail
*/
public function testGetLeadByEmail() {
$lead_data = $this->getLeadData()[0];
$this->leadsApi->getLeadsByFilterUsingGET('email', ['test@example.com'])
->shouldBeCalledOnce()
->willReturn($this->getLeadResponse([$lead_data]));
$lead = $this->getClient()->getLeadByEmail('test@example.com');
$this->assertEquals(new Lead($lead_data), $lead);
}
/**
* @covers ::getLeadActivity
*/
public function testGetLeadActivity() {
$token = 'asdf1234';
$activity_ids = [1234, 'asdf'];
$lead = new Lead(['id' => 123]);
$this->activitiesApi->getActivitiesPagingTokenUsingGET(Argument::type(\DateTime::class))
->shouldBeCalled()
->willReturn(new ResponseOfVoid([
'success' => TRUE,
'next_page_token' => $token,
]));
$result = ['not', 'real'];
$this->activitiesApi->getLeadActivitiesUsingGET($token, $activity_ids, NULL, NULL, [$lead->id()])
->shouldBeCalledOnce()
// @todo figure out the original values and write the maps(also leads?)
->willReturn(new ResponseOfActivity([
'success' => TRUE,
'result' => $result,
]));
$activity_types = $this->getClient()->getLeadActivity($lead, $activity_ids);
// Assert fields match original fields plus default name. Why?
$this->assertEquals($result, $activity_types);
// Check that broken null results work.
$lead->set('id', 234);
$this->activitiesApi->getLeadActivitiesUsingGET($token, $activity_ids, NULL, NULL, [$lead->id()])
->shouldBeCalledOnce()
// @todo figure out the original values and write the maps(also leads?)
->willReturn(new ResponseOfActivity([
'success' => TRUE,
]));
$activity_types = $this->getClient()->getLeadActivity($lead, $activity_ids);
$this->assertEquals([], $activity_types);
}
/**
* @covers ::syncLead
*/
public function testSyncLead() {
// 'id' => 543,
$lead_data = ['name' => 'test', 'email' => 'test@example.com'];
$lead = new Lead($lead_data);
$api_lead = new ApiLead(['id' => 15]);
$api_lead->setAdditionalProperties($lead_data);
$test = $this;
$arg = Argument::that(function ($arg) use ($test) {
$test->assertInstanceOf(PushLeadToMarketoRequest::class, $arg);
$input = $arg->getInput();
$test->assertCount(1, $input);
// @todo assert mapLeadToRest.
$test->assertInstanceOf(ApiLead::class, $input[0]);
$test->assertEquals('email', $arg->getLookupField());
return TRUE;
});
$this->leadsApi->pushToMarketoUsingPOST($arg)
->willReturn(new ResponseOfPushLeadToMarketo([
'success' => TRUE,
'result' => [$api_lead],
]))
->shouldBeCalledOnce();
$result = $this->getClient()->syncLead($lead);
$lead->set('id', 15);
$this->assertEquals($lead->get('id'), $result);
}
/**
* @covers ::deleteLead
*/
public function testDeleteLead() {
$leads = [123, 234, 345];
$this->leadsApi->deleteLeadsUsingPOST(NULL, $leads)
->shouldBeCalledOnce()
->willReturn($this->getLeadResponse([[]]));
$response = $this->getClient()->deleteLead($leads);
$this->assertCount(1, $response);
$this->assertInstanceOf(Lead::class, $response[0]);
}
/**
* @covers ::addLeadsToList
* @covers ::getLeadsIds
*/
public function testAddLeadsToList() {
$this->markTestIncomplete('convert');
}
/**
* @covers ::addLeadToListByEmail
*/
public function testAddLeadToListByEmail() {
$this->markTestIncomplete('convert');
}
/**
* @covers ::submitForm
*/
public function testSubmitForm() {
$field_data = ['foo' => 'bar', 'biz' => 'baz'];
$form_fields = new LeadFormFields();
$form_fields->setAdditionalProperties($field_data);
$this->assertEquals($field_data, $form_fields->getAdditionalProperties());
$cookie = 'the_cookie';
$ma_form = new Form([
'lead_form_fields' => $form_fields,
'cookie' => $cookie,
]);
$visitor_data = [
'page_url' => 'https://example.com/page',
'query_string' => 'foo=bar',
'lead_client_ip_address' => '4.4.4.4',
'user_agent_string' => 'test agent',
];
$ma_form->setVisitorData(new VisitorData($visitor_data));
$submit = new SubmitFormRequest([
'form_id' => 123,
'input' => [$ma_form],
]);
$mock_response = new ResponseOfSubmitForm([
'success' => TRUE,
'result' => [
new FormResponse([
'status' => FormResponse::STATUS_CREATED,
'id' => 123,
]),
],
]);
// Assert we set things correctly so our assertions below make sense.
$this->assertSame(123, $submit->getFormId());
$this->assertSame($ma_form['cookie'], $ma_form->getCookie());
$this->assertSame($visitor_data['page_url'], $ma_form->getVisitorData()->getPageUrl());
$this->assertSame($visitor_data['page_url'], $ma_form->getVisitorData()->getPageUrl());
$this->assertSame($visitor_data['query_string'], $ma_form->getVisitorData()->getQueryString());
$this->assertSame($visitor_data['lead_client_ip_address'], $ma_form->getVisitorData()->getLeadClientIpAddress());
$this->assertSame($visitor_data['user_agent_string'], $ma_form->getVisitorData()->getUserAgentString());
$this->leadsApi->submitFormUsingPOST($submit)
->shouldBeCalledOnce()
->willReturn($mock_response);
$this->getClient()->submitForm(
$submit->getFormId(),
$field_data,
$ma_form->getCookie(),
[
'referer' => $ma_form->getVisitorData()->getPageUrl(),
'query' => $ma_form->getVisitorData()->getQueryString(),
'ip_address' => $ma_form->getVisitorData()->getLeadClientIpAddress(),
'user_agent' => $ma_form->getVisitorData()->getUserAgentString(),
]
);
}
/**
* Get a mock API client.
*
* @return \Drupal\marketo_ma\Service\MarketoMaApiClient
* The mocked API client.
*/
private function getClient() {
return new MarketoMaApiClient(
$this->leadsApi->reveal(),
$this->activitiesApi->reveal(),
$this->prophesize(LoggerInterface::class)->reveal()
);
}
/**
* Data provider for connection options.
*
* @return array[]
* Connection datasets
*/
public function provideConnect() {
return [
[
[
'munchkin_id' => 'a',
'client_id' => 'a',
],
TRUE,
],
];
}
/**
* Get an API response for a lead.
*
* @param array $lead_data
* Mocked lead data.
*
* @return \NecLimDul\MarketoRest\Lead\Model\ResponseOfLead
* API response populated with a lead.
*/
protected function getLeadResponse(array $lead_data) {
$leads = [];
foreach ($lead_data as $lead) {
$real_lead = new MarketoLead($lead);
$real_lead->setAdditionalProperties(array_diff_key($lead, MarketoLead::attributeMap()));
$leads[] = $real_lead;
}
return new ResponseOfLead([
'success' => TRUE,
'result' => $leads,
]);
}
/**
* Get mock lead data.
*
* @return array[]
* A list of mocked lead arrays.
*/
protected function getLeadData() {
return [
['id' => 123, 'email' => 'test@example.com'],
];
}
}
