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