Merge pull request #4044 from totten/4.5-paratest-misc
[civicrm-core.git] / tests / phpunit / WebTest / Case / CaseCustomFieldsTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License along with this program; if not, contact CiviCRM LLC |
21 | at info[AT]civicrm[DOT]org. If you have questions about the |
22 | GNU Affero General Public License or the licensing of CiviCRM, |
23 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
24 +--------------------------------------------------------------------+
25 */
26
27 require_once 'CiviTest/CiviSeleniumTestCase.php';
28
29 /**
30 * Class WebTest_Case_CaseCustomFieldsTest
31 */
32 class WebTest_Case_CaseCustomFieldsTest extends CiviSeleniumTestCase {
33
34 protected function setUp() {
35 parent::setUp();
36 }
37
38 function testAddCase() {
39 $this->webtestLogin('admin');
40
41 // Enable CiviCase module if necessary
42 $this->enableComponents("CiviCase");
43
44 $customGrp1 = "CaseCustom_Data1_" . substr(sha1(rand()), 0, 7);
45
46 // create custom group1
47 $this->openCiviPage('admin/custom/group', 'reset=1');
48 $this->click("newCustomDataGroup");
49 $this->waitForPageToLoad($this->getTimeoutMsec());
50 $this->type("title", $customGrp1);
51 $this->select("extends[0]", "value=Case");
52 // Because it tends to cause problems, all uses of sleep() must be justified in comments
53 // Sleep should never be used for wait for anything to load from the server
54 // Justification for this instance: FIXME
55 sleep(1);
56 $this->select("extends_1", "value=2");
57 $this->click("_qf_Group_next-bottom");
58 $this->waitForPageToLoad($this->getTimeoutMsec());
59
60 // get custom group id
61 $customGrpId1 = $this->urlArg('gid');
62
63 $customId = $this->_testGetCustomFieldId($customGrpId1);
64 $cusId_1 = 'custom_' . $customId[0] . '_-1';
65 $cusId_2 = 'custom_' . $customId[1] . '_-1';
66 $cusId_3 = 'custom_' . $customId[2] . '_-1';
67
68 // let's give full CiviCase permissions.
69 $permission = array('edit-2-access-all-cases-and-activities', 'edit-2-access-my-cases-and-activities', 'edit-2-administer-civicase', 'edit-2-delete-in-civicase');
70 $this->changePermissions($permission);
71
72 // Log in as normal user
73 $this->webtestLogin();
74
75 // Go to reserved New Individual Profile to set value for logged in user's contact name (we'll need that later)
76 $this->openCiviPage('profile/edit', 'reset=1&gid=4', '_qf_Edit_next');
77 $testUserFirstName = "Testuserfirst";
78 $testUserLastName = "Testuserlast";
79 $this->type("first_name", $testUserFirstName);
80 $this->type("last_name", $testUserLastName);
81 $this->clickLink("_qf_Edit_next", "profilewrap4");
82
83 $this->openCiviPage('case/add', 'reset=1&action=add&atype=13&context=standalone', '_qf_Case_upload-bottom');
84
85 // Try submitting the form without creating or selecting a contact (test for CRM-7971)
86 $this->clickLink("_qf_Case_upload-bottom", "css=span.crm-error");
87
88 // Adding contact with randomized first name (so we can then select that contact when creating case)
89 // We're using pop-up New Contact dialog
90 $firstName = substr(sha1(rand()), 0, 7);
91 $lastName = "Fraser";
92 $contactName = "{$lastName}, {$firstName}";
93 $displayName = "{$firstName} {$lastName}";
94 $email = "{$lastName}.{$firstName}@example.org";
95 $custFname = "Mike" . substr(sha1(rand()), 0, 7);
96 $custMname = "Dav" . substr(sha1(rand()), 0, 7);
97 $custLname = "Krist" . substr(sha1(rand()), 0, 7);
98 $this->webtestNewDialogContact($firstName, $lastName, $email, $type = 4, "s2id_client_id");
99
100 // Fill in other form values. We'll use a case type which is included in CiviCase sample data / xml files.
101 $caseTypeLabel = "Adult Day Care Referral";
102
103 // activity types we expect for this case type
104 $activityTypes = array("ADC referral", "Follow up", "Medical evaluation", "Mental health evaluation");
105 $caseRoles = array("Senior Services Coordinator", "Health Services Coordinator", "Benefits Specialist", "Client");
106 $caseStatusLabel = "Ongoing";
107 $subject = "Safe daytime setting - senior female";
108 $this->select("medium_id", "value=1");
109 $location = "Main offices";
110 $this->type("activity_location", $location);
111 $details = "65 year old female needs safe location during the day for herself and her dog. She is in good health but somewhat disoriented.";
112 $this->fillRichTextField("activity_details", $details, 'CKEditor');
113 $this->type("activity_subject", $subject);
114
115 $this->select("case_type_id", "label={$caseTypeLabel}");
116 // Because it tends to cause problems, all uses of sleep() must be justified in comments
117 // Sleep should never be used for wait for anything to load from the server
118 // Justification for this instance: FIXME
119 sleep(3);
120 $this->select("status_id", "label={$caseStatusLabel}");
121
122 // Choose Case Start Date.
123 // Using helper webtestFillDate function.
124 $this->webtestFillDate('start_date', 'now');
125 $today = date('F jS, Y', strtotime('now'));
126
127 $this->type("duration", "20");
128 $this->type("{$cusId_1}", $custFname);
129 $this->type("{$cusId_2}", $custMname);
130 $this->type("{$cusId_3}", $custLname);
131 $this->clickLink("_qf_Case_upload-bottom", "_qf_CaseView_cancel-bottom");
132
133 // Is status message correct?
134 $this->assertTextPresent("Case opened successfully.", "Save successful status message didn't show up after saving!");
135 $this->click("_qf_CaseView_cancel-bottom");
136 $this->waitForPageToLoad($this->getTimeoutMsec());
137 $this->openCiviPage('case', 'reset=1', "xpath=//table[@class='caseSelector']/tbody//tr/td[2]/a[text()='{$contactName}']/../../td[8]/a[text()='Open Case']");
138 $this->click("xpath=//table[@class='caseSelector']/tbody//tr/td[2]/a[text()='{$contactName}']/../../td[8]/a[text()='Open Case']");
139 $this->waitForElementPresent("xpath=//span[@class='ui-button-icon-primary ui-icon ui-icon-closethick']");
140 // Because it tends to cause problems, all uses of sleep() must be justified in comments
141 // Sleep should never be used for wait for anything to load from the server
142 // Justification for this instance: FIXME
143 sleep(3);
144
145 $openCaseData = array(
146 "Client" => $displayName,
147 "Activity Type" => "Open Case",
148 "Subject" => $subject,
149 "Created By" => "{$testUserFirstName} {$testUserLastName}",
150 "Reported By" => "{$testUserFirstName} {$testUserLastName}",
151 "Medium" => "In Person",
152 "Location" => $location,
153 "Date and Time" => $today,
154 "Status" => "Completed",
155 "Priority" => "Normal",
156 );
157 $this->webtestVerifyTabularData($openCaseData);
158 $this->click("xpath=//span[@class='ui-button-icon-primary ui-icon ui-icon-closethick']");
159
160 // verify if custom data is present
161 $this->openCiviPage('case', 'reset=1');
162 $this->click("xpath=//table[@class='caseSelector']/tbody//tr/td[2]/a[text()='{$contactName}']/../../td[9]/span/a[text()='Manage']");
163 $this->waitForPageToLoad($this->getTimeoutMsec());
164 $this->click("css=#{$customGrp1} .crm-accordion-header");
165 $this->waitForElementPresent("css=#{$customGrp1} a.button");
166 $cusId_1 = 'custom_' . $customId[0] . '_1';
167 $cusId_2 = 'custom_' . $customId[1] . '_1';
168 $cusId_3 = 'custom_' . $customId[2] . '_1';
169 $this->click("css=#{$customGrp1} a.button");
170 // Because it tends to cause problems, all uses of sleep() must be justified in comments
171 // Sleep should never be used for wait for anything to load from the server
172 // Justification for this instance: FIXME
173 sleep(2);
174 $this->waitForElementPresent("{$cusId_1}");
175 $custFname = "Miky" . substr(sha1(rand()), 0, 7);
176 $custMname = "Davy" . substr(sha1(rand()), 0, 7);
177 $custLname = "Kristy" . substr(sha1(rand()), 0, 7);
178 $this->type("{$cusId_1}", $custFname);
179 $this->type("{$cusId_2}", $custMname);
180 $this->type("{$cusId_3}", $custLname);
181 $this->click("_qf_CustomData_upload");
182 // Because it tends to cause problems, all uses of sleep() must be justified in comments
183 // Sleep should never be used for wait for anything to load from the server
184 // Justification for this instance: FIXME
185 sleep(2);
186 $this->openCiviPage('case', 'reset=1');
187 $this->click("xpath=//table[@class='caseSelector']/tbody//tr/td[2]/a[text()='{$contactName}']/../../td[8]/a[text()='Change Custom Data']");
188 // Because it tends to cause problems, all uses of sleep() must be justified in comments
189 // Sleep should never be used for wait for anything to load from the server
190 // Justification for this instance: FIXME
191 sleep(3);
192 $openCaseChangeData = array(
193 "Client" => $displayName,
194 "Activity Type" => "Change Custom Data",
195 "Subject" => $customGrp1 . " : change data",
196 "Created By" => "{$testUserFirstName} {$testUserLastName}",
197 "Reported By" => "{$testUserFirstName} {$testUserLastName}",
198 "Date and Time" => $today,
199 "Status" => "Completed",
200 "Priority" => "Normal",
201 );
202 $this->webtestVerifyTabularData($openCaseChangeData);
203 $this->click("xpath=//span[@class='ui-button-icon-primary ui-icon ui-icon-closethick']");
204 // Because it tends to cause problems, all uses of sleep() must be justified in comments
205 // Sleep should never be used for wait for anything to load from the server
206 // Justification for this instance: FIXME
207 sleep(2);
208 $this->_testAdvansearchCaseData($customId, $custFname, $custMname, $custLname);
209 $this->_testDeleteCustomData($customGrpId1, $customId);
210 }
211
212 /**
213 * @param $validateStrings
214 * @param $activityTypes
215 */
216 function _testVerifyCaseSummary($validateStrings, $activityTypes) {
217 $this->assertStringsPresent($validateStrings);
218 foreach ($activityTypes as $aType) {
219 $this->assertText("activity_type_id", $aType);
220 }
221 $this->assertElementPresent("link=Assign to Another Client", "Assign to Another Client link is missing.");
222 $this->assertElementPresent("name=case_report_all", "Print Case Summary button is missing.");
223 }
224
225 /**
226 * @param $customGrpId1
227 * @param bool $noteRichEditor
228 *
229 * @return array
230 */
231 function _testGetCustomFieldId($customGrpId1, $noteRichEditor=FALSE) {
232 $customId = array();
233
234 if ($noteRichEditor) {
235 // Create a custom data to add in profile
236 $field1 = "Note_Textarea" . substr(sha1(rand()), 0, 7);
237 $field2 = "Note_Richtexteditor" . substr(sha1(rand()), 0, 7);
238
239 // add custom fields for group 1
240 $this->openCiviPage('admin/custom/group/field/add', array('reset' => 1, 'action' => 'add', 'gid' => $customGrpId1));
241 $this->type("label", $field1);
242 $this->select("data_type_0", "value=4");
243 $this->select("data_type_1", "value=TextArea");
244 $this->check("is_searchable");
245 $this->clickLink("_qf_Field_next_new-bottom");
246
247 $this->type("label", $field2);
248 $this->select("data_type_0", "value=4");
249 //$this->select("data_type_1", "value=TextArea");
250 $this->select("data_type_1", "value=RichTextEditor");
251 $this->check("is_searchable");
252 $this->clickLink("_qf_Field_next_new-bottom");
253
254 // get id of custom fields
255 $this->openCiviPage("admin/custom/group/field", array('reset' => 1, 'action' => 'browse', 'gid' => $customGrpId1));
256 $custom1 = explode('&id=', $this->getAttribute("xpath=//div[@id='field_page']//table/tbody//tr[1]/td[8]/span/a[text()='Edit Field']/@href"));
257 $custom1 = $custom1[1];
258 array_push($customId, $custom1);
259 $custom2 = explode('&id=', $this->getAttribute("xpath=//div[@id='field_page']//table/tbody//tr[2]/td[8]/span/a[text()='Edit Field']/@href"));
260 $custom2 = $custom2[1];
261 array_push($customId, $custom2);
262 }
263 else {
264 // Create a custom data to add in profile
265 $field1 = "Fname" . substr(sha1(rand()), 0, 7);
266 $field2 = "Mname" . substr(sha1(rand()), 0, 7);
267 $field3 = "Lname" . substr(sha1(rand()), 0, 7);
268
269 // add custom fields for group 1
270 $this->openCiviPage('admin/custom/group/field/add', array('reset' => 1, 'action' => 'add', 'gid' => $customGrpId1));
271 $this->type("label", $field1);
272 $this->check("is_searchable");
273 $this->click("_qf_Field_next_new-bottom");
274 $this->waitForPageToLoad($this->getTimeoutMsec());
275
276 $this->type("label", $field2);
277 $this->check("is_searchable");
278 $this->click("_qf_Field_next_new-bottom");
279 $this->waitForPageToLoad($this->getTimeoutMsec());
280
281 $this->type("label", $field3);
282 $this->check("is_searchable");
283 $this->click("_qf_Field_done-bottom");
284 $this->waitForPageToLoad($this->getTimeoutMsec());
285
286 // get id of custom fields
287 $this->openCiviPage("admin/custom/group/field", array('reset' => 1, 'action' => 'browse', 'gid' => $customGrpId1));
288 $custom1 = explode('&id=', $this->getAttribute("xpath=//div[@id='field_page']//table/tbody//tr[1]/td[8]/span/a[text()='Edit Field']/@href"));
289 $custom1 = $custom1[1];
290 array_push($customId, $custom1);
291 $custom2 = explode('&id=', $this->getAttribute("xpath=//div[@id='field_page']//table/tbody//tr[2]/td[8]/span/a[text()='Edit Field']/@href"));
292 $custom2 = $custom2[1];
293 array_push($customId, $custom2);
294 $custom3 = explode('&id=', $this->getAttribute("xpath=//div[@id='field_page']//table/tbody//tr[3]/td[8]/span/a[text()='Edit Field']/@href"));
295 $custom3 = $custom3[1];
296 array_push($customId, $custom3);
297 }
298
299 return $customId;
300 }
301
302 /**
303 * @param $customGrpId1
304 * @param $customId
305 */
306 function _testDeleteCustomData($customGrpId1, $customId) {
307 // delete all custom data
308 foreach ($customId as $cKey => $cValue) {
309 $this->openCiviPage("admin/custom/group/field", array('action' => 'delete', 'reset' => '1', 'gid' => $customGrpId1, 'id' => $cValue));
310 $this->clickLink("_qf_DeleteField_next-bottom");
311 }
312
313 // delete custom group
314 $this->openCiviPage("admin/custom/group", "action=delete&reset=1&id=" . $customGrpId1);
315 $this->clickLink("_qf_DeleteGroup_next-bottom");
316 }
317
318 /**
319 * CRM-12812
320 */
321 function testCaseCustomNoteRichEditor() {
322 $this->webtestLogin('admin');
323
324 //setting ckeditor as WYSIWYG
325 $this->openCiviPage('admin/setting/preferences/display', 'reset=1', '_qf_Display_next-bottom');
326 $this->select('editor_id', 'CKEditor');
327 $this->clickLink('_qf_Display_next-bottom');
328
329 // Enable CiviCase module if necessary
330 $this->enableComponents("CiviCase");
331
332 $customGrp1 = "CaseCustom_Data1_" . substr(sha1(rand()), 0, 7);
333
334 // create custom group1
335 $this->openCiviPage('admin/custom/group', 'reset=1');
336 $this->clickLink("newCustomDataGroup");
337 $this->type("title", $customGrp1);
338 $this->select("extends[0]", "value=Case");
339 $this->select("extends_1", "value=2");
340 $this->clickLink("_qf_Group_next-bottom");
341
342 // get custom group id
343 $customGrpId1 = $this->urlArg('gid');
344
345 $customId = $this->_testGetCustomFieldId($customGrpId1, TRUE);
346 $cusId_1 = 'custom_' . $customId[0] . '_-1';
347 $cusId_2 = 'custom_' . $customId[1] . '_-1';
348
349 // let's give full CiviCase permissions.
350 $permission = array('edit-2-access-all-cases-and-activities', 'edit-2-access-my-cases-and-activities', 'edit-2-administer-civicase', 'edit-2-delete-in-civicase');
351 $this->changePermissions($permission);
352
353 // Log in as normal user
354 $this->webtestLogin();
355
356 // Go to reserved New Individual Profile to set value for logged in user's contact name (we'll need that later)
357 $this->openCiviPage('profile/edit', 'reset=1&gid=4', '_qf_Edit_next');
358 $testUserFirstName = "Testuserfirst";
359 $testUserLastName = "Testuserlast";
360 $this->type("first_name", $testUserFirstName);
361 $this->type("last_name", $testUserLastName);
362 $this->clickLink("_qf_Edit_next", "profilewrap4");
363
364 $this->openCiviPage('case/add', 'reset=1&action=add&atype=13&context=standalone', '_qf_Case_upload-bottom');
365
366 // Try submitting the form without creating or selecting a contact (test for CRM-7971)
367 $this->clickLink("_qf_Case_upload-bottom", "css=span.crm-error");
368
369 // Adding contact with randomized first name (so we can then select that contact when creating case)
370 // We're using pop-up New Contact dialog
371 $firstName = substr(sha1(rand()), 0, 7);
372 $lastName = "Fraser";
373 $contactName = "{$lastName}, {$firstName}";
374 $displayName = "{$firstName} {$lastName}";
375 $email = "{$lastName}.{$firstName}@example.org";
376 $custFname = "Mike" . substr(sha1(rand()), 0, 7);
377 $custLname = "Krist" . substr(sha1(rand()), 0, 7);
378 $this->webtestNewDialogContact($firstName, $lastName, $email, $type = 4, "s2id_client_id");
379
380 // Fill in other form values. We'll use a case type which is included in CiviCase sample data / xml files.
381 $caseTypeLabel = "Adult Day Care Referral";
382
383 // activity types we expect for this case type
384 $activityTypes = array("ADC referral", "Follow up", "Medical evaluation", "Mental health evaluation");
385 $caseRoles = array("Senior Services Coordinator", "Health Services Coordinator", "Benefits Specialist", "Client");
386 $caseStatusLabel = "Ongoing";
387 $subject = "Safe daytime setting - senior female";
388 $this->select("medium_id", "value=1");
389 $location = "Main offices";
390 $this->type("activity_location", $location);
391 $details = "65 year old female needs safe location during the day for herself and her dog. She is in good health but somewhat disoriented.";
392 $this->fillRichTextField("activity_details", $details, 'CKEditor');
393 $this->type("activity_subject", $subject);
394
395 $this->select("case_type_id", "label={$caseTypeLabel}");
396 $this->select("status_id", "label={$caseStatusLabel}");
397
398 // Choose Case Start Date.
399 // Using helper webtestFillDate function.
400 $this->webtestFillDate('start_date', 'now');
401 $today = date('F jS, Y', strtotime('now'));
402
403 $this->type("duration", "20");
404 $this->type("{$cusId_1}", $custFname);
405 $this->type("{$cusId_2}", $custLname);
406 $this->clickLink("_qf_Case_upload-bottom", "_qf_CaseView_cancel-bottom");
407
408 // Is status message correct?
409 $this->assertTextPresent("Case opened successfully.", "Save successful status message didn't show up after saving!");
410 $this->clickLink("_qf_CaseView_cancel-bottom");
411
412 $this->openCiviPage('case', 'reset=1');
413 $this->waitForElementPresent("xpath=//table[@class='caseSelector']/tbody//tr/td[2]/a[text()='{$contactName}']/../../td[8]/a[text()='Open Case']");
414
415 $this->click("xpath=//table[@class='caseSelector']/tbody//tr/td[2]/a[text()='{$contactName}']/../../td[8]/a[text()='Open Case']");
416
417 $openCaseData = array(
418 "Client" => $displayName,
419 "Activity Type" => "Open Case",
420 "Subject" => $subject,
421 "Created By" => "{$testUserFirstName} {$testUserLastName}",
422 "Reported By" => "{$testUserFirstName} {$testUserLastName}",
423 "Medium" => "In Person",
424 "Location" => $location,
425 "Date and Time" => $today,
426 "Status" => "Completed",
427 "Priority" => "Normal",
428 );
429 // wait for elements to load
430 foreach ($openCaseData as $label => $value) {
431 $this->waitForElementPresent("xpath=//table/tbody/tr/td[text()='{$label}']/following-sibling::td");
432 }
433 $this->webtestVerifyTabularData($openCaseData);
434
435 // verify if custom data is present
436 $this->openCiviPage('case', 'reset=1');
437 $this->clickLink("xpath=//table[@class='caseSelector']/tbody//tr/td[2]/a[text()='{$contactName}']/../../td[9]/span/a[text()='Manage']", "css=#{$customGrp1} .crm-accordion-header");
438
439 $this->click("css=#{$customGrp1} .crm-accordion-header");
440
441 $cusId_1 = 'custom_' . $customId[0] . '_1';
442 $cusId_2 = 'custom_' . $customId[1] . '_1';
443 $this->clickLink("css=#{$customGrp1} a.button", '_qf_CustomData_cancel-bottom', FALSE);
444
445 $this->assertElementContainsText("xpath=//span[@class='ui-dialog-title']", "Edit $customGrp1");
446
447 $custFname = "Miky" . substr(sha1(rand()), 0, 7);
448 $custLname = "Kristy" . substr(sha1(rand()), 0, 7);
449 $this->type("{$cusId_1}", $custFname);
450
451 // Wait for rich text editor element
452 $this->waitForElementPresent("css=div#cke_{$cusId_2}");
453
454 $this->fillRichTextField("{$cusId_2}", $custLname, 'CKEditor');
455 $this->click("_qf_CustomData_upload");
456 // delete custom data
457 $this->_testDeleteCustomData($customGrpId1, $customId);
458 }
459
460 /**
461 * @param $customId
462 * @param $custFname
463 * @param $custMname
464 * @param $custLname
465 */
466 function _testAdvansearchCaseData($customId, $custFname, $custMname, $custLname) {
467 // search casecontact
468 $this->openCiviPage('contact/search/advanced', 'reset=1', '_qf_Advanced_refresh');
469 $this->click("CiviCase");
470 $this->waitForElementPresent('case_from_relative');
471 $cusId_1 = 'custom_' . $customId[0];
472 $cusId_2 = 'custom_' . $customId[1];
473 $cusId_3 = 'custom_' . $customId[2];
474 $this->type("{$cusId_1}", $custFname);
475 $this->type("{$cusId_2}", $custMname);
476 $this->type("{$cusId_3}", $custLname);
477 $this->click("_qf_Advanced_refresh");
478 $this->waitForPageToLoad($this->getTimeoutMsec());
479 $this->assertElementContainsText('crm-container', '1 Contact');
480 }
481 }
482