4 * Class CRM_Dedupe_DedupeFinderTest
7 class CRM_Dedupe_DedupeFinderTest
extends CiviUnitTestCase
{
10 * IDs of created contacts.
14 protected $contactIDs = array();
17 * ID of the group holding the contacts.
24 * Clean up after the test.
26 public function tearDown() {
28 foreach ($this->contactIDs
as $contactId) {
29 $this->contactDelete($contactId);
32 $this->callAPISuccess('group', 'delete', array('id' => $this->groupID
));
38 * Test the unsupervised dedupe rule against a group.
42 public function testUnsupervisedDupes() {
43 // make dupe checks based on based on following contact sets:
44 // FIRST - LAST - EMAIL
45 // ---------------------------------
46 // robin - hood - robin@example.com
47 // robin - hood - hood@example.com
48 // robin - dale - robin@example.com
49 // little - dale - dale@example.com
50 // will - dale - dale@example.com
51 // will - dale - will@example.com
52 // will - dale - will@example.com
53 $this->setupForGroupDedupe();
55 $ruleGroup = $this->callAPISuccessGetSingle('RuleGroup', array('is_reserved' => 1, 'contact_type' => 'Individual', 'used' => 'Unsupervised'));
57 $foundDupes = CRM_Dedupe_Finder
::dupesInGroup($ruleGroup['id'], $this->groupID
);
58 $this->assertEquals(count($foundDupes), 3, 'Check Individual-Fuzzy dupe rule for dupesInGroup().');
62 * Test that a rule set to is_reserved = 0 works.
64 * There is a different search used dependent on this variable.
66 public function testCustomRule() {
67 $this->setupForGroupDedupe();
69 $ruleGroup = $this->callAPISuccess('RuleGroup', 'create', array(
70 'contact_type' => 'Individual',
74 'title' => 'TestRule',
78 foreach (array('birth_date', 'first_name', 'last_name') as $field) {
79 $rules[$field] = $this->callAPISuccess('Rule', 'create', [
80 'dedupe_rule_group_id' => $ruleGroup['id'],
81 'rule_table' => 'civicrm_contact',
83 'rule_field' => $field,
86 $foundDupes = CRM_Dedupe_Finder
::dupesInGroup($ruleGroup['id'], $this->groupID
);
87 $this->assertEquals(count($foundDupes), 4);
88 CRM_Dedupe_Finder
::dupes($ruleGroup['id']);
93 * Test a custom rule with a non-default field.
95 public function testCustomRuleWithAddress() {
96 $this->setupForGroupDedupe();
98 $ruleGroup = $this->callAPISuccess('RuleGroup', 'create', array(
99 'contact_type' => 'Individual',
102 'name' => 'TestRule',
103 'title' => 'TestRule',
107 foreach (array('postal_code') as $field) {
108 $rules[$field] = $this->callAPISuccess('Rule', 'create', [
109 'dedupe_rule_group_id' => $ruleGroup['id'],
110 'rule_table' => 'civicrm_address',
112 'rule_field' => $field,
115 $foundDupes = CRM_Dedupe_Finder
::dupesInGroup($ruleGroup['id'], $this->groupID
);
116 $this->assertEquals(count($foundDupes), 1);
117 CRM_Dedupe_Finder
::dupes($ruleGroup['id']);
122 * Test the supervised dedupe rule against a group.
126 public function testSupervisedDupes() {
127 $this->setupForGroupDedupe();
128 $ruleGroup = $this->callAPISuccessGetSingle('RuleGroup', array('is_reserved' => 1, 'contact_type' => 'Individual', 'used' => 'Supervised'));
129 $foundDupes = CRM_Dedupe_Finder
::dupesInGroup($ruleGroup['id'], $this->groupID
);
130 // -------------------------------------------------------------------------
131 // default dedupe rule: threshold = 20 => (First + Last + Email) Matches ( 1 pair )
132 // --------------------------------------------------------------------------
133 // will - dale - will@example.com
134 // will - dale - will@example.com
135 // so 1 pair for - first + last + mail
136 $this->assertEquals(count($foundDupes), 1, 'Check Individual-Fuzzy dupe rule for dupesInGroup().');
140 * Test dupesByParams function.
142 public function testDupesByParams() {
143 // make dupe checks based on based on following contact sets:
144 // FIRST - LAST - EMAIL
145 // ---------------------------------
146 // robin - hood - robin@example.com
147 // robin - hood - hood@example.com
148 // robin - dale - robin@example.com
149 // little - dale - dale@example.com
150 // will - dale - dale@example.com
151 // will - dale - will@example.com
152 // will - dale - will@example.com
155 // FIXME: move create params to separate function
158 'first_name' => 'robin',
159 'last_name' => 'hood',
160 'email' => 'robin@example.com',
161 'contact_type' => 'Individual',
164 'first_name' => 'robin',
165 'last_name' => 'hood',
166 'email' => 'hood@example.com',
167 'contact_type' => 'Individual',
170 'first_name' => 'robin',
171 'last_name' => 'dale',
172 'email' => 'robin@example.com',
173 'contact_type' => 'Individual',
176 'first_name' => 'little',
177 'last_name' => 'dale',
178 'email' => 'dale@example.com',
179 'contact_type' => 'Individual',
182 'first_name' => 'will',
183 'last_name' => 'dale',
184 'email' => 'dale@example.com',
185 'contact_type' => 'Individual',
188 'first_name' => 'will',
189 'last_name' => 'dale',
190 'email' => 'will@example.com',
191 'contact_type' => 'Individual',
194 'first_name' => 'will',
195 'last_name' => 'dale',
196 'email' => 'will@example.com',
197 'contact_type' => 'Individual',
201 $this->hookClass
->setHook('civicrm_findDuplicates', array($this, 'hook_civicrm_findDuplicates'));
205 foreach ($params as $param) {
206 $contact = $this->callAPISuccess('contact', 'create', $param);
208 'contact_id' => $contact['id'],
209 'street_address' => 'Ambachtstraat 23',
210 'location_type_id' => 1,
212 $this->callAPISuccess('address', 'create', $params);
213 $contactIds[$count++
] = $contact['id'];
216 // verify that all contacts have been created separately
217 $this->assertEquals(count($contactIds), 7, 'Check for number of contacts.');
220 'first_name' => 'robin',
221 'last_name' => 'hood',
222 'email' => 'hood@example.com',
223 'street_address' => 'Ambachtstraat 23',
225 CRM_Core_TemporaryErrorScope
::useException();
226 $ids = CRM_Contact_BAO_Contact
::getDuplicateContacts($fields, 'Individual', 'General', [], TRUE, NULL, ['event_id' => 1]);
228 // Check with default Individual-General rule
229 $this->assertEquals(count($ids), 2, 'Check Individual-General rule for dupesByParams().');
231 // delete all created contacts
232 foreach ($contactIds as $contactId) {
233 $this->contactDelete($contactId);
238 * Implements hook_civicrm_findDuplicates().
240 * Locks in expected params
243 public function hook_civicrm_findDuplicates($dedupeParams, &$dedupeResults, $contextParams) {
244 $expectedDedupeParams = [
245 'check_permission' => TRUE,
246 'contact_type' => 'Individual',
248 'rule_group_id' => NULL,
249 'excluded_contact_ids' => [],
251 foreach ($expectedDedupeParams as $key => $value) {
252 $this->assertEquals($value, $dedupeParams[$key]);
254 $expectedDedupeResults = [
258 foreach ($expectedDedupeResults as $key => $value) {
259 $this->assertEquals($value, $dedupeResults[$key]);
262 $expectedContext = ['event_id' => 1];
263 foreach ($expectedContext as $key => $value) {
264 $this->assertEquals($value, $contextParams[$key]);
267 return $dedupeResults;
271 * Set up a group of dedupable contacts.
273 protected function setupForGroupDedupe() {
275 'name' => 'Dupe Group',
276 'title' => 'New Test Dupe Group',
279 'visibility' => 'Public Pages',
282 $result = $this->callAPISuccess('group', 'create', $params);
283 $this->groupID
= $result['id'];
287 'first_name' => 'robin',
288 'last_name' => 'hood',
289 'email' => 'robin@example.com',
290 'contact_type' => 'Individual',
291 'birth_date' => '2016-01-01',
292 'api.Address.create' => ['location_type_id' => 'Billing', 'postal_code' => '99999'],
295 'first_name' => 'robin',
296 'last_name' => 'hood',
297 'email' => 'hood@example.com',
298 'contact_type' => 'Individual',
299 'birth_date' => '2016-01-01',
300 'api.Address.create' => ['location_type_id' => 'Billing', 'postal_code' => '99999'],
303 'first_name' => 'robin',
304 'last_name' => 'dale',
305 'email' => 'robin@example.com',
306 'contact_type' => 'Individual',
309 'first_name' => 'little',
310 'last_name' => 'dale',
311 'email' => 'dale@example.com',
312 'contact_type' => 'Individual',
315 'first_name' => 'will',
316 'last_name' => 'dale',
317 'email' => 'dale@example.com',
318 'contact_type' => 'Individual',
321 'first_name' => 'will',
322 'last_name' => 'dale',
323 'email' => 'will@example.com',
324 'contact_type' => 'Individual',
327 'first_name' => 'will',
328 'last_name' => 'dale',
329 'email' => 'will@example.com',
330 'contact_type' => 'Individual',
335 foreach ($params as $param) {
336 $contact = $this->callAPISuccess('contact', 'create', $param);
337 $this->contactIDs
[$count++
] = $contact['id'];
340 'contact_id' => $contact['id'],
341 'group_id' => $this->groupID
,
343 $this->callAPISuccess('group_contact', 'create', $grpParams);
346 // verify that all contacts have been created separately
347 $this->assertEquals(count($this->contactIDs
), 7, 'Check for number of contacts.');