'Honeypot form protections', 'description' => 'Ensure that Honeypot protects site forms properly.', 'group' => 'Form API', ); } public function setUp() { // Enable modules required for this test. parent::setUp(array('honeypot', 'comment', 'honeypot_test')); // Set up required Honeypot variables. variable_set('honeypot_element_name', 'url'); // Disable time_limit protection. variable_set('honeypot_time_limit', 0); // Test protecting all forms. variable_set('honeypot_protect_all_forms', TRUE); variable_set('honeypot_log', FALSE); // Set up other required variables. variable_set('user_email_verification', TRUE); variable_set('user_register', USER_REGISTER_VISITORS); // Set up admin user. $this->adminUser = $this->drupalCreateUser(array( 'administer honeypot', 'bypass honeypot protection', 'administer content types', 'administer users', 'access comments', 'post comments', 'skip comment approval', 'administer comments', )); // Set up web user. $this->webUser = $this->drupalCreateUser(array( 'access comments', 'post comments', 'create article content', )); // Set up example node. $this->node = $this->drupalCreateNode(array( 'type' => 'article', 'promote' => 1, 'uid' => $this->webUser->uid, )); } /** * Test user registration (anonymous users). */ public function testProtectRegisterUserNormal() { // Set up form and submit it. $edit['name'] = $this->randomName(); $edit['mail'] = $edit['name'] . '@example.com'; $this->drupalPost('user/register', $edit, t('Create new account')); // Form should have been submitted successfully. $this->assertText(t('A welcome message with further instructions has been sent to your e-mail address.'), 'User registered successfully.'); } public function testProtectUserRegisterHoneypotFilled() { // Set up form and submit it. $edit['name'] = $this->randomName(); $edit['mail'] = $edit['name'] . '@example.com'; $edit['url'] = 'http://www.example.com/'; $this->drupalPost('user/register', $edit, t('Create new account')); // Form should have error message. $this->assertText(t('There was a problem with your form submission. Please refresh the page and try again.'), 'Registration form protected by honeypot.'); } public function testProtectRegisterUserTooFast() { // Enable time limit for honeypot. variable_set('honeypot_time_limit', 5); // Set up form and submit it. $edit['name'] = $this->randomName(); $edit['mail'] = $edit['name'] . '@example.com'; $this->drupalPost('user/register', $edit, t('Create new account')); // Form should have error message. $this->assertText(t('There was a problem with your form submission. Please wait 6 seconds and try again.'), 'Registration form protected by time limit.'); } /** * Test comment form protection. */ public function testProtectCommentFormNormal() { $comment = 'Test comment.'; // Disable time limit for honeypot. variable_set('honeypot_time_limit', 0); // Log in the web user. $this->drupalLogin($this->webUser); // Set up form and submit it. $edit['comment_body[' . LANGUAGE_NONE . '][0][value]'] = $comment; $this->drupalPost('comment/reply/' . $this->node->nid, $edit, t('Save')); $this->assertText(t('Your comment has been posted.'), 'Comment posted successfully.'); } public function testProtectCommentFormHoneypotFilled() { $comment = 'Test comment.'; // Log in the web user. $this->drupalLogin($this->webUser); // Set up form and submit it. $edit['comment_body[' . LANGUAGE_NONE . '][0][value]'] = $comment; $edit['url'] = 'http://www.example.com/'; $this->drupalPost('comment/reply/' . $this->node->nid, $edit, t('Save')); $this->assertText(t('There was a problem with your form submission. Please refresh the page and try again.'), 'Comment posted successfully.'); } public function testProtectCommentFormHoneypotBypass() { // Log in the admin user. $this->drupalLogin($this->adminUser); // Get the comment reply form and ensure there's no 'url' field. $this->drupalGet('comment/reply/' . $this->node->nid); $this->assertNoText('id="edit-url" name="url"', 'Honeypot home page field not shown.'); } /** * Test node form protection. */ public function testProtectNodeFormTooFast() { // Log in the admin user. $this->drupalLogin($this->webUser); // Reset the time limit to 5 seconds. variable_set('honeypot_time_limit', 5); // Set up the form and submit it. $edit["title"] = 'Test Page'; $this->drupalPost('node/add/article', $edit, t('Save')); $this->assertText(t('There was a problem with your form submission.'), 'Honeypot node form timestamp protection works.'); } /** * Test node form protection. */ public function testProtectNodeFormPreviewPassthru() { // Log in the admin user. $this->drupalLogin($this->webUser); // Post a node form using the 'Preview' button and make sure it's allowed. $edit["title"] = 'Test Page'; $this->drupalPost('node/add/article', $edit, t('Preview')); $this->assertNoText(t('There was a problem with your form submission.'), 'Honeypot not blocking node form previews.'); } /** * Test programmatic submission. */ public function testProgrammaticSubmission() { // Enable time limit protection. variable_set('honeypot_time_limit', 5); // Create a user for which we are going to trigger the password reset. $edit = array(); $edit['name'] = 'robo-user'; $edit['mail'] = $edit['name'] . '@example.com'; $edit['status'] = 1; user_save(drupal_anonymous_user(), $edit); // Trigger the password reset through a programmatic submission. $this->drupalGet('honeypot_test/submit_form'); // Verify that the submission did not return any validation errors. $form_errors = drupal_json_decode($this->content); $this->assertNoRaw('There was a problem with your form submission. Please wait 6 seconds and try again.'); $this->assertFalse($form_errors, 'The were no validation errors when submitting the form.'); } } /** * Test the functionality of the Honeypot module for an admin user. */ class HoneypotAdminFormTestCase extends DrupalWebTestCase { protected $adminUser; public static function getInfo() { return array( 'name' => 'Honeypot admin form', 'description' => 'Ensure the Honeypot admin form functions properly.', 'group' => 'Form API', ); } public function setUp() { // Enable modules required for this test. parent::setUp(array('honeypot')); // Set up admin user. $this->adminUser = $this->drupalCreateUser(array( 'administer honeypot', 'bypass honeypot protection', )); } /** * Test a valid element name. */ public function testElementNameUpdateSuccess() { // Log in the web user. $this->drupalLogin($this->adminUser); // Set up form and submit it. $edit['honeypot_element_name'] = "test"; $this->drupalPost('admin/config/content/honeypot', $edit, t('Save configuration')); // Form should have been submitted successfully. $this->assertText(t('The configuration options have been saved.'), 'Honeypot element name assertion works for valid names.'); // Set up form and submit it. $edit['honeypot_element_name'] = "test-1"; $this->drupalPost('admin/config/content/honeypot', $edit, t('Save configuration')); // Form should have been submitted successfully. $this->assertText(t('The configuration options have been saved.'), 'Honeypot element name assertion works for valid names with dashes and numbers.'); } /** * Test an invalid element name (invalid first character). */ public function testElementNameUpdateFirstCharacterFail() { // Log in the admin user. $this->drupalLogin($this->adminUser); // Set up form and submit it. $edit['honeypot_element_name'] = "1test"; $this->drupalPost('admin/config/content/honeypot', $edit, t('Save configuration')); // Form submission should fail. $this->assertText(t('The element name must start with a letter.'), 'Honeypot element name assertion works for invalid names.'); } /** * Test an invalid element name (invalid character in name). */ public function testElementNameUpdateInvalidCharacterFail() { // Log in the admin user. $this->drupalLogin($this->adminUser); // Set up form and submit it. $edit['honeypot_element_name'] = "special-character-&"; $this->drupalPost('admin/config/content/honeypot', $edit, t('Save configuration')); // Form submission should fail. $this->assertText(t('The element name cannot contain spaces or other special characters.'), 'Honeypot element name assertion works for invalid names with special characters.'); // Set up form and submit it. $edit['honeypot_element_name'] = "space in name"; $this->drupalPost('admin/config/content/honeypot', $edit, t('Save configuration')); // Form submission should fail. $this->assertText(t('The element name cannot contain spaces or other special characters.'), 'Honeypot element name assertion works for invalid names with spaces.'); } } /** * Test Honeypot's CSS generation routines. */ class HoneypotCssTestCase extends DrupalWebTestCase { public static function getInfo() { return array( 'name' => 'Honeypot CSS tests', 'description' => 'Ensure that Honeypot rebuilds its CSS file correctly.', 'group' => 'Form API', ); } public function setUp() { // Enable modules required for this test. parent::setUp(array('honeypot')); // Set up required Honeypot variables. variable_set('honeypot_element_name', 'url'); } /** * Test CSS file regeneration. */ public function testHoneypotCssRegeneration() { $honeypot_css = honeypot_get_css_file_path(); // Delete the Honeypot CSS file (if it exists). file_unmanaged_delete($honeypot_css); // Make sure the Honeypot CSS file doesn't exist. $this->assertFalse(file_exists($honeypot_css)); // Create the CSS file. honeypot_create_css(variable_get('honeypot_element_name', 'url')); // Make sure the Honeypot CSS file exists. $this->assertTrue(file_exists($honeypot_css)); } /** * Test cron-based CSS file regeneration. */ public function testHoneypotCssRegenerationOnCron() { $honeypot_css = honeypot_get_css_file_path(); // Delete the Honeypot CSS file (if it exists). file_unmanaged_delete($honeypot_css); // Make sure the Honeypot CSS file doesn't exist. $this->assertFalse(file_exists($honeypot_css)); // Run cron. honeypot_cron(); // Make sure the Honeypot CSS file exists. $this->assertTrue(file_exists($honeypot_css)); } /** * Test cron-based CSS file update. */ public function testHoneypotCssUpdateOnCron() { $honeypot_css = honeypot_get_css_file_path(); $original_element_name = variable_get('honeypot_element_name', 'url'); // Update the honeypot element name. variable_set('honeypot_element_name', 'test'); // Make sure the Honeypot CSS file still exists. $this->assertTrue(file_exists($honeypot_css)); // Run cron. honeypot_cron(); // Make sure the Honeypot CSS file was updated with the new element name. $handle = fopen($honeypot_css, 'r'); $contents = fread($handle, filesize($honeypot_css)); fclose($handle); $updated_element_name_in_css = (strpos($contents, 'test') === 1); $this->assertTrue($updated_element_name_in_css); // For debug. $this->verbose($contents); // Revert the honeypot element name back to the original. variable_set('honeypot_element_name', $original_element_name); } /** * Test CSS works when default file scheme is not public:// */ public function testHoneypotCssNonpublicFileSystem() { variable_set('file_default_scheme', 'private'); $honeypot_css = honeypot_get_css_file_path(); // Delete the Honeypot CSS file (if it exists). file_unmanaged_delete($honeypot_css); // Make sure the Honeypot CSS file doesn't exist. $this->assertFalse(file_exists($honeypot_css)); // Run cron. honeypot_cron(); // Make sure the Honeypot CSS file exists. $this->assertTrue(file_exists($honeypot_css)); } /** * Test CSS file availability. */ public function testHoneypotCssAvailability() { // Public CSS file can be consumed. variable_set('file_default_scheme', 'public'); if ($wrapper = file_stream_wrapper_get_instance_by_uri(honeypot_get_css_file_path())) { $url = $wrapper->getExternalUrl(); } $this->drupalGet($url); $this->assertResponse(200); // Private CSS file can not be consumed. variable_set('file_default_scheme', 'private'); honeypot_cron(); if ($wrapper = file_stream_wrapper_get_instance_by_uri(honeypot_get_css_file_path())) { $url = $wrapper->getExternalUrl(); } $this->drupalGet($url); $this->assertNoResponse(200); // Site default is private, but override honeypot's to public to consume. variable_set('honeypot_file_default_scheme', 'public'); honeypot_cron(); if ($wrapper = file_stream_wrapper_get_instance_by_uri(honeypot_get_css_file_path())) { $url = $wrapper->getExternalUrl(); } $this->drupalGet($url); $this->assertResponse(200); } } /** * Test the functionality of the Honeypot module's integration with Trigger. */ class HoneypotTriggerTestCase extends DrupalWebTestCase { public static function getInfo() { return array( 'name' => 'Honeypot Trigger integration', 'description' => 'Ensure that Honeypot triggers events correctly.', 'group' => 'Form API', ); } public function setUp() { // Enable modules required for this test. parent::setUp(array('honeypot', 'trigger')); // Set up required Honeypot variables. variable_set('honeypot_element_name', 'url'); // Disable time_limit protection. variable_set('honeypot_time_limit', 0); // Test protecting all forms. variable_set('honeypot_protect_all_forms', TRUE); variable_set('honeypot_log', FALSE); // Set up other required variables. variable_set('user_email_verification', TRUE); variable_set('user_register', USER_REGISTER_VISITORS); // Assign new action to Honeypot form rejection Trigger. db_insert('trigger_assignments') ->fields(array( 'hook' => 'honeypot_reject', 'aid' => 'system_block_ip_action', 'weight' => 1, )) ->execute(); } /** * Test trigger integration. */ public function testHoneypotTriggerIntegration() { // Set up form and submit it. $edit['name'] = $this->randomName(); $edit['mail'] = $edit['name'] . '@example.com'; $edit['url'] = 'http://www.example.com/'; $this->drupalPost('user/register', $edit, t('Create new account')); // Make sure Honeypot is working. $this->assertText(t('There was a problem with your form submission.'), 'Honeypot working correctly.'); // Visit the home page and make sure the user is banned. $this->drupalGet('node'); $this->assertText(t('has been banned'), 'User banned successfully.'); } }