Merge pull request #5077 from eileenmcnaughton/comment-full-stops
[civicrm-core.git] / tests / phpunit / WebTest / Contact / MergeContactsTest.php
... / ...
CommitLineData
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
27require_once 'CiviTest/CiviSeleniumTestCase.php';
28
29/**
30 * Class WebTest_Contact_MergeContactsTest
31 */
32class WebTest_Contact_MergeContactsTest extends CiviSeleniumTestCase {
33
34 protected function setUp() {
35 parent::setUp();
36 }
37
38 public function testIndividualAdd() {
39 $this->webtestLogin();
40
41 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
42
43 // add contact1
44 //select prefix
45 $prefix = 'Mr.';
46 $this->click("prefix_id");
47 $this->select("prefix_id", "label=$prefix");
48
49 //fill in first name
50 $firstName = substr(sha1(rand()), 0, 7);
51 $this->type('first_name', $firstName);
52
53 //fill in last name
54 $lastName = substr(sha1(rand()), 0, 7);
55 $this->type('last_name', $lastName);
56
57 //fill in email id
58 $this->type('email_1_email', "{$firstName}.{$lastName}@example.com");
59
60 //fill in billing email id
61 $this->click('addEmail');
62 $this->waitForElementPresent('email_2_email');
63 $this->type('email_2_email', "$firstName.$lastName@billing.com");
64 $this->select('email_2_location_type_id', 'value=5');
65
66 // Clicking save.
67 $this->click("_qf_Contact_upload_view");
68 $this->waitForPageToLoad($this->getTimeoutMsec());
69 $this->waitForText('crm-notification-container', "Contact Saved");
70
71 // Add Contact to a group
72 $group = 'Newsletter Subscribers';
73 $this->click('css=li#tab_group a');
74 $this->waitForElementPresent('_qf_GroupContact_next');
75 $this->select('group_id', "label=$group");
76 $this->click('_qf_GroupContact_next');
77 $this->waitForElementPresent('link=Delete');
78 $this->waitForText('crm-notification-container', "Added to Group");
79
80 // Add Tags to the contact
81 $tag = 'Government Entity';
82 $this->click("css=li#tab_tag a");
83 $this->waitForElementPresent('tagtree');
84 $this->click("xpath=//div[@id='tagtree']/ul//li/input/../span/label[text()='$tag']");
85 $this->click("css=#tab_summary a");
86 $this->assertElementContainsText('css=.crm-summary-block #tags', $tag);
87
88 // Add an activity
89 $subject = "This is subject of test activity being added through activity tab of contact summary screen.";
90 $this->addActivity($firstName, $lastName, $subject);
91
92 // contact2: duplicate of contact1.
93 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
94
95 //fill in first name
96 $this->type("first_name", $firstName);
97
98 //fill in last name
99 $this->type("last_name", $lastName);
100
101 //fill in email
102 $this->type("email_1_email", "{$firstName}.{$lastName}@example.com");
103
104 // Clicking save.
105 $this->click("_qf_Contact_refresh_dedupe");
106 $this->waitForPageToLoad($this->getTimeoutMsec());
107
108 $this->waitForText('crm-notification-container', "One matching contact was found. You can View or Edit the existing contact.");
109 $this->click("_qf_Contact_upload_duplicate");
110 $this->waitForPageToLoad($this->getTimeoutMsec());
111 $this->waitForText('crm-notification-container', "Contact Saved");
112
113 // Add second pair of dupes so we can test Merge and Goto Next Pair
114 $fname2 = 'Janet';
115 $lname2 = 'Rogers' . substr(sha1(rand()), 0, 7);
116 $email2 = "{$fname2}.{$lname2}@example.org";
117 $this->webtestAddContact($fname2, $lname2, $email2);
118
119 // Can not use helper for 2nd contact since it is a dupe
120 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
121 $this->type("first_name", $fname2);
122 $this->type("last_name", $lname2);
123 $this->type("email_1_email", $email2);
124 $this->click("_qf_Contact_refresh_dedupe");
125 $this->waitForPageToLoad($this->getTimeoutMsec());
126 $this->waitForText('crm-notification-container', "One matching contact was found. You can View or Edit the existing contact.");
127 $this->click("_qf_Contact_upload_duplicate");
128 $this->waitForPageToLoad($this->getTimeoutMsec());
129 $this->waitForText('crm-notification-container', "Contact Saved");
130
131 // Find and Merge Contacts with Supervised Rule
132 $this->openCiviPage("contact/dedupefind", "reset=1&rgid=1&action=renew");
133
134 // reload the page
135 $this->openCiviPage("contact/dedupefind", "reset=1&rgid=1&action=update");
136
137 // Select the contacts to be merged
138 $this->select("name=option51_length", "value=100");
139
140 $this->waitForElementPresent("xpath=//a[text()='$firstName $lastName']/../../td[4]/a[text()='merge']");
141 $this->clickLink("xpath=//a[text()='$firstName $lastName']/../../td[4]/a[text()='merge']");
142 $this->waitForElementPresent('_qf_Merge_cancel-bottom');
143
144 $this->clickLink("css=div.crm-contact-merge-form-block div.action-link a", '_qf_Merge_cancel-bottom');
145
146 // Move the activities, groups, etc to the main contact and merge using Merge and Goto Next Pair
147 $this->check('move_prefix_id');
148 $this->check('move_location_email_2');
149 $this->check('move_rel_table_activities');
150 $this->check('move_rel_table_groups');
151 $this->check('move_rel_table_tags');
152 $this->clickLink('_qf_Merge_next-bottom', '_qf_Merge_cancel-bottom');
153 $this->assertTrue($this->isTextPresent('Contacts Merged'), "Contacts Merged text was not found after merge.");
154
155 // Check that we are viewing the next Merge Pair (our 2nd contact, since the merge list is ordered by contact_id)
156 $this->assertTrue($this->isTextPresent("{$fname2} {$lname2}"), "Redirect for Goto Next Pair after merge did not work.");
157
158 // Ensure that the duplicate contact has been deleted
159 $this->openCiviPage("contact/search/advanced", "reset=1", '_qf_Advanced_refresh');
160 $this->type('sort_name', $firstName);
161 $this->click('deleted_contacts');
162 $this->click('_qf_Advanced_refresh');
163 $this->waitForPageToLoad($this->getTimeoutMsec());
164 $this->assertTrue($this->isTextPresent('1 Contact'), "Deletion of duplicate contact during merge was not successful. Dupe contact not found when searching trash.");
165
166 // Search for the main contact
167 $this->openCiviPage("contact/search/advanced", "reset=1", '_qf_Advanced_refresh');
168 $this->type('sort_name', $firstName);
169 $this->click('_qf_Advanced_refresh');
170 $this->waitForElementPresent("xpath=//form[@id='Advanced']/div[3]/div/div[2]/table/tbody/tr");
171
172 $this->click("//form[@id='Advanced']/div[3]/div/div[2]/table/tbody/tr/td[11]/span[1]/a[text()='View']");
173 $this->waitForPageToLoad($this->getTimeoutMsec());
174
175 // Verify prefix merged
176 // $this->verifyText( "xpath=//div[@class='left-corner']/h2", preg_quote( "$prefix $firstName $lastName" ) );
177
178 // Verify billing email merged
179 $this->isElementPresent("xpath=//div[@class='contact_details']/div[1][@class='contact_panel']/div[1][@class='contactCardLeft']/table/tbody/tr[4]/td[2]/span/a[text()='$firstName.$lastName@billing.com']");
180
181 // Verify activity merged
182 $this->click("css=li#tab_activity a");
183 $this->waitForElementPresent("xpath=//table[@class='contact-activity-selector-activity dataTable no-footer']/tbody/tr");
184 $this->verifyText("xpath=//table[@class='contact-activity-selector-activity dataTable no-footer']/tbody/tr/td[5]/a",
185 preg_quote("$lastName, $firstName")
186 );
187
188 // Verify group merged
189 $this->click("css=li#tab_group a");
190 $this->waitForElementPresent("GroupContact");
191 $this->waitForElementPresent("xpath=//form[@id='GroupContact']//div[@class='view-content view-contact-groups']//div/table/tbody/tr/td/a");
192 $this->verifyText("xpath=//form[@id='GroupContact']//div[@class='view-content view-contact-groups']//div/table/tbody/tr/td/a",
193 preg_quote("$group")
194 );
195
196 // Verify tag merged
197 $this->click("css=li#tab_tag a");
198 $this->waitForElementPresent('check_5');
199 $this->assertChecked("check_3");
200 }
201
202 public function testMergeContactSubType() {
203 $this->webtestLogin();
204 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
205 $this->waitForElementPresent('_qf_Contact_cancel-bottom');
206 //fill in first name
207 $firstName = "Anderson" . substr(sha1(rand()), 0, 4);
208 $this->type('first_name', $firstName);
209
210 //fill in last name
211 $lastName = substr(sha1(rand()), 0, 4);
212 $this->type('last_name', $lastName);
213
214 //fill in email id
215 $this->waitForElementPresent('email_1_email');
216 $this->type('email_1_email', "{$firstName}.{$lastName}@example.com");
217 $this->waitForElementPresent('contact_sub_type');
218 $this->select('contact_sub_type', "Parent");
219
220 // Clicking save.
221 $this->click("_qf_Contact_upload_view");
222 $this->waitForPageToLoad($this->getTimeoutMsec());
223 $this->waitForText('crm-notification-container', "Contact Saved");
224
225 // contact2: contact with same email id as contact 1.
226 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
227 $this->waitForElementPresent('_qf_Contact_cancel-bottom');
228
229 $fName = "John" . substr(sha1(rand()), 0, 4);
230 $this->type('first_name', $fName);
231 $lName = substr(sha1(rand()), 0, 4);
232 $this->type('last_name', $lName);
233 $this->type('email_1_email', "{$firstName}.{$lastName}@example.com");
234 $this->waitForElementPresent('contact_sub_type');
235 $this->multiselect2('contact_sub_type', array("Student", "Staff"));
236 $this->click("_qf_Contact_upload_view");
237 $this->waitForText('crm-notification-container', "Contact Saved");
238 $this->openCiviPage("contact/deduperules", "reset=1");
239 $this->click("xpath=//*[@id='option12']/tbody/tr[3]/td[3]/span/a[1][contains(text(),'Use Rule')]");
240 $this->waitForElementPresent('_qf_DedupeFind_submit-bottom');
241 $this->click("_qf_DedupeFind_next-bottom");
242
243 $this->waitForElementPresent("xpath=//form[@id='DedupeFind']/div[2]/div/table/tbody/tr[1]/td[4]/a[text()='merge']");
244 $this->waitForElementPresent("xpath=//form[@id='DedupeFind']/a[3]/span[contains(text(),'Done')]");
245 $this->isElementPresent("xpath=//table[@id='option51']/tbody/tr/td[1]/a[text()='{$firstName} {$lastName}']/../td[2]/a[text()='{$fName} {$lName}']");
246 $this->click("xpath=//table[@id='option51']/tbody/tr[1]/td[4]/a[text()='merge']");
247 $this->waitForElementPresent('_qf_Merge_cancel-bottom');
248 $this->click('toggleSelect');
249 $this->click('_qf_Merge_next-bottom');
250 $this->waitForPageToLoad($this->getTimeoutMsec());
251 $this->assertTrue($this->isTextPresent("Staff, Student"));
252 }
253
254 /**
255 * @param string $firstName
256 * @param string $lastName
257 * @param $subject
258 */
259 public function addActivity($firstName, $lastName, $subject) {
260 $withContact = substr(sha1(rand()), 0, 7);
261 $this->webtestAddContact($withContact, "Anderson", $withContact . "@anderson.name");
262
263 $this->click("css=li#tab_activity a");
264
265 // waiting for the activity dropdown to show up
266 $this->waitForElementPresent("other_activity");
267
268 // Select the activity type from the activity dropdown
269 $this->select("other_activity", "label=Meeting");
270
271 // waitForPageToLoad is not always reliable. Below, we're waiting for the submit
272 // button at the end of this page to show up, to make sure it's fully loaded.
273 $this->waitForElementPresent("_qf_Activity_upload");
274
275 // ...and verifying if the page contains properly formatted display name for chosen contact.
276 $this->assertTrue($this->isTextPresent("Anderson, " . $withContact), "Contact not found in line " . __LINE__);
277
278 // Now we're filling the "Assigned To" field.
279 // Typing contact's name into the field (using typeKeys(), not type()!)...
280 $this->select2("assignee_contact_id", $firstName, TRUE, FALSE);
281
282 // ...and verifying if the page contains properly formatted display name for chosen contact.
283 $this->assertTrue($this->isTextPresent("$lastName, " . $firstName), "Contact not found in line " . __LINE__);
284
285 // Since we're here, let's check if screen help is being displayed properly
286 $this->assertTrue($this->isTextPresent("A copy of this activity will be emailed to each Assignee."));
287
288 // Putting the contents into subject field - assigning the text to variable, it'll come in handy later
289 // For simple input fields we can use field id as selector
290 $this->type("subject", $subject);
291 $this->type("location", "Some location needs to be put in this field.");
292
293 // Choosing the Date.
294 // Please note that we don't want to put in fixed date, since
295 // we want this test to work in the future and not fail because
296 // of date being set in the past. Therefore, using helper webtestFillDateTime function.
297 $this->webtestFillDateTime('activity_date_time', '+1 month 11:10PM');
298
299 // Setting duration.
300 $this->type("duration", "30");
301
302 // Putting in details.
303 $this->type("details", "Really brief details information.");
304
305 // Making sure that status is set to Scheduled (using value, not label).
306 $this->select("status_id", "value=1");
307
308 // Setting priority.
309 $this->select("priority_id", "value=1");
310
311 // Clicking save.
312 $this->click("_qf_Activity_upload");
313 $this->waitForElementPresent("crm-notification-container");
314
315 // Is status message correct?
316 $this->waitForText('crm-notification-container', "Activity '$subject' has been saved.", "Status message didn't show up after saving!");
317 }
318
319 public function testMergeTest() {
320 $this->webtestLogin();
321
322 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
323
324 // add contact1
325 //fill in first name
326 $firstName = substr(sha1(rand()), 0, 7);
327 $this->type('first_name', $firstName);
328
329 //fill in last name
330 $lastName = substr(sha1(rand()), 0, 7);
331 $this->type('last_name', $lastName);
332
333 //fill in email id
334 $this->type('email_1_email', "{$firstName}.{$lastName}@example.com");
335
336 //fill in billing email id
337 $this->click('addEmail');
338 $this->waitForElementPresent('email_2_email');
339 $this->type('email_2_email', "$firstName.$lastName@billing.com");
340 $this->select('email_2_location_type_id', 'value=5');
341
342 //fill in home phone no
343 $this->type('phone_1_phone', "9876543210");
344
345 //fill in billing phone id
346 $this->click('addPhone');
347 $this->waitForElementPresent('phone_2_phone');
348 $this->type('phone_2_phone', "9876543120");
349 $this->select('phone_2_location_type_id', 'value=5');
350
351 // Clicking save.
352 $this->click("_qf_Contact_upload_view");
353 $this->waitForPageToLoad($this->getTimeoutMsec());
354 $this->waitForText('crm-notification-container', "Contact Saved");
355
356 // contact2: duplicate of contact1.
357 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
358
359 //fill in first name
360 $this->type("first_name", $firstName);
361
362 //fill in last name
363 $this->type("last_name", $lastName);
364
365 //fill in email
366 $this->type("email_1_email", "{$firstName}.{$lastName}@example.com");
367
368 //fill in home phone no
369 $this->type('phone_1_phone', "9876543211");
370
371 // Clicking save.
372 $this->click("_qf_Contact_refresh_dedupe");
373 $this->waitForPageToLoad($this->getTimeoutMsec());
374
375 $this->waitForText('crm-notification-container', "One matching contact was found. You can View or Edit the existing contact.");
376 $this->click("_qf_Contact_upload_duplicate");
377 $this->waitForPageToLoad($this->getTimeoutMsec());
378 $this->waitForText('crm-notification-container', "Contact Saved");
379
380 // Find and Merge Contacts with Supervised Rule
381 $this->openCiviPage("contact/dedupefind", "reset=1&rgid=1&action=renew");
382
383 // Select the contacts to be merged
384 $this->select("name=option51_length", "value=100");
385 $this->waitForElementPresent("xpath=//a[text()='$firstName $lastName']");
386 $this->click("xpath=//a[text()='$firstName $lastName']/../../td[4]/a[text()='merge']");
387 $this->waitForElementPresent('_qf_Merge_cancel-bottom');
388 $this->clickLink("css=div.crm-contact-merge-form-block div.action-link a", "xpath=//form[@id='Merge']/div[2]/table/tbody/tr[3]/td[4]/span[text()='(overwrite)']", FALSE);
389 $this->waitForElementPresent("xpath=//form[@id='Merge']/div[2]/table/tbody/tr[5]/td[4]/span[text()='(add)']");
390 $this->waitForElementPresent('_qf_Merge_cancel-bottom');
391
392 $this->check("move_location_email_1");
393 $this->check("location[email][1][operation]");
394 $this->check("move_location_email_2");
395 $this->check("move_location_phone_1");
396 $this->check("location[phone][1][operation]");
397 $this->check("move_location_phone_2");
398 $this->click("_qf_Merge_next-bottom");
399 $this->waitForPageToLoad($this->getTimeoutMsec());
400
401 $this->assertTrue($this->isTextPresent('Contacts Merged'));
402 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[2]/div[1][contains(text(), 'Home')]"));
403 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[2]/div[2]/a[contains(text(), '{$firstName}.{$lastName}@example.com')]"));
404 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[3]/div[1][contains(text(), 'Home')]"));
405 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[3]/div[2]/a[contains(text(), '{$firstName}.{$lastName}@example.com')]"));
406 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[4]/div[1][contains(text(), 'Billing')]"));
407 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[4]/div[2]/a[contains(text(), '$firstName.$lastName@billing.com')]"));
408 $this->assertTrue($this->isElementPresent("xpath=//div[@id='phone-block']/div/div/div[2]/div[1][contains(text(), 'Home')]"));
409 $this->assertTrue($this->isElementPresent("xpath=//div[@id='phone-block']/div/div/div[2]/div[2][contains(text(), '9876543211')]"));
410 $this->assertTrue($this->isElementPresent("xpath=//div[@id='phone-block']/div/div/div[3]/div[1][contains(text(), 'Home')]"));
411 $this->assertTrue($this->isElementPresent("xpath=//div[@id='phone-block']/div/div/div[3]/div[2][contains(text(), '9876543210')]"));
412 $this->assertTrue($this->isElementPresent("xpath=//div[@id='phone-block']/div/div/div[4]/div[1][contains(text(), 'Billing')]"));
413 $this->assertTrue($this->isElementPresent("xpath=//div[@id='phone-block']/div/div/div[4]/div[2][contains(text(), '9876543120')]"));
414
415 //Merge with the feature of (add)
416 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
417
418 // add contact1
419 //fill in first name
420 $firstName1 = substr(sha1(rand()), 0, 7);
421 $this->type('first_name', $firstName1);
422
423 //fill in last name
424 $lastName1 = substr(sha1(rand()), 0, 7);
425 $this->type('last_name', $lastName1);
426
427 //fill in billing email id
428 $this->waitForElementPresent('email_1_email');
429 $this->type('email_1_email', "$firstName1.$lastName1@example.com");
430 $this->select('email_1_location_type_id', 'value=5');
431
432 $this->click('addEmail');
433 $this->waitForElementPresent('email_2_email');
434 $this->type('email_2_email', "$firstName.$lastName@home.com");
435 $this->select('email_2_location_type_id', 'value=1');
436
437 //fill in home phone no
438 $this->type('phone_1_phone', "9876543210");
439
440 // Clicking save.
441 $this->click("_qf_Contact_upload_view");
442 $this->waitForPageToLoad($this->getTimeoutMsec());
443 $this->waitForText('crm-notification-container', "Contact Saved");
444
445 // contact2: duplicate of contact1.
446 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
447
448 //fill in first name
449 $this->type("first_name", $firstName1);
450
451 //fill in last name
452 $this->type("last_name", $lastName1);
453
454 //fill in email
455 $this->type("email_1_email", "{$firstName1}.{$lastName1}@example.com");
456
457 //fill in billing phone no
458 $this->type('phone_1_phone', "9876543120");
459 $this->select('phone_1_location_type_id', 'value=5');
460
461 // Clicking save.
462 $this->click("_qf_Contact_refresh_dedupe");
463 $this->waitForPageToLoad($this->getTimeoutMsec());
464 $this->waitForText('crm-notification-container', "One matching contact was found. You can View or Edit the existing contact.");
465 $this->click("_qf_Contact_upload_duplicate");
466 $this->waitForPageToLoad($this->getTimeoutMsec());
467 $this->waitForText('crm-notification-container', "Contact Saved");
468
469 // Find and Merge Contacts with Supervised Rule
470 $this->openCiviPage("contact/dedupefind", "reset=1&rgid=1&action=renew");
471
472 // Select the contacts to be merged
473 $this->select("name=option51_length", "value=100");
474 $this->waitForElementPresent("xpath=//table[@class='pagerDisplay dataTable no-footer']/tbody//tr/td[1]/a[text()='$firstName1 $lastName1']/../../td[2]/a[text()='$firstName1 $lastName1']");
475 $this->click("xpath=//table[@class='pagerDisplay dataTable no-footer']/tbody//tr/td[1]/a[text()='$firstName1 $lastName1']/../../td[2]/a[text()='$firstName1 $lastName1']/../../td[4]/a[text()='merge']");
476 $this->waitForElementPresent('_qf_Merge_cancel-bottom');
477 $this->clickLink("css=div.crm-contact-merge-form-block div.action-link a", "xpath=//form[@id='Merge']/div[2]/table/tbody/tr[4]/td[4]/span[text()='(overwrite)']");
478 $this->waitForElementPresent("xpath=//form[@id='Merge']/div[2]/table/tbody/tr[3]/td[4]/span[text()='(add)']");
479 $this->waitForElementPresent("xpath=//form[@id='Merge']/div[2]/table/tbody/tr[4]/td[4]/span[text()='(overwrite)']");
480 $this->select('location_email_1_locTypeId', 'value=3');
481 $this->select('location_phone_1_locTypeId', 'value=1');
482 $this->assertFalse($this->isElementPresent("xpath=//form[@id='Merge']/div[2]/table/tbody/tr[2]/td[4]/span[text()='(overwrite)']"));
483 $this->assertFalse($this->isElementPresent("xpath=//form[@id='Merge']/div[2]/table/tbody/tr[4]/td[4]/span[text()='(overwrite)']"));
484 $this->assertTrue($this->isElementPresent("xpath=//form[@id='Merge']/div[2]/table/tbody/tr[3]/td[4]/span[text()='(add)']"));
485 $this->waitForElementPresent('_qf_Merge_cancel-bottom');
486
487 $this->check("move_location_email_1");
488 $this->check("move_location_phone_1");
489 $this->click("_qf_Merge_next-bottom");
490 $this->waitForPageToLoad($this->getTimeoutMsec());
491
492 $this->assertTrue($this->isTextPresent('Contacts Merged'));
493 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[2]/div[1][contains(text(), 'Home')]"));
494 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[2]/div[2]/a[contains(text(), '{$firstName1}.{$lastName1}@example.com')]"));
495 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[3]/div[1][contains(text(), 'Main')]"));
496 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[3]/div[2]/a[contains(text(), '{$firstName1}.{$lastName1}@example.com')]"));
497 $this->assertTrue($this->isElementPresent("xpath=//div[@id='phone-block']/div/div/div[2]/div[1][contains(text(), 'Billing')]"));
498 $this->assertTrue($this->isElementPresent("xpath=//div[@id='phone-block']/div/div/div[2]/div[2][contains(text(), '9876543120')]"));
499 $this->assertTrue($this->isElementPresent("xpath=//div[@id='phone-block']/div/div/div[3]/div[1][contains(text(), 'Home')]"));
500 $this->assertTrue($this->isElementPresent("xpath=//div[@id='phone-block']/div/div/div[3]/div[2][contains(text(), '9876543210')]"));
501 }
502
503 public function testBatchMerge() {
504 $this->webtestLogin();
505
506 // add contact1 and its duplicate
507 //first name
508 $firstName = "Kerry" . substr(sha1(rand()), 0, 7);
509 //last name
510 $lastName = "King" . substr(sha1(rand()), 0, 7);
511 $this->_createContacts($firstName, $lastName);
512
513 //add contact2 and its duplicate
514 //These are the contacts with conflicts in communication preference.these contacts will be skipped during merge.
515 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
516
517 //fill in first name
518 $firstName1 = "Kurt" . substr(sha1(rand()), 0, 7);
519 $this->type('first_name', $firstName1);
520
521 //fill in last name
522 $lastName1 = "Cobain" . substr(sha1(rand()), 0, 7);
523 $this->type('last_name', $lastName1);
524
525 //fill in email id
526 $this->type('email_1_email', "{$firstName1}.{$lastName1}@example.com");
527
528 //fill in billing email id
529 $this->click('addEmail');
530 $this->waitForElementPresent('email_2_email');
531 $this->type('email_2_email', "$firstName1.$lastName1@billing.com");
532 $this->select('email_2_location_type_id', 'value=5');
533
534 //fill in home phone no
535 $this->type('phone_1_phone', "9876543210");
536
537 //fill in billing phone id
538 $this->click('addPhone');
539 $this->waitForElementPresent('phone_2_phone');
540 $this->type('phone_2_phone', "9876543120");
541 $this->select('phone_2_location_type_id', 'value=5');
542
543 //select communication preference
544 $this->check("privacy[do_not_phone]");
545
546 //Clicking save.
547 $this->click("_qf_Contact_upload_view");
548 $this->waitForPageToLoad($this->getTimeoutMsec());
549 $this->waitForText('crm-notification-container', "Contact Saved");
550
551 //duplicate of contact2.
552 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
553
554 //fill in first name
555 $this->type("first_name", $firstName1);
556
557 //fill in last name
558 $this->type("last_name", $lastName1);
559
560 //fill in email
561 $this->type("email_1_email", "{$firstName1}.{$lastName1}@example.com");
562
563 //fill in home phone no
564 $this->type('phone_1_phone', "9876543211");
565
566 //select communication preference
567 $this->check("preferred_communication_method[1]");
568
569 // Clicking save.
570 $this->click("_qf_Contact_refresh_dedupe");
571 $this->waitForPageToLoad($this->getTimeoutMsec());
572
573 $this->waitForText('crm-notification-container', "One matching contact was found. You can View or Edit the existing contact.");
574 $this->click("_qf_Contact_upload_duplicate");
575 $this->waitForPageToLoad($this->getTimeoutMsec());
576 $this->waitForText('crm-notification-container', "Contact Saved");
577
578 // add contact3 and its duplicate
579 //fill in first name
580 $firstName2 = "David" . substr(sha1(rand()), 0, 7);
581 //fill in last name
582 $lastName2 = "Gilmour" . substr(sha1(rand()), 0, 7);
583 $this->_createContacts($firstName2, $lastName2);
584
585 // add contact4 and its duplicate
586 //fill in first name
587 $firstName3 = "Dave" . substr(sha1(rand()), 0, 7);
588 //fill in last name
589 $lastName3 = "Mustaine" . substr(sha1(rand()), 0, 7);
590 $this->_createContacts($firstName3, $lastName3);
591
592 // Find and Merge Contacts with Supervised Rule
593 $this->openCiviPage("contact/dedupefind", "reset=1&rgid=1&action=renew", "css=#DedupeFind table.pagerDisplay tbody tr");
594
595 $this->select("name=option51_length", "value=100");
596 $totalContacts = $this->getXpathCount("//table[@class='pagerDisplay']/tbody/tr");
597 $this->click("//form[@id='DedupeFind']//a/span[contains(text(),'Batch Merge Duplicates')]");
598
599 // Check confirmation alert.
600 $this->assertTrue(
601 (bool) preg_match("/^This will run the batch merge process on the listed duplicates. The operation will run in safe mode - only records with no direct data conflicts will be merged. Click OK to proceed if you are sure you wish to run this operation./",
602 $this->getConfirmation()
603 )
604 );
605 $this->chooseOkOnNextConfirmation();
606 $this->waitForPageToLoad($this->getTimeoutMsec());
607 $this->waitForElementPresent('civicrm-footer');
608 $this->waitForText('crm-notification-container', "safe mode");
609
610 // If we are still on the dedupe table page, count unmerged contacts
611 if ($this->isElementPresent("//table[@class='pagerDisplay']")) {
612 // Wait for datatable to load
613 $this->waitForElementPresent("//table[@class='pagerDisplay']/tbody/tr");
614 $unMergedContacts = $this->getXpathCount("//table[@class='pagerDisplay']/tbody/tr");
615 }
616 else {
617 $unMergedContacts = 0;
618 }
619
620 $mergedContacts = $totalContacts - $unMergedContacts;
621
622 //check the existence of merged contacts
623 $contactEmails = array(
624 1 => "{$firstName}.{$lastName}@example.com",
625 2 => "{$firstName2}.{$lastName2}@example.com",
626 3 => "{$firstName3}.{$lastName3}@example.com",
627 );
628
629 foreach ($contactEmails as $key => $value) {
630 $this->click('sort_name_navigation');
631 $this->type('css=input#sort_name_navigation', $value);
632 $this->typeKeys('css=input#sort_name_navigation', $value);
633 // Wait for result list.
634 $this->waitForElementPresent("css=ul.ui-autocomplete li.ui-menu-item");
635
636 // Visit contact summary page.
637 $this->clickLink("css=ul.ui-autocomplete li.ui-menu-item", 'civicrm-footer');
638 }
639 }
640
641 /**
642 * Helper FN
643 * @param null $firstName
644 * @param null $lastName
645 * @param null $organizationName
646 * @param string $contactType
647 * @return array
648 */
649 public function _createContacts($firstName = NULL, $lastName = NULL, $organizationName = NULL, $contactType = 'Individual') {
650 if ($contactType == 'Individual') {
651 // add contact
652 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
653 //fill in first name
654 $this->type('first_name', $firstName);
655
656 //fill in last name
657 $this->type('last_name', $lastName);
658
659 //fill in email id
660 $this->type('email_1_email', "{$firstName}.{$lastName}@example.com");
661
662 //fill in billing email id
663 $this->click('addEmail');
664 $this->waitForElementPresent('email_2_email');
665 $this->type('email_2_email', "$firstName.$lastName@billing.com");
666 $this->select('email_2_location_type_id', 'value=5');
667
668 // Clicking save.
669 $this->click("_qf_Contact_upload_view");
670 $this->waitForPageToLoad($this->getTimeoutMsec());
671 $this->waitForText('crm-notification-container', "Contact Saved");
672
673 //duplicate of above contact.
674 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
675
676 //fill in first name
677 $this->type("first_name", $firstName);
678
679 //fill in last name
680 $this->type("last_name", $lastName);
681
682 //fill in email
683 $this->type("email_1_email", "{$firstName}.{$lastName}@example.com");
684
685 // Clicking save.
686 $this->click("_qf_Contact_refresh_dedupe");
687 $this->waitForPageToLoad($this->getTimeoutMsec());
688
689 $this->waitForText('crm-notification-container', "One matching contact was found. You can View or Edit the existing contact.");
690 $this->click("_qf_Contact_upload_duplicate");
691 $this->waitForPageToLoad($this->getTimeoutMsec());
692 $this->waitForText('crm-notification-container', "Contact Saved");
693 }
694 elseif ($contactType == 'Organization') {
695 // add contact
696 $this->openCiviPage("contact/add", "reset=1&ct=Organization");
697 //fill in Organization name
698 $this->type('organization_name', $organizationName);
699
700 //fill in email id
701 $this->type('email_1_email', "{$organizationName}@org.com");
702 // Clicking save.
703 $this->click("_qf_Contact_upload_view-bottom");
704 $this->waitForPageToLoad($this->getTimeoutMsec());
705 $this->waitForText('crm-notification-container', "Contact Saved");
706 $mainId = explode("CiviCRM ID:", trim($this->getText("xpath=//div[@id='crm-record-log']/span[@class='col1']")));
707 $mainId = trim($mainId[1]);
708
709 //Duplicate of above contact.
710 $this->openCiviPage("contact/add", "reset=1&ct=Organization");
711
712 //fill in Organization name
713 $this->type('organization_name', $organizationName);
714
715 //fill in email id
716 $this->type('email_1_email', "{$organizationName}@org.com");
717
718 // Clicking save.
719 $this->click("_qf_Contact_upload_view-bottom");
720 $this->waitForPageToLoad($this->getTimeoutMsec());
721
722 $this->waitForText('crm-notification-container', "One matching contact was found. You can View or Edit the existing contact.");
723 $this->click("_qf_Contact_upload_duplicate");
724 $this->waitForPageToLoad($this->getTimeoutMsec());
725 $this->waitForText('crm-notification-container', "Contact Saved");
726 $duplicateId = explode("CiviCRM ID:", trim($this->getText("xpath=//div[@id='crm-record-log']/span[@class='col1']")));
727 $duplicateId = trim($duplicateId[1]);
728
729 return array(
730 'mainId' => $mainId,
731 'duplicateId' => $duplicateId,
732 );
733 }
734 }
735
736 /**
737 * Helper FN
738 * to create new membership type
739 * @param $membershipOrganization
740 */
741 public function addMembershipType($membershipOrganization) {
742 $this->openCiviPage("admin/member/membershipType", "reset=1&action=browse");
743 $this->click("link=Add Membership Type");
744 $this->waitForElementPresent('_qf_MembershipType_cancel-bottom');
745
746 $this->type('name', "Membership Type $membershipOrganization");
747 $this->select2('member_of_contact_id', $membershipOrganization);
748
749 $this->type('minimum_fee', '1');
750 $this->select('financial_type_id', 'value=2');
751 $this->type('duration_interval', 1);
752 $this->select('duration_unit', "label=year");
753
754 $this->select('period_type', "label=Fixed");
755 $this->waitForElementPresent('fixed_period_rollover_day[d]');
756
757 // fixed period start set to April 1
758 $this->select('fixed_period_start_day[M]', 'value=4');
759 // rollover date set to Jan 31
760 $this->select('fixed_period_rollover_day[M]', 'value=1');
761
762 // Employer of relationship
763 $this->select('relationship_type_id', 'value=5_b_a');
764 $this->click('_qf_MembershipType_upload-bottom');
765 $this->waitForElementPresent('link=Add Membership Type');
766 $this->waitForText("crm-notification-container", "The membership type 'Membership Type $membershipOrganization' has been saved.");
767 }
768
769 /**
770 * Test for CRM-12695 fix
771 */
772 public function testMergeOrganizations() {
773 $this->webtestLogin();
774
775 // build organisation name
776 $orgnaizationName = 'org_' . substr(sha1(rand()), 0, 7);
777
778 $contactIds = array();
779 // create organization and its duplicate
780 $contactIds = $this->_createContacts(NULL, NULL, $orgnaizationName, 'Organization');
781
782 /*** Add Membership Type - start ***/
783 $this->addMembershipType($orgnaizationName);
784 /*** Add Membership Type - end ***/
785
786 //create a New Individual to be related to main organization
787 $firstName = substr(sha1(rand()), 0, 7);
788 $this->webtestAddContact($firstName, "Anderson", "$firstName@anderson.name");
789 $sortName = "Anderson, $firstName";
790
791 // go to main organization contact to add membership
792 $this->openCiviPage("contact/view", "reset=1&cid={$contactIds['mainId']}");
793 // click through to the membership view screen
794 $this->click("css=li#tab_member a");
795
796 $this->waitForElementPresent("link=Add Membership");
797 $this->click("link=Add Membership");
798
799 $this->waitForElementPresent("_qf_Membership_cancel-bottom");
800
801 // fill in Membership Organization and Type
802 $this->select("membership_type_id[0]", "label={$orgnaizationName}");
803 $this->waitForElementPresent("membership_type_id[1]");
804 // Wait for membership type select to reload
805 $this->waitForTextPresent("Membership Type $orgnaizationName");
806 $this->select("membership_type_id[1]", "label=Membership Type $orgnaizationName");
807
808 $sourceText = "Membership-Organization Duplicate Merge Webtest";
809 // fill in Source
810 $this->type("source", $sourceText);
811
812 // Let Join Date stay default
813
814 // fill in Start Date
815 $this->webtestFillDate('start_date');
816
817 // Clicking save.
818 $this->click("_qf_Membership_upload");
819 $this->waitForElementPresent('crm-notification-container');
820 // page was loaded
821 $this->waitForTextPresent($sourceText);
822 // Is status message correct?
823 $this->waitForText('crm-notification-container', "membership for $orgnaizationName has been added.");
824
825 // add relationship "Employer of"
826 // click through to the relationship view screen
827 $this->click("css=li#tab_rel a");
828
829 // wait for add Relationship link
830 $this->waitForElementPresent('link=Add Relationship');
831 $this->click('link=Add Relationship');
832
833 //choose the created relationship type
834 $this->waitForElementPresent("relationship_type_id");
835 $this->select('relationship_type_id', "value=5_b_a");
836
837 //fill in the individual
838 $this->select2('related_contact_id', $sortName, TRUE, FALSE);
839
840 $this->waitForElementPresent("_qf_Relationship_upload");
841
842 //fill in the relationship start date
843 //$this->webtestFillDate('start_date', '-2 year');
844 //$this->webtestFillDate('end_date', '+1 year');
845
846 $description = "Well here is some description !!!!";
847 $this->type("description", $description);
848
849 //save the relationship
850 $this->click("_qf_Relationship_upload");
851 $this->isTextPresent("Current Relationships");
852
853 //check the status message
854 $this->waitForText('crm-notification-container', "Relationship created.");
855
856 $this->waitForElementPresent("xpath=//table[@class='crm-contact-relationship-selector-current dataTable no-footer']/tbody//tr/td[9]/span/a[text()='View']");
857 $this->waitForElementPresent("xpath=//a[text()='$sortName']");
858 $this->click("xpath=//a[text()='$sortName']");
859 $this->waitForPageToLoad($this->getTimeoutMsec());
860
861 // Check if Membership for the individual is created
862 $this->waitForElementPresent("xpath=//li[@id='tab_member']/a/em");
863 $this->verifyText("xpath=//li[@id='tab_member']/a/em", 1);
864
865 //create a New Individual to be related to duplicate organization
866 $firstNameOther = substr(sha1(rand()), 0, 7);
867 $this->webtestAddContact($firstNameOther, "Harmison", "$firstNameOther@harmison.name");
868 $sortNameOther = "Harmison, $firstNameOther";
869
870 // go to main organization contact to add membership
871 $this->openCiviPage("contact/view", "reset=1&cid={$contactIds['duplicateId']}");
872
873 // add relationship "Employer of"
874 // click through to the relationship view screen
875 $this->click("css=li#tab_rel a");
876
877 // wait for add Relationship link
878 $this->waitForElementPresent('link=Add Relationship');
879 $this->click('link=Add Relationship');
880
881 //choose the created relationship type
882 $this->waitForElementPresent("relationship_type_id");
883 $this->select('relationship_type_id', "value=5_b_a");
884
885 //fill in the individual
886 $this->select2('related_contact_id', $sortNameOther, TRUE, FALSE);
887
888 $this->waitForElementPresent("_qf_Relationship_upload");
889
890 //fill in the relationship start date
891 $this->webtestFillDate('start_date', '-2 year');
892 $this->webtestFillDate('end_date', '+1 year');
893
894 $description = "Well here is some description !!!!";
895 $this->type("description", $description);
896
897 //save the relationship
898 //$this->click("_qf_Relationship_upload");
899 $this->click("_qf_Relationship_upload");
900 $this->isTextPresent("Current Relationships");
901
902 //check the status message
903 $this->isTextPresent("Relationship created.");
904
905 $this->waitForElementPresent("xpath=//table[@class='crm-contact-relationship-selector-current dataTable no-footer']/tbody//tr/td[9]/span/a[text()='View']");
906
907 // go directly to contact merge page.
908 $this->openCiviPage("contact/merge", "reset=1&cid={$contactIds['mainId']}&oid={$contactIds['duplicateId']}&action=update&rgid=2");
909
910 $this->waitForElementPresent('_qf_Merge_cancel-bottom');
911 $this->click('_qf_Merge_next-bottom');
912 $this->waitForPageToLoad($this->getTimeoutMsec());
913
914 // click through to the relationship view screen
915 $this->click("css=li#tab_rel a");
916
917 // wait for add Relationship link
918 $this->waitForElementPresent("xpath=//a[text()='$sortName']");
919 // go to duplicate organization's related contact
920 // to check if membership is added to that contact
921 $this->click("xpath=//a[text()='$sortName']");
922 $this->waitForPageToLoad($this->getTimeoutMsec());
923
924 // Check if Membership for the individual is created
925 $this->waitForElementPresent("xpath=//li[@id='tab_member']/a/em");
926 $this->verifyText("xpath=//li[@id='tab_member']/a/em", 0);
927 }
928
929 /**
930 * Test for CRM-15658 fix
931 */
932 public function testMergeEmailAndAddress() {
933 $this->webtestLogin();
934 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
935 $firstName = substr(sha1(rand()), 0, 7);
936 $this->type('first_name', $firstName);
937
938 //fill in last name
939 $lastName = substr(sha1(rand()), 0, 7);
940 $this->type('last_name', $lastName);
941
942 //fill in email id
943 $this->type('email_1_email', "{$firstName}.{$lastName}@example.com");
944
945 //address section
946 $this->click("addressBlock");
947 $this->waitForElementPresent("address_1_street_address");
948 $this->type("address_1_street_address", "902C El Camino Way SW");
949 $this->type("address_1_city", "Dumfries");
950 $this->type("address_1_postal_code", "1234");
951
952 // Clicking save.
953 $this->click("_qf_Contact_upload_view");
954 $this->waitForPageToLoad($this->getTimeoutMsec());
955 $this->waitForText('crm-notification-container', "Contact Saved");
956
957 //duplicate contact with same email id
958 $this->openCiviPage("contact/add", "reset=1&ct=Individual");
959 $firstName2 = substr(sha1(rand()), 0, 7);
960 $this->type('first_name', $firstName2);
961
962 //fill in last name
963 $lastName2 = substr(sha1(rand()), 0, 7);
964 $this->type('last_name', $lastName2);
965
966 //fill in email id
967 $this->type('email_1_email', "{$firstName}.{$lastName}@example.com");
968
969 //address section
970 $this->click("addressBlock");
971 $this->waitForElementPresent("address_1_street_address");
972 $this->type("address_1_street_address", "2782Y Dowlen Path W");
973 $this->type("address_1_city", "Birmingham");
974 $this->type("address_1_postal_code", "3456");
975
976 // Clicking save.
977 $this->click("_qf_Contact_upload_view");
978 $this->waitForPageToLoad($this->getTimeoutMsec());
979 $this->waitForText('crm-notification-container', "Contact Saved");
980
981 $this->openCiviPage("contact/dedupefind", "reset=1&action=update&rgid=4");
982 $this->click("//a/span[contains(text(),'Refresh Duplicates')]");
983 $this->assertTrue((bool) preg_match("/This will refresh the duplicates list. Click OK to proceed./", $this->getConfirmation()));
984 $this->chooseOkOnNextConfirmation();
985 $this->waitForPageToLoad($this->getTimeoutMsec());
986 $this->waitForElementPresent("xpath=//a[text()='$firstName $lastName']/../../td[4]/a[text()='merge']");
987 $this->clickLink("xpath=//a[text()='$firstName $lastName']/../../td[4]/a[text()='merge']");
988
989 //merge without specifying any criteria
990 $this->click("_qf_Merge_next-bottom");
991 $this->waitForPageToLoad($this->getTimeoutMsec());
992
993 $this->assertTrue($this->isTextPresent('Contacts Merged'));
994 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[2]/div[1][contains(text(), 'Home')]"));
995 $this->verifyElementNotPresent("xpath=//div[@id='email-block']/div/div/div[3]/div[1][contains(text(), 'Home')]");
996 $this->assertTrue($this->isElementPresent("xpath=//div[@id='email-block']/div/div/div[2]/div[2]/a[contains(text(), '{$firstName}.{$lastName}@example.com')]"));
997 $this->verifyElementNotPresent("xpath=//div[@id='email-block']/div/div/div[3]/div[2]/a[contains(text(), '{$firstName}.{$lastName}@example.com')]");
998
999 $this->assertElementContainsText('address-block-1', "902C El Camino Way SW");
1000 $this->assertElementContainsText('address-block-1', "Dumfries");
1001 $this->assertElementContainsText('address-block-1', "1234");
1002
1003 $this->assertElementNotContainsText("address-block-2", "2782Y Dowlen Path W");
1004 $this->assertElementNotContainsText("address-block-2", "Birmingham");
1005 $this->assertElementNotContainsText("address-block-2", "3456");
1006 }
1007
1008}