|
1 <?php |
|
2 /** |
|
3 * @file |
|
4 * Tests for the Contact module. |
|
5 */ |
|
6 |
|
7 /** |
|
8 * Tests the site-wide contact form. |
|
9 */ |
|
10 class ContactSitewideTestCase extends DrupalWebTestCase { |
|
11 public static function getInfo() { |
|
12 return array( |
|
13 'name' => 'Site-wide contact form', |
|
14 'description' => 'Tests site-wide contact form functionality.', |
|
15 'group' => 'Contact', |
|
16 ); |
|
17 } |
|
18 |
|
19 function setUp() { |
|
20 parent::setUp('contact'); |
|
21 } |
|
22 |
|
23 /** |
|
24 * Tests configuration options and the site-wide contact form. |
|
25 */ |
|
26 function testSiteWideContact() { |
|
27 // Create and login administrative user. |
|
28 $admin_user = $this->drupalCreateUser(array('access site-wide contact form', 'administer contact forms', 'administer users')); |
|
29 $this->drupalLogin($admin_user); |
|
30 |
|
31 $flood_limit = 3; |
|
32 variable_set('contact_threshold_limit', $flood_limit); |
|
33 variable_set('contact_threshold_window', 600); |
|
34 |
|
35 // Set settings. |
|
36 $edit = array(); |
|
37 $edit['contact_default_status'] = TRUE; |
|
38 $this->drupalPost('admin/config/people/accounts', $edit, t('Save configuration')); |
|
39 $this->assertText(t('The configuration options have been saved.'), 'Setting successfully saved.'); |
|
40 |
|
41 // Delete old categories to ensure that new categories are used. |
|
42 $this->deleteCategories(); |
|
43 |
|
44 // Ensure that the contact form won't be shown without categories. |
|
45 user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access site-wide contact form')); |
|
46 $this->drupalLogout(); |
|
47 $this->drupalGet('contact'); |
|
48 $this->assertResponse(404); |
|
49 $this->drupalLogin($admin_user); |
|
50 $this->drupalGet('contact'); |
|
51 $this->assertResponse(200); |
|
52 $this->assertText(t('The contact form has not been configured.')); |
|
53 |
|
54 // Add categories. |
|
55 // Test invalid recipients. |
|
56 $invalid_recipients = array('invalid', 'invalid@', 'invalid@site.', '@site.', '@site.com'); |
|
57 foreach ($invalid_recipients as $invalid_recipient) { |
|
58 $this->addCategory($this->randomName(16), $invalid_recipient, '', FALSE); |
|
59 $this->assertRaw(t('%recipient is an invalid e-mail address.', array('%recipient' => $invalid_recipient)), format_string('Caught invalid recipient (@invalid_recipient).', array('@invalid_recipient' => $invalid_recipient))); |
|
60 } |
|
61 |
|
62 // Test validation of empty category and recipients fields. |
|
63 $this->addCategory($category = '', '', '', TRUE); |
|
64 $this->assertText(t('Category field is required.'), 'Caught empty category field'); |
|
65 $this->assertText(t('Recipients field is required.'), 'Caught empty recipients field.'); |
|
66 |
|
67 // Create first valid category. |
|
68 $recipients = array('simpletest@example.com', 'simpletest2@example.com', 'simpletest3@example.com'); |
|
69 $this->addCategory($category = $this->randomName(16), implode(',', array($recipients[0])), '', TRUE); |
|
70 $this->assertRaw(t('Category %category has been saved.', array('%category' => $category)), 'Category successfully saved.'); |
|
71 |
|
72 // Make sure the newly created category is included in the list of categories. |
|
73 $this->assertNoUniqueText($category, 'New category included in categories list.'); |
|
74 |
|
75 // Test update contact form category. |
|
76 $categories = $this->getCategories(); |
|
77 $category_id = $this->updateCategory($categories, $category = $this->randomName(16), $recipients_str = implode(',', array($recipients[0], $recipients[1])), $reply = $this->randomName(30), FALSE); |
|
78 $category_array = db_query("SELECT category, recipients, reply, selected FROM {contact} WHERE cid = :cid", array(':cid' => $category_id))->fetchAssoc(); |
|
79 $this->assertEqual($category_array['category'], $category); |
|
80 $this->assertEqual($category_array['recipients'], $recipients_str); |
|
81 $this->assertEqual($category_array['reply'], $reply); |
|
82 $this->assertFalse($category_array['selected']); |
|
83 $this->assertRaw(t('Category %category has been saved.', array('%category' => $category)), 'Category successfully saved.'); |
|
84 |
|
85 // Ensure that the contact form is shown without a category selection input. |
|
86 user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access site-wide contact form')); |
|
87 $this->drupalLogout(); |
|
88 $this->drupalGet('contact'); |
|
89 $this->assertText(t('Your e-mail address'), 'Contact form is shown when there is one category.'); |
|
90 $this->assertNoText(t('Category'), 'When there is only one category, the category selection element is hidden.'); |
|
91 $this->drupalLogin($admin_user); |
|
92 |
|
93 // Add more categories. |
|
94 $this->addCategory($category = $this->randomName(16), implode(',', array($recipients[0], $recipients[1])), '', FALSE); |
|
95 $this->assertRaw(t('Category %category has been saved.', array('%category' => $category)), 'Category successfully saved.'); |
|
96 |
|
97 $this->addCategory($category = $this->randomName(16), implode(',', array($recipients[0], $recipients[1], $recipients[2])), '', FALSE); |
|
98 $this->assertRaw(t('Category %category has been saved.', array('%category' => $category)), 'Category successfully saved.'); |
|
99 |
|
100 // Try adding a category that already exists. |
|
101 $this->addCategory($category, '', '', FALSE); |
|
102 $this->assertNoRaw(t('Category %category has been saved.', array('%category' => $category)), 'Category not saved.'); |
|
103 $this->assertRaw(t('A contact form with category %category already exists.', array('%category' => $category)), 'Duplicate category error found.'); |
|
104 |
|
105 // Clear flood table in preparation for flood test and allow other checks to complete. |
|
106 db_delete('flood')->execute(); |
|
107 $num_records_after = db_query("SELECT COUNT(*) FROM {flood}")->fetchField(); |
|
108 $this->assertIdentical($num_records_after, '0', 'Flood table emptied.'); |
|
109 $this->drupalLogout(); |
|
110 |
|
111 // Check to see that anonymous user cannot see contact page without permission. |
|
112 user_role_revoke_permissions(DRUPAL_ANONYMOUS_RID, array('access site-wide contact form')); |
|
113 $this->drupalGet('contact'); |
|
114 $this->assertResponse(403, 'Access denied to anonymous user without permission.'); |
|
115 |
|
116 // Give anonymous user permission and see that page is viewable. |
|
117 user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access site-wide contact form')); |
|
118 $this->drupalGet('contact'); |
|
119 $this->assertResponse(200, 'Access granted to anonymous user with permission.'); |
|
120 |
|
121 // Submit contact form with invalid values. |
|
122 $this->submitContact('', $recipients[0], $this->randomName(16), $categories[0], $this->randomName(64)); |
|
123 $this->assertText(t('Your name field is required.'), 'Name required.'); |
|
124 |
|
125 $this->submitContact($this->randomName(16), '', $this->randomName(16), $categories[0], $this->randomName(64)); |
|
126 $this->assertText(t('Your e-mail address field is required.'), 'E-mail required.'); |
|
127 |
|
128 $this->submitContact($this->randomName(16), $invalid_recipients[0], $this->randomName(16), $categories[0], $this->randomName(64)); |
|
129 $this->assertText(t('You must enter a valid e-mail address.'), 'Valid e-mail required.'); |
|
130 |
|
131 $this->submitContact($this->randomName(16), $recipients[0], '', $categories[0], $this->randomName(64)); |
|
132 $this->assertText(t('Subject field is required.'), 'Subject required.'); |
|
133 |
|
134 $this->submitContact($this->randomName(16), $recipients[0], $this->randomName(16), $categories[0], ''); |
|
135 $this->assertText(t('Message field is required.'), 'Message required.'); |
|
136 |
|
137 // Test contact form with no default category selected. |
|
138 db_update('contact') |
|
139 ->fields(array('selected' => 0)) |
|
140 ->execute(); |
|
141 $this->drupalGet('contact'); |
|
142 $this->assertRaw(t('- Please choose -'), 'Without selected categories the visitor is asked to chose a category.'); |
|
143 |
|
144 // Submit contact form with invalid category id (cid 0). |
|
145 $this->submitContact($this->randomName(16), $recipients[0], $this->randomName(16), 0, ''); |
|
146 $this->assertText(t('You must select a valid category.'), 'Valid category required.'); |
|
147 |
|
148 // Submit contact form with correct values and check flood interval. |
|
149 for ($i = 0; $i < $flood_limit; $i++) { |
|
150 $this->submitContact($this->randomName(16), $recipients[0], $this->randomName(16), $categories[0], $this->randomName(64)); |
|
151 $this->assertText(t('Your message has been sent.'), 'Message sent.'); |
|
152 } |
|
153 // Submit contact form one over limit. |
|
154 $this->drupalGet('contact'); |
|
155 $this->assertResponse(403, 'Access denied to anonymous user after reaching message treshold.'); |
|
156 $this->assertRaw(t('You cannot send more than %number messages in @interval. Try again later.', array('%number' => variable_get('contact_threshold_limit', 3), '@interval' => format_interval(600))), 'Message threshold reached.'); |
|
157 |
|
158 // Delete created categories. |
|
159 $this->drupalLogin($admin_user); |
|
160 $this->deleteCategories(); |
|
161 } |
|
162 |
|
163 /** |
|
164 * Tests auto-reply on the site-wide contact form. |
|
165 */ |
|
166 function testAutoReply() { |
|
167 // Create and login administrative user. |
|
168 $admin_user = $this->drupalCreateUser(array('access site-wide contact form', 'administer contact forms', 'administer permissions', 'administer users')); |
|
169 $this->drupalLogin($admin_user); |
|
170 |
|
171 // Set up three categories, 2 with an auto-reply and one without. |
|
172 $foo_autoreply = $this->randomName(40); |
|
173 $bar_autoreply = $this->randomName(40); |
|
174 $this->addCategory('foo', 'foo@example.com', $foo_autoreply, FALSE); |
|
175 $this->addCategory('bar', 'bar@example.com', $bar_autoreply, FALSE); |
|
176 $this->addCategory('no_autoreply', 'bar@example.com', '', FALSE); |
|
177 |
|
178 // Test the auto-reply for category 'foo'. |
|
179 $email = $this->randomName(32) . '@example.com'; |
|
180 $subject = $this->randomName(64); |
|
181 $this->submitContact($this->randomName(16), $email, $subject, 2, $this->randomString(128)); |
|
182 |
|
183 // We are testing the auto-reply, so there should be one e-mail going to the sender. |
|
184 $captured_emails = $this->drupalGetMails(array('id' => 'contact_page_autoreply', 'to' => $email, 'from' => 'foo@example.com')); |
|
185 $this->assertEqual(count($captured_emails), 1, 'Auto-reply e-mail was sent to the sender for category "foo".', 'Contact'); |
|
186 $this->assertEqual($captured_emails[0]['body'], drupal_html_to_text($foo_autoreply), 'Auto-reply e-mail body is correct for category "foo".', 'Contact'); |
|
187 |
|
188 // Test the auto-reply for category 'bar'. |
|
189 $email = $this->randomName(32) . '@example.com'; |
|
190 $this->submitContact($this->randomName(16), $email, $this->randomString(64), 3, $this->randomString(128)); |
|
191 |
|
192 // Auto-reply for category 'bar' should result in one auto-reply e-mail to the sender. |
|
193 $captured_emails = $this->drupalGetMails(array('id' => 'contact_page_autoreply', 'to' => $email, 'from' => 'bar@example.com')); |
|
194 $this->assertEqual(count($captured_emails), 1, 'Auto-reply e-mail was sent to the sender for category "bar".', 'Contact'); |
|
195 $this->assertEqual($captured_emails[0]['body'], drupal_html_to_text($bar_autoreply), 'Auto-reply e-mail body is correct for category "bar".', 'Contact'); |
|
196 |
|
197 // Verify that no auto-reply is sent when the auto-reply field is left blank. |
|
198 $email = $this->randomName(32) . '@example.com'; |
|
199 $this->submitContact($this->randomName(16), $email, $this->randomString(64), 4, $this->randomString(128)); |
|
200 $captured_emails = $this->drupalGetMails(array('id' => 'contact_page_autoreply', 'to' => $email, 'from' => 'no_autoreply@example.com')); |
|
201 $this->assertEqual(count($captured_emails), 0, 'No auto-reply e-mail was sent to the sender for category "no-autoreply".', 'Contact'); |
|
202 } |
|
203 |
|
204 /** |
|
205 * Adds a category. |
|
206 * |
|
207 * @param string $category |
|
208 * The category name. |
|
209 * @param string $recipients |
|
210 * The list of recipient e-mail addresses. |
|
211 * @param string $reply |
|
212 * The auto-reply text that is sent to a user upon completing the contact |
|
213 * form. |
|
214 * @param boolean $selected |
|
215 * Boolean indicating whether the category should be selected by default. |
|
216 */ |
|
217 function addCategory($category, $recipients, $reply, $selected) { |
|
218 $edit = array(); |
|
219 $edit['category'] = $category; |
|
220 $edit['recipients'] = $recipients; |
|
221 $edit['reply'] = $reply; |
|
222 $edit['selected'] = ($selected ? '1' : '0'); |
|
223 $this->drupalPost('admin/structure/contact/add', $edit, t('Save')); |
|
224 } |
|
225 |
|
226 /** |
|
227 * Updates a category. |
|
228 * |
|
229 * @param string $category |
|
230 * The category name. |
|
231 * @param string $recipients |
|
232 * The list of recipient e-mail addresses. |
|
233 * @param string $reply |
|
234 * The auto-reply text that is sent to a user upon completing the contact |
|
235 * form. |
|
236 * @param boolean $selected |
|
237 * Boolean indicating whether the category should be selected by default. |
|
238 */ |
|
239 function updateCategory($categories, $category, $recipients, $reply, $selected) { |
|
240 $category_id = $categories[array_rand($categories)]; |
|
241 $edit = array(); |
|
242 $edit['category'] = $category; |
|
243 $edit['recipients'] = $recipients; |
|
244 $edit['reply'] = $reply; |
|
245 $edit['selected'] = ($selected ? '1' : '0'); |
|
246 $this->drupalPost('admin/structure/contact/edit/' . $category_id, $edit, t('Save')); |
|
247 return ($category_id); |
|
248 } |
|
249 |
|
250 /** |
|
251 * Submits the contact form. |
|
252 * |
|
253 * @param string $name |
|
254 * The name of the sender. |
|
255 * @param string $mail |
|
256 * The e-mail address of the sender. |
|
257 * @param string $subject |
|
258 * The subject of the message. |
|
259 * @param integer $cid |
|
260 * The category ID of the message. |
|
261 * @param string $message |
|
262 * The message body. |
|
263 */ |
|
264 function submitContact($name, $mail, $subject, $cid, $message) { |
|
265 $edit = array(); |
|
266 $edit['name'] = $name; |
|
267 $edit['mail'] = $mail; |
|
268 $edit['subject'] = $subject; |
|
269 $edit['cid'] = $cid; |
|
270 $edit['message'] = $message; |
|
271 $this->drupalPost('contact', $edit, t('Send message')); |
|
272 } |
|
273 |
|
274 /** |
|
275 * Deletes all categories. |
|
276 */ |
|
277 function deleteCategories() { |
|
278 $categories = $this->getCategories(); |
|
279 foreach ($categories as $category) { |
|
280 $category_name = db_query("SELECT category FROM {contact} WHERE cid = :cid", array(':cid' => $category))->fetchField(); |
|
281 $this->drupalPost('admin/structure/contact/delete/' . $category, array(), t('Delete')); |
|
282 $this->assertRaw(t('Category %category has been deleted.', array('%category' => $category_name)), 'Category deleted successfully.'); |
|
283 } |
|
284 } |
|
285 |
|
286 /** |
|
287 * Gets a list of all category IDs. |
|
288 * |
|
289 * @return array |
|
290 * A list of the category IDs. |
|
291 */ |
|
292 function getCategories() { |
|
293 $categories = db_query('SELECT cid FROM {contact}')->fetchCol(); |
|
294 return $categories; |
|
295 } |
|
296 } |
|
297 |
|
298 /** |
|
299 * Tests the personal contact form. |
|
300 */ |
|
301 class ContactPersonalTestCase extends DrupalWebTestCase { |
|
302 private $admin_user; |
|
303 private $web_user; |
|
304 private $contact_user; |
|
305 |
|
306 public static function getInfo() { |
|
307 return array( |
|
308 'name' => 'Personal contact form', |
|
309 'description' => 'Tests personal contact form functionality.', |
|
310 'group' => 'Contact', |
|
311 ); |
|
312 } |
|
313 |
|
314 function setUp() { |
|
315 parent::setUp('contact'); |
|
316 |
|
317 // Create an admin user. |
|
318 $this->admin_user = $this->drupalCreateUser(array('administer contact forms', 'administer users')); |
|
319 |
|
320 // Create some normal users with their contact forms enabled by default. |
|
321 variable_set('contact_default_status', TRUE); |
|
322 $this->web_user = $this->drupalCreateUser(array('access user contact forms')); |
|
323 $this->contact_user = $this->drupalCreateUser(); |
|
324 } |
|
325 |
|
326 /** |
|
327 * Tests access to the personal contact form. |
|
328 */ |
|
329 function testPersonalContactAccess() { |
|
330 // Test allowed access to user with contact form enabled. |
|
331 $this->drupalLogin($this->web_user); |
|
332 $this->drupalGet('user/' . $this->contact_user->uid . '/contact'); |
|
333 $this->assertResponse(200); |
|
334 |
|
335 // Test denied access to the user's own contact form. |
|
336 $this->drupalGet('user/' . $this->web_user->uid . '/contact'); |
|
337 $this->assertResponse(403); |
|
338 |
|
339 // Test always denied access to the anonymous user contact form. |
|
340 $this->drupalGet('user/0/contact'); |
|
341 $this->assertResponse(403); |
|
342 |
|
343 // Test that anonymous users can access the contact form. |
|
344 $this->drupalLogout(); |
|
345 user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access user contact forms')); |
|
346 $this->drupalGet('user/' . $this->contact_user->uid . '/contact'); |
|
347 $this->assertResponse(200); |
|
348 |
|
349 // Test that users can disable their contact form. |
|
350 $this->drupalLogin($this->contact_user); |
|
351 $edit = array('contact' => FALSE); |
|
352 $this->drupalPost('user/' . $this->contact_user->uid . '/edit', $edit, 'Save'); |
|
353 $this->drupalLogout(); |
|
354 $this->drupalGet('user/' . $this->contact_user->uid . '/contact'); |
|
355 $this->assertResponse(403); |
|
356 |
|
357 // Test that user's contact status stays disabled when saving. |
|
358 $contact_user_temp = user_load($this->contact_user->uid, TRUE); |
|
359 user_save($contact_user_temp); |
|
360 $this->drupalGet('user/' . $this->contact_user->uid . '/contact'); |
|
361 $this->assertResponse(403); |
|
362 |
|
363 // Test that users can enable their contact form. |
|
364 $this->drupalLogin($this->contact_user); |
|
365 $edit = array('contact' => TRUE); |
|
366 $this->drupalPost('user/' . $this->contact_user->uid . '/edit', $edit, 'Save'); |
|
367 $this->drupalLogout(); |
|
368 $this->drupalGet('user/' . $this->contact_user->uid . '/contact'); |
|
369 $this->assertResponse(200); |
|
370 |
|
371 // Revoke the personal contact permission for the anonymous user. |
|
372 user_role_revoke_permissions(DRUPAL_ANONYMOUS_RID, array('access user contact forms')); |
|
373 $this->drupalGet('user/' . $this->contact_user->uid . '/contact'); |
|
374 $this->assertResponse(403); |
|
375 |
|
376 // Disable the personal contact form. |
|
377 $this->drupalLogin($this->admin_user); |
|
378 $edit = array('contact_default_status' => FALSE); |
|
379 $this->drupalPost('admin/config/people/accounts', $edit, t('Save configuration')); |
|
380 $this->assertText(t('The configuration options have been saved.'), 'Setting successfully saved.'); |
|
381 $this->drupalLogout(); |
|
382 |
|
383 // Re-create our contacted user with personal contact forms disabled by |
|
384 // default. |
|
385 $this->contact_user = $this->drupalCreateUser(); |
|
386 |
|
387 // Test denied access to a user with contact form disabled. |
|
388 $this->drupalLogin($this->web_user); |
|
389 $this->drupalGet('user/' . $this->contact_user->uid . '/contact'); |
|
390 $this->assertResponse(403); |
|
391 |
|
392 // Test allowed access for admin user to a user with contact form disabled. |
|
393 $this->drupalLogin($this->admin_user); |
|
394 $this->drupalGet('user/' . $this->contact_user->uid . '/contact'); |
|
395 $this->assertResponse(200); |
|
396 |
|
397 // Re-create our contacted user as a blocked user. |
|
398 $this->contact_user = $this->drupalCreateUser(); |
|
399 user_save($this->contact_user, array('status' => 0)); |
|
400 |
|
401 // Test that blocked users can still be contacted by admin. |
|
402 $this->drupalGet('user/' . $this->contact_user->uid . '/contact'); |
|
403 $this->assertResponse(200); |
|
404 |
|
405 // Test that blocked users cannot be contacted by non-admins. |
|
406 $this->drupalLogin($this->web_user); |
|
407 $this->drupalGet('user/' . $this->contact_user->uid . '/contact'); |
|
408 $this->assertResponse(403); |
|
409 } |
|
410 |
|
411 /** |
|
412 * Tests the personal contact form flood protection. |
|
413 */ |
|
414 function testPersonalContactFlood() { |
|
415 $flood_limit = 3; |
|
416 variable_set('contact_threshold_limit', $flood_limit); |
|
417 |
|
418 // Clear flood table in preparation for flood test and allow other checks to complete. |
|
419 db_delete('flood')->execute(); |
|
420 $num_records_flood = db_query("SELECT COUNT(*) FROM {flood}")->fetchField(); |
|
421 $this->assertIdentical($num_records_flood, '0', 'Flood table emptied.'); |
|
422 |
|
423 $this->drupalLogin($this->web_user); |
|
424 |
|
425 // Submit contact form with correct values and check flood interval. |
|
426 for ($i = 0; $i < $flood_limit; $i++) { |
|
427 $this->submitPersonalContact($this->contact_user); |
|
428 $this->assertText(t('Your message has been sent.'), 'Message sent.'); |
|
429 } |
|
430 |
|
431 // Submit contact form one over limit. |
|
432 $this->drupalGet('user/' . $this->contact_user->uid. '/contact'); |
|
433 $this->assertRaw(t('You cannot send more than %number messages in @interval. Try again later.', array('%number' => $flood_limit, '@interval' => format_interval(variable_get('contact_threshold_window', 3600)))), 'Normal user denied access to flooded contact form.'); |
|
434 |
|
435 // Test that the admin user can still access the contact form even though |
|
436 // the flood limit was reached. |
|
437 $this->drupalLogin($this->admin_user); |
|
438 $this->assertNoText('Try again later.', 'Admin user not denied access to flooded contact form.'); |
|
439 } |
|
440 |
|
441 /** |
|
442 * Fills out a user's personal contact form and submits it. |
|
443 * |
|
444 * @param $account |
|
445 * A user object of the user being contacted. |
|
446 * @param $message |
|
447 * An optional array with the form fields being used. |
|
448 */ |
|
449 protected function submitPersonalContact($account, array $message = array()) { |
|
450 $message += array( |
|
451 'subject' => $this->randomName(16), |
|
452 'message' => $this->randomName(64), |
|
453 ); |
|
454 $this->drupalPost('user/' . $account->uid . '/contact', $message, t('Send message')); |
|
455 } |
|
456 } |