Issues (3627)

Tests/Unit/EventListener/LeadSubscriberTest.php (2 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * @copyright   2019 Mautic, Inc. All rights reserved
7
 * @author      Mautic, Inc.
8
 *
9
 * @link        https://mautic.com
10
 *
11
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
12
 */
13
14
namespace Mautic\IntegrationsBundle\Tests\Unit\EventListener;
15
16
use Mautic\IntegrationsBundle\Entity\FieldChangeRepository;
17
use Mautic\IntegrationsBundle\Entity\ObjectMappingRepository;
18
use Mautic\IntegrationsBundle\EventListener\LeadSubscriber;
19
use Mautic\IntegrationsBundle\Helper\SyncIntegrationsHelper;
20
use Mautic\IntegrationsBundle\Sync\DAO\Value\EncodedValueDAO;
21
use Mautic\IntegrationsBundle\Sync\SyncDataExchange\Internal\Object\Contact;
22
use Mautic\IntegrationsBundle\Sync\SyncDataExchange\MauticSyncDataExchange;
23
use Mautic\IntegrationsBundle\Sync\VariableExpresser\VariableExpresserHelperInterface;
24
use Mautic\LeadBundle\Entity\Company;
25
use Mautic\LeadBundle\Entity\Lead;
26
use Mautic\LeadBundle\Event\CompanyEvent;
27
use Mautic\LeadBundle\Event\LeadEvent;
28
use Mautic\LeadBundle\LeadEvents;
29
use PHPUnit\Framework\MockObject\MockObject;
30
use PHPUnit\Framework\TestCase;
31
32
class LeadSubscriberTest extends TestCase
33
{
34
    /**
35
     * @var MockObject|FieldChangeRepository
36
     */
37
    private $fieldChangeRepository;
38
39
    /**
40
     * @var MockObject|ObjectMappingRepository
41
     */
42
    private $objectMappingRepository;
43
44
    /**
45
     * @var MockObject|VariableExpresserHelperInterface
46
     */
47
    private $variableExpresserHelper;
48
49
    /**
50
     * @var MockObject|SyncIntegrationsHelper
51
     */
52
    private $syncIntegrationsHelper;
53
54
    /**
55
     * @var MockObject|LeadEvent
56
     */
57
    private $leadEvent;
58
59
    /**
60
     * @var MockObject|CompanyEvent
61
     */
62
    private $companyEvent;
63
64
    /**
65
     * @var LeadSubscriber
66
     */
67
    private $subscriber;
68
69
    public function setUp(): void
70
    {
71
        parent::setUp();
72
73
        $this->fieldChangeRepository   = $this->createMock(FieldChangeRepository::class);
74
        $this->objectMappingRepository = $this->createMock(ObjectMappingRepository::class);
75
        $this->variableExpresserHelper = $this->createMock(VariableExpresserHelperInterface::class);
76
        $this->syncIntegrationsHelper  = $this->createMock(SyncIntegrationsHelper::class);
77
        $this->leadEvent               = $this->createMock(LeadEvent::class);
78
        $this->companyEvent            = $this->createMock(CompanyEvent::class);
79
        $this->subscriber              = new LeadSubscriber(
80
            $this->fieldChangeRepository,
81
            $this->objectMappingRepository,
82
            $this->variableExpresserHelper,
83
            $this->syncIntegrationsHelper
84
        );
85
    }
86
87
    public function testGetSubscribedEvents(): void
88
    {
89
        $this->assertEquals(
90
            [
91
                LeadEvents::LEAD_POST_SAVE      => ['onLeadPostSave', 0],
92
                LeadEvents::LEAD_POST_DELETE    => ['onLeadPostDelete', 255],
93
                LeadEvents::COMPANY_POST_SAVE   => ['onCompanyPostSave', 0],
94
                LeadEvents::COMPANY_POST_DELETE => ['onCompanyPostDelete', 255],
95
                LeadEvents::LEAD_COMPANY_CHANGE => ['onLeadCompanyChange', 128],
96
            ],
97
            LeadSubscriber::getSubscribedEvents()
98
        );
99
    }
100
101
    public function testOnLeadPostSaveAnonymousLead(): void
102
    {
103
        $lead = $this->createMock(Lead::class);
104
        $lead->expects($this->at(0))
105
            ->method('isAnonymous')
106
            ->willReturn(true);
107
        $lead->expects($this->never())
108
            ->method('getChanges');
109
110
        $this->leadEvent->expects($this->once())
111
            ->method('getLead')
112
            ->willReturn($lead);
113
114
        $this->syncIntegrationsHelper->expects($this->never())
115
            ->method('hasObjectSyncEnabled');
116
117
        $this->subscriber->onLeadPostSave($this->leadEvent);
118
    }
119
120
    public function testOnLeadPostSaveLeadObjectSyncNotEnabled(): void
121
    {
122
        $lead = $this->createMock(Lead::class);
123
        $lead->expects($this->at(0))
124
            ->method('isAnonymous')
125
            ->willReturn(false);
126
        $lead->expects($this->never())
127
            ->method('getChanges');
128
129
        $this->leadEvent->expects($this->once())
130
            ->method('getLead')
131
            ->willReturn($lead);
132
133
        $this->syncIntegrationsHelper->expects($this->once())
134
            ->method('hasObjectSyncEnabled')
135
            ->with(Contact::NAME)
136
            ->willReturn(false);
137
138
        $this->subscriber->onLeadPostSave($this->leadEvent);
139
    }
140
141
    public function testOnLeadCompanyChange(): void
142
    {
143
        $leadId      = 3;
144
        $companyName = 'Dell';
145
146
        $lead = $this->createMock(Lead::class);
147
        $lead->expects($this->at(0))
148
            ->method('getCompany')
149
            ->willReturn($companyName);
150
        $lead->expects($this->at(0))
151
            ->method('getId')
152
            ->willReturn($leadId);
153
154
        $this->leadEvent->expects($this->once())
155
            ->method('getLead')
156
            ->willReturn($lead);
157
158
        $this->subscriber->onLeadPostSave($this->leadEvent);
159
    }
160
161
    public function testOnLeadPostSaveNoAction(): void
162
    {
163
        $fieldChanges = [];
164
165
        $lead = $this->createMock(Lead::class);
166
        $lead->expects($this->at(0))
167
            ->method('isAnonymous')
168
            ->willReturn(false);
169
        $lead->expects($this->once())
170
            ->method('getChanges')
171
            ->willReturn($fieldChanges);
172
173
        $this->leadEvent->expects($this->once())
174
            ->method('getLead')
175
            ->willReturn($lead);
176
177
        $this->syncIntegrationsHelper->expects($this->once())
178
            ->method('hasObjectSyncEnabled')
179
            ->with(Contact::NAME)
180
            ->willReturn(true);
181
182
        $this->subscriber->onLeadPostSave($this->leadEvent);
183
    }
184
185
    public function testOnLeadPostSaveRecordChanges(): void
186
    {
187
        $fieldName    = 'fieldName';
188
        $oldValue     = 'oldValue';
189
        $newValue     = 'newValue';
190
        $fieldChanges = [
191
            'fields' => [
192
                $fieldName => [
193
                    $oldValue,
194
                    $newValue,
195
                ],
196
            ],
197
        ];
198
        $objectId   = 1;
199
        $objectType = Lead::class;
200
201
        $lead = $this->createMock(Lead::class);
202
        $lead->expects($this->at(0))
203
            ->method('isAnonymous')
204
            ->willReturn(false);
205
        $lead->expects($this->once())
206
            ->method('getChanges')
207
            ->willReturn($fieldChanges);
208
        $lead->expects($this->once())
209
            ->method('getId')
210
            ->willReturn($objectId);
211
212
        $this->leadEvent->expects($this->once())
213
            ->method('getLead')
214
            ->willReturn($lead);
215
216
        $this->syncIntegrationsHelper->expects($this->once())
217
            ->method('hasObjectSyncEnabled')
218
            ->with(Contact::NAME)
219
            ->willReturn(true);
220
221
        $this->handleRecordFieldChanges($fieldChanges['fields'], $objectId, $objectType);
222
223
        $this->subscriber->onLeadPostSave($this->leadEvent);
224
    }
225
226
    public function testOnLeadPostSaveRecordChangesWithOwnerChange(): void
227
    {
228
        $newOwnerId   = 5;
229
        $fieldChanges = [
230
            'owner' => [
231
                2,
232
                $newOwnerId,
233
            ],
234
        ];
235
        $objectId   = 1;
236
        $objectType = Lead::class;
237
238
        $lead = $this->createMock(Lead::class);
239
        $lead->expects($this->at(0))
240
            ->method('isAnonymous')
241
            ->willReturn(false);
242
        $lead->expects($this->once())
243
            ->method('getChanges')
244
            ->willReturn($fieldChanges);
245
        $lead->expects($this->once())
246
            ->method('getId')
247
            ->willReturn($objectId);
248
249
        $this->leadEvent->expects($this->once())
250
            ->method('getLead')
251
            ->willReturn($lead);
252
253
        $this->syncIntegrationsHelper->expects($this->once())
254
            ->method('hasObjectSyncEnabled')
255
            ->with(Contact::NAME)
256
            ->willReturn(true);
257
258
        $fieldChanges['fields']['owner_id'] = $fieldChanges['owner'];
259
260
        $this->handleRecordFieldChanges($fieldChanges['fields'], $objectId, $objectType);
261
262
        $this->subscriber->onLeadPostSave($this->leadEvent);
263
    }
264
265
    public function testOnLeadPostSaveRecordChangesWithPointChange(): void
266
    {
267
        $newPointCount   = 5;
268
        $fieldChanges    = [
269
            'points' => [
270
                2,
271
                $newPointCount,
272
            ],
273
        ];
274
        $objectId   = 1;
275
        $objectType = Lead::class;
276
277
        $lead = $this->createMock(Lead::class);
278
        $lead->expects($this->at(0))
279
            ->method('isAnonymous')
280
            ->willReturn(false);
281
        $lead->expects($this->once())
282
            ->method('getChanges')
283
            ->willReturn($fieldChanges);
284
        $lead->expects($this->once())
285
            ->method('getId')
286
            ->willReturn($objectId);
287
288
        $this->leadEvent->expects($this->once())
289
            ->method('getLead')
290
            ->willReturn($lead);
291
292
        $this->syncIntegrationsHelper->expects($this->once())
293
            ->method('hasObjectSyncEnabled')
294
            ->with(Contact::NAME)
295
            ->willReturn(true);
296
297
        $fieldChanges['fields']['points'] = $fieldChanges['points'];
298
299
        $this->handleRecordFieldChanges($fieldChanges['fields'], $objectId, $objectType);
300
301
        $this->subscriber->onLeadPostSave($this->leadEvent);
302
    }
303
304
    public function testOnLeadPostDelete(): void
305
    {
306
        $deletedId       = '5';
307
        $lead            = new Lead();
308
        $lead->deletedId = $deletedId;
0 ignored issues
show
Documentation Bug introduced by
It seems like $deletedId of type string is incompatible with the declared type integer|null of property $deletedId.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
309
310
        $this->leadEvent->expects($this->exactly(2))
311
            ->method('getLead')
312
            ->willReturn($lead);
313
314
        $this->fieldChangeRepository->expects($this->once())
315
            ->method('deleteEntitiesForObject')
316
            ->with((int) $deletedId, MauticSyncDataExchange::OBJECT_CONTACT);
317
318
        $this->objectMappingRepository->expects($this->once())
319
            ->method('deleteEntitiesForObject')
320
            ->with((int) $deletedId, MauticSyncDataExchange::OBJECT_CONTACT);
321
322
        $this->subscriber->onLeadPostDelete($this->leadEvent);
323
    }
324
325
    public function testOnCompanyPostSaveSyncNotEnabled(): void
326
    {
327
        $this->syncIntegrationsHelper->expects($this->once())
328
            ->method('hasObjectSyncEnabled')
329
            ->with(MauticSyncDataExchange::OBJECT_COMPANY)
330
            ->willReturn(false);
331
332
        $this->companyEvent->expects($this->never())
333
            ->method('getCompany');
334
335
        $this->subscriber->onCompanyPostSave($this->companyEvent);
336
    }
337
338
    public function testOnCompanyPostSaveSyncNoAction(): void
339
    {
340
        $fieldChanges = [];
341
342
        $company = $this->createMock(Company::class);
343
        $company->expects($this->once())
344
            ->method('getChanges')
345
            ->willReturn($fieldChanges);
346
347
        $this->companyEvent->expects($this->once())
348
            ->method('getCompany')
349
            ->willReturn($company);
350
351
        $this->syncIntegrationsHelper->expects($this->once())
352
            ->method('hasObjectSyncEnabled')
353
            ->with(MauticSyncDataExchange::OBJECT_COMPANY)
354
            ->willReturn(true);
355
356
        $this->subscriber->onCompanyPostSave($this->companyEvent);
357
    }
358
359
    public function testOnCompanyPostSaveSyncRecordChanges(): void
360
    {
361
        $fieldName    = 'fieldName';
362
        $oldValue     = 'oldValue';
363
        $newValue     = 'newValue';
364
        $fieldChanges = [
365
            'fields' => [
366
                $fieldName => [
367
                    $oldValue,
368
                    $newValue,
369
                ],
370
            ],
371
        ];
372
        $objectId   = 1;
373
        $objectType = Company::class;
374
375
        $company = $this->createMock(Company::class);
376
        $company->expects($this->once())
377
            ->method('getChanges')
378
            ->willReturn($fieldChanges);
379
        $company->expects($this->once())
380
            ->method('getChanges')
381
            ->willReturn($fieldChanges);
382
        $company->expects($this->once())
383
            ->method('getId')
384
            ->willReturn($objectId);
385
386
        $this->companyEvent->expects($this->once())
387
            ->method('getCompany')
388
            ->willReturn($company);
389
390
        $this->syncIntegrationsHelper->expects($this->once())
391
            ->method('hasObjectSyncEnabled')
392
            ->with(MauticSyncDataExchange::OBJECT_COMPANY)
393
            ->willReturn(true);
394
395
        $this->handleRecordFieldChanges($fieldChanges['fields'], $objectId, $objectType);
396
397
        $this->subscriber->onCompanyPostSave($this->companyEvent);
398
    }
399
400
    public function testOnCompanyPostSaveRecordChangesWithOwnerChange(): void
401
    {
402
        $newOwnerId   = 5;
403
        $fieldChanges = [
404
            'owner' => [
405
                2,
406
                $newOwnerId,
407
            ],
408
        ];
409
        $objectId   = 1;
410
        $objectType = Company::class;
411
412
        $company = $this->createMock(Company::class);
413
        $company->expects($this->once())
414
            ->method('getChanges')
415
            ->willReturn($fieldChanges);
416
        $company->expects($this->once())
417
            ->method('getId')
418
            ->willReturn($objectId);
419
420
        $this->companyEvent->expects($this->once())
421
            ->method('getCompany')
422
            ->willReturn($company);
423
424
        $this->syncIntegrationsHelper->expects($this->once())
425
            ->method('hasObjectSyncEnabled')
426
            ->with(MauticSyncDataExchange::OBJECT_COMPANY)
427
            ->willReturn(true);
428
429
        $fieldChanges['fields']['owner_id'] = $fieldChanges['owner'];
430
431
        $this->handleRecordFieldChanges($fieldChanges['fields'], $objectId, $objectType);
432
433
        $this->subscriber->onCompanyPostSave($this->companyEvent);
434
    }
435
436
    public function testOnCompanyPostDelete(): void
437
    {
438
        $deletedId       = '5';
439
        $lead            = new Company();
440
        $lead->deletedId = $deletedId;
0 ignored issues
show
Documentation Bug introduced by
It seems like $deletedId of type string is incompatible with the declared type integer|null of property $deletedId.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
441
442
        $this->companyEvent->expects($this->exactly(2))
443
            ->method('getCompany')
444
            ->willReturn($lead);
445
446
        $this->fieldChangeRepository->expects($this->once())
447
            ->method('deleteEntitiesForObject')
448
            ->with((int) $deletedId, MauticSyncDataExchange::OBJECT_COMPANY);
449
450
        $this->objectMappingRepository->expects($this->once())
451
            ->method('deleteEntitiesForObject')
452
            ->with((int) $deletedId, MauticSyncDataExchange::OBJECT_COMPANY);
453
454
        $this->subscriber->onCompanyPostDelete($this->companyEvent);
455
    }
456
457
    private function handleRecordFieldChanges(array $fieldChanges, int $objectId, string $objectType): void
458
    {
459
        $integrationName     = 'testIntegration';
460
        $enabledIntegrations = [$integrationName];
461
462
        $this->syncIntegrationsHelper->expects($this->any())
463
            ->method('getEnabledIntegrations')
464
            ->willReturn($enabledIntegrations);
465
466
        $fieldNames = [];
467
        $i          = 0;
468
        foreach ($fieldChanges as $fieldName => [$oldValue, $newValue]) {
469
            $valueDao = new EncodedValueDAO($objectType, (string) $newValue);
470
471
            $this->variableExpresserHelper->expects($this->at($i))
472
                ->method('encodeVariable')
473
                ->with($newValue)
474
                ->willReturn($valueDao);
475
476
            $fieldNames[] = $fieldName;
477
        }
478
479
        $this->fieldChangeRepository->expects($this->once())
480
            ->method('deleteEntitiesForObjectByColumnName')
481
            ->with($objectId, $objectType, $fieldNames);
482
483
        $this->fieldChangeRepository->expects($this->once())
484
            ->method('saveEntities');
485
486
        $this->fieldChangeRepository->expects($this->once())
487
            ->method('clear');
488
    }
489
}
490