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