Merge pull request #15330 from mattwire/paymentprocessor_testmodelivemode
[civicrm-core.git] / tests / phpunit / CRM / Dedupe / MergerTest.php
index be93391b97f0683e1e0a50302db492c0b19a0176..37e4f8ba21b69abfa3a544293d4029e16d69b260 100644 (file)
@@ -11,6 +11,15 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
 
   protected $_contactIds = [];
 
+  /**
+   * Contacts created for the test.
+   *
+   * Overlaps contactIds....
+   *
+   * @var array
+   */
+  protected $contacts = [];
+
   /**
    * Tear down.
    *
@@ -21,6 +30,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
       'civicrm_contact',
       'civicrm_group_contact',
       'civicrm_group',
+      'civicrm_prevnext_cache',
     ]);
     parent::tearDown();
   }
@@ -175,7 +185,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
 
     // Retrieve pairs from prev next cache table
     $select = ['pn.is_selected' => 'is_selected'];
-    $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($dao->id, $this->_groupId);
+    $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($dao->id, $this->_groupId, [], TRUE, 0);
     $pnDupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, NULL, NULL, 0, 0, $select);
     $this->assertEquals(count($foundDupes), count($pnDupePairs), 'Check number of dupe pairs in prev next cache.');
 
@@ -245,7 +255,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
 
     // Retrieve pairs from prev next cache table
     $select = ['pn.is_selected' => 'is_selected'];
-    $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($dao->id, $this->_groupId);
+    $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($dao->id, $this->_groupId, [], TRUE, 0);
     $pnDupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, NULL, NULL, 0, 0, $select);
 
     $this->assertEquals(count($foundDupes), count($pnDupePairs), 'Check number of dupe pairs in prev next cache.');
@@ -321,6 +331,79 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
     ], $pairs);
   }
 
+  /**
+   * Test results are returned when criteria are passed in.
+   */
+  public function testGetMatchesCriteriaMatched() {
+    $this->setupMatchData();
+    $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+      'rule_group_id' => 1,
+      'criteria' => ['contact' => ['id' => ['>' => 1]]],
+    ])['values'];
+    $this->assertCount(2, $pairs);
+  }
+
+  /**
+   * Test results are returned when criteria are passed in & limit is  respected.
+   */
+  public function testGetMatchesCriteriaMatchedWithLimit() {
+    $this->setupMatchData();
+    $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+      'rule_group_id' => 1,
+      'criteria' => ['contact' => ['id' => ['>' => 1]]],
+      'options' => ['limit' => 1],
+    ])['values'];
+    $this->assertCount(1, $pairs);
+  }
+
+  /**
+   * Test results are returned when criteria are passed in & limit is  respected.
+   */
+  public function testGetMatchesCriteriaMatchedWithSearchLimit() {
+    $this->setupMatchData();
+    $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+      'rule_group_id' => 1,
+      'criteria' => ['contact' => ['id' => ['>' => 1]]],
+      'search_limit' => 1,
+    ])['values'];
+    $this->assertCount(1, $pairs);
+  }
+
+  /**
+   * Test getting matches where there are  no criteria.
+   */
+  public function testGetMatchesNoCriteria() {
+    $this->setupMatchData();
+    $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+      'rule_group_id' => 1,
+    ])['values'];
+    $this->assertCount(2, $pairs);
+  }
+
+  /**
+   * Test getting matches with a limit in play.
+   */
+  public function testGetMatchesNoCriteriaButLimit() {
+    $this->setupMatchData();
+    $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+      'rule_group_id' => 1,
+      'options' => ['limit' => 1],
+    ])['values'];
+    $this->assertCount(1, $pairs);
+  }
+
+  /**
+   * Test that if criteria are passed and there are no matching contacts no matches are returned.
+   */
+  public function testGetMatchesCriteriaNotMatched() {
+    $this->setupMatchData();
+    $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
+      'rule_group_id' => 1,
+      'criteria' => ['contact' => ['id' => ['>' => 100000]]],
+    ])['values'];
+    $this->assertCount(0, $pairs);
+  }
+
   /**
    * Test function that gets organization pairs.
    *
@@ -800,6 +883,67 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
     $this->callAPISuccess('CustomGroup', 'delete', ['id' => $multiGroup['id']]);
   }
 
+  /**
+   * Test that ContactReference fields are updated to point to the main contact
+   * after a merge is performed and the duplicate contact is deleted.
+   */
+  public function testMigrationOfContactReferenceCustomField() {
+    // Create Custom Fields
+    $contactGroup = $this->setupCustomGroupForIndividual();
+    $activityGroup = $this->customGroupCreate([
+      'name'    => 'test_group_activity',
+      'extends' => 'Activity',
+    ]);
+    $refFieldContact = $this->customFieldCreate([
+      'custom_group_id' => $contactGroup['id'],
+      'label'           => 'field_1' . $contactGroup['id'],
+      'data_type'       => 'ContactReference',
+      'default_value'   => NULL,
+    ]);
+    $refFieldActivity = $this->customFieldCreate([
+      'custom_group_id' => $activityGroup['id'],
+      'label'           => 'field_1' . $activityGroup['id'],
+      'data_type'       => 'ContactReference',
+      'default_value'   => NULL,
+    ]);
+
+    // Contacts setup
+    $this->setupMatchData();
+    $originalContactID = $this->contacts[0]['id'];
+    $duplicateContactID = $this->contacts[1]['id'];
+
+    // create a contact that won't be merged but has a ContactReference field
+    // pointing to the duplicate (to be deleted) contact
+    $unrelatedContact = $this->individualCreate([
+      'first_name'               => 'Unrelated',
+      'first_name'               => 'Contact',
+      'email'                    => 'unrelated@example.com',
+      "custom_{$refFieldContact['id']}" => $duplicateContactID,
+    ]);
+    // also create an activity with a ContactReference custom field
+    $activity = $this->activityCreate([
+      'target_contact_id'                => $unrelatedContact,
+      "custom_{$refFieldActivity['id']}" => $duplicateContactID,
+    ]);
+
+    // verify that the fields were set
+    $this->assertCustomFieldValue($unrelatedContact, $duplicateContactID, "custom_{$refFieldContact['id']}");
+    $this->assertEntityCustomFieldValue('Activity', $activity['id'], $duplicateContactID, "custom_{$refFieldActivity['id']}_id");
+
+    // Perform merge
+    $this->mergeContacts($originalContactID, $duplicateContactID, []);
+
+    // verify that the ContactReference fields were updated to point to the surviving contact post-merge
+    $this->assertCustomFieldValue($unrelatedContact, $originalContactID, "custom_{$refFieldContact['id']}");
+    $this->assertEntityCustomFieldValue('Activity', $activity['id'], $originalContactID, "custom_{$refFieldActivity['id']}_id");
+
+    // cleanup created custom set
+    $this->callAPISuccess('CustomField', 'delete', ['id' => $refFieldContact['id']]);
+    $this->callAPISuccess('CustomGroup', 'delete', ['id' => $contactGroup['id']]);
+    $this->callAPISuccess('CustomField', 'delete', ['id' => $refFieldActivity['id']]);
+    $this->callAPISuccess('CustomGroup', 'delete', ['id' => $activityGroup['id']]);
+  }
+
   /**
    * Calls merge method on given contacts, with values given in $params array.
    *
@@ -835,8 +979,21 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
    * @param $customFieldName
    */
   private function assertCustomFieldValue($contactID, $expectedValue, $customFieldName) {
-    $data = $this->callAPISuccess('Contact', 'getsingle', [
-      'id' => $contactID,
+    $this->assertEntityCustomFieldValue('Contact', $contactID, $expectedValue, $customFieldName);
+  }
+
+  /**
+   * Check if the custom field of the given field and entity id matches the
+   * expected value
+   *
+   * @param $entity
+   * @param $id
+   * @param $expectedValue
+   * @param $customFieldName
+   */
+  private function assertEntityCustomFieldValue($entity, $id, $expectedValue, $customFieldName) {
+    $data = $this->callAPISuccess($entity, 'getsingle', [
+      'id'     => $id,
       'return' => [$customFieldName],
     ]);
 
@@ -918,7 +1075,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
     foreach ($fixtures as $fixture) {
       $contactID = $this->individualCreate($fixture);
       $this->contacts[] = array_merge($fixture, ['id' => $contactID]);
-      sleep(5);
+      sleep(2);
     }
     $organizationFixtures = [
       [