Merge pull request #3179 from webpartners/master
[civicrm-core.git] / tests / phpunit / WebTest / Contact / InlineFieldsEditTest.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_Contact_InlineFieldsEditTest
31 */
32 class WebTest_Contact_InlineFieldsEditTest extends CiviSeleniumTestCase {
33
34 protected function setUp() {
35 parent::setUp();
36 }
37
38 function testAddAndEditField() {
39 $this->webtestLogin();
40
41 // Add a contact
42 $firstName = 'WebTest' . substr(sha1(rand()), 0, 7);
43 $lastName = 'InlineFieldsEdit' . substr(sha1(rand()), 0, 7);
44 $this->webtestAddContact($firstName, $lastName);
45 $this->waitForElementPresent('css=.crm-inline-edit-container.crm-edit-ready');
46
47 // Set Communication Prefs
48 $this->inlineEdit('crm-communication-pref-content', array(
49 'css=#email_greeting_display a' => TRUE,
50 'privacy_do_not_email' => 1,
51 'preferred_communication_method_1' => 1,
52 'preferred_communication_method_2' => 1,
53 ), 'keep_open');
54 $this->waitForElementPresent('css=.icon.privacy-flag.do-not-email');
55 $this->inlineEdit('crm-communication-pref-content', array(
56 'privacy_do_not_phone' => 1,
57 'privacy_do_not_email' => 0,
58 'preferred_communication_method_1' => 0,
59 'preferred_communication_method_2' => 0,
60 ), 'keep_open');
61 $this->waitForElementPresent('css=.icon.privacy-flag.do-not-phone');
62 $this->inlineEdit('crm-communication-pref-content', array(
63 'email_greeting_custom' => 'Hey You!',
64 ), 'no_open');
65 $this->assertElementNotPresent('css=.icon.privacy-flag.do-not-email');
66
67 // Custom data
68 $this->click('css=div.crm-custom-set-block-1 .collapsible-title');
69 // Because it tends to cause problems, all uses of sleep() must be justified in comments
70 // NOTE: Sleep should never be used for wait for anything to load from the server
71 // Justification for this instance: opening an accordion is predictable
72 sleep(1);
73 $this->openInlineForm('custom-set-content-1');
74 $dateFieldId = $this->getAttribute("xpath=//div[@class='crm-accordion-body']/table/tbody/tr[3]/td[@class='html-adjust']/input@id");
75 $this->inlineEdit('custom-set-content-1', array(
76 'CIVICRM_QFID_Edu_2' => 1,
77 "//div[@class='crm-accordion-body']/table/tbody/tr[2]/td[@class='html-adjust']/select" => array('Single'),
78 $dateFieldId => 'date: now - 10 years',
79 ));
80
81 // Edit contact info
82 $params = array(
83 'job_title' => 'jobtest123',
84 'nick_name' => 'nicktest123',
85 'contact_source' => 'sourcetest123',
86 );
87 $this->inlineEdit('crm-contactinfo-content', $params, 'keep_open');
88 // Clear fields and verify they are deleted
89 $this->inlineEdit('crm-contactinfo-content', array(
90 'job_title' => '',
91 'nick_name' => '',
92 'contact_source' => '',
93 ), 'no_open');
94 foreach ($params as $str) {
95 $this->assertElementNotContainsText('crm-contactinfo-content', $str);
96 }
97
98 // Add a phone
99 $this->inlineEdit('crm-phone-content', array(
100 'phone_1_phone' => '123-456-7890',
101 'phone_1_phone_ext' => '101',
102 'phone_1_location_type_id' => array('Work'),
103 'phone_1_phone_type_id' => array('Mobile'),
104 ));
105
106 // Add im
107 $this->inlineEdit('crm-im-content', array(
108 'im_1_name' => 'testmeout',
109 'im_1_location_type_id' => array('Work'),
110 'im_1_provider_id' => array('Jabber'),
111 ));
112
113 // Add an address - should default to home
114 $this->inlineEdit('address-block-1', array(
115 'address_1_street_address' => '123 St',
116 'address_1_city' => 'San Somewhere',
117 ), 'keep_open');
118 // Try to uncheck is_primary, we should get an error and it should stay checked
119 $this->click('address[1][is_primary]');
120 $this->waitForElementPresent('css=#crm-notification-container .error.ui-notify-message');
121 $this->assertChecked('address[1][is_primary]');
122 // Try to open another form while this one is still open - nothing should happen
123 $this->waitForElementPresent('address-block-2');
124 $this->openInlineForm('address-block-2', FALSE);
125 $this->assertElementNotPresent('css#address-block-2.form');
126 // Update address
127 $this->inlineEdit('address-block-1', array(
128 'address_1_street_address' => '321 Other St',
129 'address_1_city' => 'Sans Nowhere',
130 'address_1_postal_code' => '99999',
131 'address_1_postal_code_suffix' => '99',
132 ), 'no_open');
133 // Another address with same location type as first - should give an error
134 $this->inlineEdit('address-block-2', array(
135 'address_2_street_address' => '123 Foo',
136 'address_2_city' => 'San Anywhere',
137 'address_2_location_type_id' => array('Home'),
138 ), 'error');
139 $this->waitForTextPresent('required');
140 // Share address with a new org
141 $this->click('address[2][use_shared_address]');
142 $this->select('profiles_2', 'label=New Organization');
143 $orgName = 'Test Org Inline' . substr(sha1(rand()), 0, 7);
144 $this->waitForElementPresent('css=#contact-dialog-2 form');
145 $this->type('organization_name', $orgName);
146 $this->type('street_address-1', 'Test Org Street');
147 $this->type('city-1', 'Test Org City');
148 $this->clickLink('_qf_Edit_next', 'selected_shared_address-2', FALSE);
149 $this->waitForTextPresent('Test Org Street');
150 $this->inlineEdit('address-block-2', array(
151 'address_2_location_type_id' => array('Work'),
152 ), 'no_open');
153 $this->waitForElementPresent('css=.crm-content.crm-contact-current_employer');
154 $this->assertElementContainsText('crm-contactinfo-content', $orgName);
155 $this->assertElementContainsText('address-block-2', $orgName);
156 $this->assertElementContainsText('address-block-2', 'Work Address');
157
158 // Edit demographics
159 $this->inlineEdit('crm-demographic-content', array(
160 'civicrm_gender_Female_1' => 1,
161 'is_deceased' => 1,
162 'birth_date' => 'date: Jan 1 1970',
163 ), 'no_open');
164 $this->assertElementContainsText('crm-demographic-content', 'Female');
165 $this->assertElementContainsText('crm-demographic-content', 'Contact is Deceased');
166 $this->inlineEdit('crm-demographic-content', array(
167 'is_deceased' => 0,
168 ), 'no_open');
169 $age = date('Y') - 1970;
170 $this->assertElementContainsText('crm-demographic-content', "$age years");
171
172 // Add emails
173 $this->inlineEdit('crm-email-content', array(
174 'css=#crm-email-content a.add-more-inline' => TRUE,
175 'email_1_email' => 'test1@monkey.com',
176 'email_2_email' => 'test2@monkey.com',
177 ), 'keep_open');
178
179 // Try an invalid email
180 $this->inlineEdit('crm-email-content', array(
181 'email_2_email' => 'invalid@monkey,com',
182 ), 'error');
183
184 // Delete email
185 $this->inlineEdit('crm-email-content', array(
186 'css=#Email_Block_2 a.crm-delete-inline' => TRUE,
187 ));
188 $this->assertElementNotContainsText('crm-email-content', 'test2@monkey.com');
189
190 // Add website with invalid url
191 $this->inlineEdit('crm-website-content', array(
192 'css=#crm-website-content a.add-more-inline' => TRUE,
193 'website_1_url' => 'http://example.com',
194 'website_2_url' => 'something.wrong',
195 ), 'error');
196
197 // Correct invalid url and add a third website
198 $this->inlineEdit('crm-website-content', array(
199 'css=#crm-website-content a.add-more-inline' => TRUE,
200 'website_2_url' => 'http://example.net',
201 'website_2_website_type_id' => array('Work'),
202 'website_3_url' => 'http://example.biz',
203 'website_3_website_type_id' => array('Main'),
204 ), 'keep_open');
205
206 // Delete website
207 $this->inlineEdit('crm-website-content', array(
208 'css=#Website_Block_2 a.crm-delete-inline' => TRUE,
209 ));
210 $this->assertElementNotContainsText('crm-website-content', 'http://example.net');
211
212 // Change contact name
213 $this->inlineEdit('crm-contactname-content', array(
214 'first_name' => 'NewName',
215 'prefix_id' => array('Mr.'),
216 ));
217 // Page title should be updated with new name
218 $this->assertElementContainsText('css=title', "Mr. NewName $lastName");
219 }
220
221 /**
222 * Click on an inline-edit block and wait for it to open
223 *
224 * @param $block string selector
225 * @param bool $wait
226 */
227 private function openInlineForm($block, $wait = TRUE) {
228 $this->mouseDown($block);
229 $this->mouseUp($block);
230 if ($wait) {
231 $this->waitForElementPresent("css=#$block .crm-container-snippet form");
232 }
233 }
234
235 /**
236 * Enter values in an inline edit block and save
237 *
238 * @param $block string selector
239 * @param $params array
240 * @param \str|string $valid str: submit behavior
241 * 'error' if we are expecting a form validation error,
242 * 're_open' (default) after saving, opens the form and validate inputs
243 * 'keep_open' same as 're_open' but doesn't automatically cancel at the end
244 * 'no_open' do not re-open to validate
245 */
246 private function inlineEdit($block, $params, $valid = 're_open') {
247 $this->openInlineForm($block);
248 foreach ($params as $item => $val) {
249 switch(gettype($val)) {
250 case 'boolean':
251 $this->click($item);
252 break;
253 case 'string':
254 if (substr($val, 0, 5) == 'date:') {
255 $this->webtestFillDate($item, trim(substr($val, 5)));
256 }
257 else {
258 $this->type($item, $val);
259 }
260 break;
261 case 'integer':
262 $method = $val ? 'check' : 'uncheck';
263 $this->$method($item);
264 break;
265 case 'array':
266 foreach ($val as $option) {
267 $selector = is_int($option) ? 'value' : 'label';
268 $this->select($item, "$selector=$option");
269 }
270 break;
271 }
272 }
273 $this->click("css=#$block input.form-submit");
274 if ($valid !== 'error') {
275 // Verify the form saved
276 $this->waitForElementPresent("css=#$block > .crm-inline-block-content");
277 $validate = FALSE;
278 foreach ($params as $val) {
279 if (is_string($val) && $val && substr($val, 0, 5) != 'date:') {
280 $this->assertElementContainsText($block, $val);
281 $validate = TRUE;
282 }
283 elseif (!is_bool($val)) {
284 $validate = TRUE;
285 }
286 if (is_array($val)) {
287 foreach ($val as $option) {
288 if (!is_int($option)) {
289 $this->assertElementContainsText($block, $option);
290 }
291 }
292 }
293 }
294 // Open the form back up and check everything
295 if ($validate && $valid !== 'no_open') {
296 $this->openInlineForm($block);
297 foreach ($params as $item => $val) {
298 switch(gettype($val)) {
299 case 'string':
300 if ($val && substr($val, 0, 5) == 'date:') {
301 $val = date('m/d/Y', strtotime(trim(substr($val, 5))));
302 $item .= '_display';
303 }
304 if ($val) {
305 $this->assertElementValueEquals($item, $val);
306 }
307 break;
308 case 'integer':
309 $method = $val ? 'assertChecked' : 'assertNotChecked';
310 $this->$method($item);
311 break;
312 case 'array':
313 foreach ($val as $option) {
314 $method = is_int($option) ? 'assertIsSelected' : 'assertSelected';
315 $this->$method($item, $option);
316 }
317 break;
318 }
319 }
320 if ($valid !== 'keep_open') {
321 $this->click("css=#$block input.cancel");
322 }
323 }
324 }
325 // Verify there was a form error
326 else {
327 $this->waitForElementPresent('css=#crm-notification-container .error.ui-notify-message');
328 $this->click('css=#crm-notification-container .error .ui-notify-cross');
329 }
330 }
331 }