cms/drupal/modules/contact/contact.test
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     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 }