Merge pull request #4771 from pratikshad/CRM-15409
[civicrm-core.git] / tests / phpunit / WebTest / Import / DuplicateMatchingTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License along with this program; if not, contact CiviCRM LLC |
21 | at info[AT]civicrm[DOT]org. If you have questions about the |
22 | GNU Affero General Public License or the licensing of CiviCRM, |
23 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
24 +--------------------------------------------------------------------+
25 */
26
27 require_once 'WebTest/Import/ImportCiviSeleniumTestCase.php';
28
29 /**
30 * Class WebTest_Import_DuplicateMatchingTest
31 */
32 class WebTest_Import_DuplicateMatchingTest extends ImportCiviSeleniumTestCase {
33
34 protected function setUp() {
35 parent::setUp();
36 }
37
38 /*
39 * Test contact import for Individuals Duplicate Matching.
40 */
41 function testIndividualDuplicateMatchingImport() {
42 $this->webtestLogin();
43
44 $this->openCiviPage("contact/add", "reset=1&ct=Individual", 'first_name');
45
46 $email = substr(sha1(rand()), 0, 7) . '@example.com';
47
48 // fill in first name
49 $firstName = substr(sha1(rand()), 0, 7);
50 $this->type('first_name', $firstName);
51
52 // fill in last name
53 $lastName = substr(sha1(rand()), 0, 7);
54 $this->type('last_name', $lastName);
55
56 //fill in email
57 $this->type('email_1_email', $email);
58
59 // Clicking save.
60 $this->click('_qf_Contact_upload_view');
61 $this->waitForPageToLoad($this->getTimeoutMsec());
62 $this->waitForText('crm-notification-container', "Contact Saved");
63
64 $existingContact = array(
65 'first_name' => $firstName,
66 'last_name' => $lastName,
67 'email' => $email,
68 );
69
70 // Get sample import data.
71 list($headers, $rows) = $this->_individualDuplicateMatchingCSVData($existingContact);
72
73 // Import and check Individual contacts in Skip mode.
74 $other = array('callbackImportSummary' => 'checkDuplicateContacts');
75 $this->importContacts($headers, $rows, 'Individual', 'Skip', array(), $other);
76
77 // Get imported contact Ids
78 $importedContactIds = $this->_getImportedContactIds($rows);
79
80 // Build update mode import headers
81 $updateHeaders = array(
82 'email' => 'Email',
83 'first_name' => 'First Name',
84 'last_name' => 'Last Name',
85 );
86
87 // Create update mode import rows
88 $updateRows = array();
89 $contact = current($rows);
90 foreach ($importedContactIds as $cid) {
91 $updateRows[$cid] = array(
92 'email' => $contact['email'],
93 'first_name' => substr(sha1(rand()), 0, 7),
94 'last_name' => 'Anderson' . substr(sha1(rand()), 0, 7),
95 );
96 $contact = next($rows);
97 }
98
99 // Import and check Individual contacts in Update mode.
100 $this->importContacts($updateHeaders, $updateRows, 'Individual', 'Update');
101
102 // Headers that should not updated.
103 $fillHeaders = $updateHeaders;
104
105 // Headers that should fill.
106 $fillHeaders['gender'] = 'Gender';
107 $fillHeaders['dob'] = 'Birth Date';
108
109 $fillRows = array();
110 foreach ($importedContactIds as $cid) {
111 $fillRows[$cid] = array(
112 'email' => $updateRows[$cid]['email'],
113 // should not update
114 'first_name' => substr(sha1(rand()), 0, 7),
115 // should not update
116 'last_name' => 'Anderson' . substr(sha1(rand()), 0, 7),
117 'gender' => 'Male',
118 'dob' => '1986-04-16',
119 );
120 }
121
122 // Import and check Individual contacts in Fill mode.
123 $this->importContacts($fillHeaders, $fillRows, 'Individual', 'Fill');
124
125 foreach ($importedContactIds as $cid) {
126 $this->openCiviPage("contact/view", "reset=1&cid={$cid}");
127
128 // Check old display name.
129 $displayName = "{$updateRows[$cid]['first_name']} {$updateRows[$cid]['last_name']}";
130 $this->assertTrue($this->isTextPresent("$displayName"), 'Contact display name should not update in fill mode!');
131
132 $this->verifyText('css=div.crm-contact-gender_display', preg_quote($fillRows[$cid]['gender']));
133 }
134
135 // Recreate same conacts using 'No Duplicate Checking'
136 $this->importContacts($headers, $rows, 'Individual', 'No Duplicate Checking');
137 }
138
139 /*
140 * Test contact import for Organization Duplicate Matching.
141 */
142 function testOrganizationDuplicateMatchingImport() {
143 $this->webtestLogin();
144
145 //create oranization
146 $this->openCiviPage("contact/add", "reset=1&ct=Organization", 'organization_name');
147
148 // get value for organization contact
149 $organizationName = 'org_' . substr(sha1(rand()), 0, 7);
150 $organizationEmail = substr(sha1(rand()), 0, 7) . '@example.org';
151
152 $this->click('organization_name');
153
154 //fill in first name
155 $this->type('organization_name', $organizationName);
156
157 //fill in Email
158 $this->type('email_1_email', $organizationEmail);
159
160 // Clicking save.
161 $this->click('_qf_Contact_upload_view');
162 $this->waitForPageToLoad($this->getTimeoutMsec());
163
164 // Reset Organization strict dedupe rule for Organization name
165 // and Organization email (default)
166 $this->webtestStrictDedupeRuleDefault('Organization');
167
168 $organizationFields = array(
169 'organization_name' => $organizationName,
170 'email' => $organizationEmail,
171 );
172 // Get sample import data.
173 list($headers, $rows) = $this->_organizationDuplicateMatchingCSVData($organizationFields);
174
175 // Import and check Individual contacts in Skip mode.
176 $other = array('callbackImportSummary' => 'checkDuplicateContacts');
177 $this->importContacts($headers, $rows, 'Organization', 'Skip', array(), $other);
178
179 // Get imported contact Ids
180 $importedContactIds = $this->_getImportedContactIds($rows, 'Organization');
181
182 // Build update mode import headers
183 $updateHeaders = array(
184 'email' => 'Email',
185 'organization_name' => 'Organization Name',
186 );
187
188 // Create update mode import rows
189 $updateRows = array();
190 $contact = current($rows);
191 foreach ($importedContactIds as $cid) {
192 $updateRows[$cid] = array(
193 'email' => $contact['email'],
194 'organization_name' => 'UpdatedOrg ' . substr(sha1(rand()), 0, 7),
195 );
196 $contact = next($rows);
197 }
198
199 // Import and check Individual contacts in Update mode.
200 $this->importContacts($updateHeaders, $updateRows, 'Organization', 'Update');
201
202 // Headers that should not updated.
203 $fillHeaders = $updateHeaders;
204
205 // Headers that should fill.
206 $fillHeaders['legal_name'] = 'Legal Name';
207
208 $fillRows = array();
209 foreach ($importedContactIds as $cid) {
210 $fillRows[$cid] = array(
211 'email' => $updateRows[$cid]['email'],
212 // should not update
213 'organization_name' => 'UpdateOrg ' . substr(sha1(rand()), 0, 7),
214 'legal_name' => 'org ' . substr(sha1(rand()), 0, 7),
215 );
216 }
217
218 // Import and check Individual contacts in Fill mode.
219 $this->importContacts($fillHeaders, $fillRows, 'Organization', 'Fill');
220
221 foreach ($importedContactIds as $cid) {
222 $this->openCiviPage("contact/view", "reset=1&cid={$cid}");
223
224 // Check old Organization name.
225 $organizationName = $updateRows[$cid]['organization_name'];
226 $this->assertTrue($this->isTextPresent("$organizationName"), 'Contact should not update in fill mode!');
227 $this->verifyText("xpath=//div[@id='crm-contactinfo-content']/div/div[3]/div[2]", preg_quote($fillRows[$cid]['legal_name']));
228 }
229
230 // Recreate same conacts using 'No Duplicate Checking'
231 $this->importContacts($headers, $rows, 'Organization', 'No Duplicate Checking');
232 }
233
234 /*
235 * Test contact import for Household Duplicate Matching.
236 */
237 function testHouseholdDuplicateMatchingImport() {
238 $this->webtestLogin();
239
240 // create household
241 $this->openCiviPage("contact/add", "reset=1&ct=Household", 'household_name');
242
243 // get values for household contact
244 $householdName = 'household_' . substr(sha1(rand()), 0, 7);
245 $householdEmail = substr(sha1(rand()), 0, 7) . '@example.com';
246
247 //fill in household name
248 $this->type('household_name', $householdName);
249
250 //fill in Email
251 $this->type('email_1_email', $householdEmail);
252
253 // Clicking save.
254 $this->click('_qf_Contact_upload_view');
255 $this->waitForPageToLoad($this->getTimeoutMsec());
256
257 // Reset Household strict dedupe rule for Household name
258 // and Household email (default)
259 $this->webtestStrictDedupeRuleDefault('Household');
260
261 $this->waitForPageToLoad($this->getTimeoutMsec());
262
263 // Store household contact value in array
264 $householdFields = array(
265 'household_name' => $householdName,
266 'email' => $householdEmail,
267 );
268
269 // Get sample import data.
270 list($headers, $rows) = $this->_householdDuplicateMatchingCSVData($householdFields);
271
272 // Import and check Individual contacts in Skip mode.
273 $other = array('callbackImportSummary' => 'checkDuplicateContacts');
274 $this->importContacts($headers, $rows, 'Household', 'Skip', array(), $other);
275
276 // Get imported contact Ids
277 $importedContactIds = $this->_getImportedContactIds($rows, 'Household');
278
279 // Build update mode import headers
280 $updateHeaders = array(
281 'email' => 'Email',
282 'household_name' => 'Household Name',
283 );
284
285 // Create update mode import rows
286 $updateRows = array();
287 $contact = current($rows);
288 foreach ($importedContactIds as $cid) {
289 $updateRows[$cid] = array(
290 'email' => $contact['email'],
291 'household_name' => 'UpdatedHousehold ' . substr(sha1(rand()), 0, 7),
292 );
293 $contact = next($rows);
294 }
295
296 $this->importContacts($updateHeaders, $updateRows, 'Household', 'Update');
297
298 // Headers that should not updated.
299 $fillHeaders = $updateHeaders;
300
301 // Headers that should fill.
302 $fillHeaders['nick_name'] = 'Nick Name';
303
304 $fillRows = array();
305 foreach ($importedContactIds as $cid) {
306 $fillRows[$cid] = array(
307 'email' => $updateRows[$cid]['email'],
308 // should not update
309 'household_name' => 'UpdatedHousehold ' . substr(sha1(rand()), 0, 7),
310 'nick_name' => 'Household ' . substr(sha1(rand()), 0, 7),
311 );
312 }
313
314 // Import and check Individual contacts in Fill mode.
315 $this->importContacts($fillHeaders, $fillRows, 'Household', 'Fill');
316
317 foreach ($importedContactIds as $cid) {
318 $this->openCiviPage("contact/view", "reset=1&cid={$cid}");
319
320 // Check old Household name.
321 $householdName = $updateRows[$cid]['household_name'];
322 $this->assertTrue($this->isTextPresent("$householdName"), 'Contact should not update in fill mode!');
323 $this->verifyText("xpath=//div[@id='crm-contactinfo-content']/div/div[2]/div[2]", preg_quote($fillRows[$cid]['nick_name']));
324 }
325
326 // Recreate same conacts using 'No Duplicate Checking'
327 $this->importContacts($headers, $rows, 'Household', 'No Duplicate Checking');
328 }
329
330 /**
331 * @param $originalHeaders
332 * @param $originalRows
333 * @param $checkSummary
334 */
335 function checkDuplicateContacts($originalHeaders, $originalRows, $checkSummary) {
336 $this->assertTrue($this->isTextPresent('CiviCRM has detected one record which is a duplicate of existing CiviCRM contact record. These records have not been imported.'));
337
338 $checkSummary = array(
339 'Total Rows' => '2',
340 'Duplicate Rows' => '1',
341 'Total Contacts' => '1',
342 );
343
344 foreach ($checkSummary as $label => $value) {
345 $this->verifyText("xpath=//table[@id='summary-counts']/tbody/tr/td[text()='{$label}']/following-sibling::td", preg_quote($value));
346 }
347 }
348
349 /*
350 * Helper function to provide data for contact import for
351 * Individual Duplicate Matching.
352 */
353 /**
354 * @param $individualFields
355 *
356 * @return array
357 */
358 function _individualDuplicateMatchingCSVData($individualFields) {
359 $headers = array(
360 'first_name' => 'First Name',
361 'middle_name' => 'Middle Name',
362 'last_name' => 'Last Name',
363 'email' => 'Email',
364 'phone' => 'Phone',
365 'address_1' => 'Additional Address 1',
366 'address_2' => 'Additional Address 2',
367 'city' => 'City',
368 'state' => 'State',
369 'country' => 'Country',
370 );
371
372 $rows = array(
373 array('first_name' => isset($individualFields['first_name']) ? $individualFields['first_name'] : substr(sha1(rand()), 0, 7),
374 'middle_name' => isset($individualFields['middle_name']) ? $individualFields['middle_name'] : substr(sha1(rand()), 0, 7),
375 'last_name' => isset($individualFields['last_name']) ? $individualFields['last_name'] : 'Anderson',
376 'email' => isset($individualFields['email']) ? $individualFields['email'] : substr(sha1(rand()), 0, 7) . '@example.com',
377 'phone' => '6949912154',
378 'address_1' => 'Add 1',
379 'address_2' => 'Add 2',
380 'city' => 'Watson',
381 'state' => 'NY',
382 'country' => 'United States',
383 ),
384 array('first_name' => substr(sha1(rand()), 0, 7),
385 'middle_name' => substr(sha1(rand()), 0, 7),
386 'last_name' => 'Summerson',
387 'email' => substr(sha1(rand()), 0, 7) . '@example.com',
388 'phone' => '6944412154',
389 'address_1' => 'Add 1',
390 'address_2' => 'Add 2',
391 'city' => 'Watson',
392 'state' => 'NY',
393 'country' => 'United States',
394 ),
395 );
396
397 return array($headers, $rows);
398 }
399
400 /*
401 * Helper function to provide data for contact import for
402 * Organizations Duplicate Matching.
403 */
404 /**
405 * @param $organizationFields
406 *
407 * @return array
408 */
409 function _organizationDuplicateMatchingCSVData($organizationFields) {
410 $headers = array(
411 'organization_name' => 'Organization Name',
412 'email' => 'Email',
413 'phone' => 'Phone',
414 'address_1' => 'Additional Address 1',
415 'address_2' => 'Additional Address 2',
416 'city' => 'City',
417 'state' => 'State',
418 'country' => 'Country',
419 );
420 $rows = array(
421 array('organization_name' => isset($organizationFields['organization_name']) ? $organizationFields['organization_name'] : 'org_' . substr(sha1(rand()), 0, 7),
422 'email' => isset($organizationFields['email']) ? $organizationFields['email'] : substr(sha1(rand()), 0, 7) . 'example.org',
423 'phone' => '9949912154',
424 'address_1' => 'Add 1',
425 'address_2' => 'Add 2',
426 'city' => 'Watson',
427 'state' => 'NY',
428 'country' => 'United States',
429 ),
430 array('organization_name' => 'org_' . substr(sha1(rand()), 0, 7),
431 'email' => substr(sha1(rand()), 0, 7) . '@example.org',
432 'phone' => '6949412154',
433 'address_1' => 'Add 1',
434 'address_2' => 'Add 2',
435 'city' => 'Watson',
436 'state' => 'NY',
437 'country' => 'United States',
438 ),
439 );
440
441 return array($headers, $rows);
442 }
443
444 /*
445 * Helper function to provide data for contact import for Household
446 * Duplicate Matching.
447 */
448 /**
449 * @param $householdFields
450 *
451 * @return array
452 */
453 function _householdDuplicateMatchingCSVData($householdFields) {
454 $headers = array(
455 'household_name' => 'Household Name',
456 'email' => 'Email',
457 'phone' => 'Phone',
458 'address_1' => 'Additional Address 1',
459 'address_2' => 'Additional Address 2',
460 'city' => 'City',
461 'state' => 'State',
462 'country' => 'Country',
463 );
464
465 $rows = array(
466 array('household_name' => isset($householdFields['household_name']) ? $householdFields['household_name'] : 'household_' . substr(sha1(rand()), 0, 7),
467 'email' => isset($householdFields['email']) ? $householdFields['email'] : substr(sha1(rand()), 0, 7) . '@example.com',
468 'phone' => '3949912154',
469 'address_1' => 'Add 1',
470 'address_2' => 'Add 2',
471 'city' => 'Watson',
472 'state' => 'NY',
473 'country' => 'United States',
474 ),
475 array('household_name' => 'household_' . substr(sha1(rand()), 0, 7),
476 'email' => substr(sha1(rand()), 0, 7) . '@example.org',
477 'phone' => '5949412154',
478 'address_1' => 'Add 1',
479 'address_2' => 'Add 2',
480 'city' => 'Watson',
481 'state' => 'NY',
482 'country' => 'United States',
483 ),
484 );
485
486 return array($headers, $rows);
487 }
488 }
489