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