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