| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: mollom.test,v 1.1.2.60 2010/09/15 02:56:56 dries Exp $ 3 4 /** 5 * @file 6 * Tests for the Mollom module. 7 */ 8 9 /** 10 * Defines Mollom testing keys. 11 * 12 * These keys will only work in test mode, so consult the Mollom API 13 * documentation for details. Do NOT use PRODUCTION keys for testing! 14 */ 15 define('MOLLOM_TEST_PUBLIC_KEY', '9cc3d2e43971de758ecddad61a3d12ec'); 16 define('MOLLOM_TEST_PRIVATE_KEY', '603a8d11099f17faaab49139bfc7d00a'); 17 18 /** 19 * Indicates that Mollom testing keys are reseller keys. 20 * 21 * If the above keys are reseller keys, make sure to change this value to TRUE. 22 * If you set this to TRUE and you are testing with non-reseller keys, the 23 * tests will fail due to unprivileged API access. 24 */ 25 define('MOLLOM_TEST_RESELLER_KEY', FALSE); 26 27 /** 28 * Common base test class for Mollom tests. 29 */ 30 class MollomWebTestCase extends DrupalWebTestCase { 31 /** 32 * The Mollom administrator user account. 33 */ 34 protected $admin_user; 35 36 /** 37 * A normal web user account. 38 */ 39 protected $web_user; 40 41 /** 42 * The text the user should see when they are blocked from submitting a form 43 * because the Mollom servers are unreachable. 44 */ 45 protected $fallback_message = 'The spam filter installed on this site is currently unavailable. Per site policy, we are unable to accept new submissions until that problem is resolved. Please try resubmitting the form in a couple of minutes.'; 46 47 /** 48 * The text the user should see if there submission was determinted to be spam. 49 */ 50 protected $spam_message = 'Your submission has triggered the spam filter and will not be accepted.'; 51 52 /** 53 * The text the user should see if they did not fill out the CAPTCHA correctly. 54 */ 55 protected $incorrect_message = 'The word verification was not completed correctly. Please complete this new word verification and try again.'; 56 57 /** 58 * The text the user should see if the textual analysis was unsure about the 59 * content. 60 */ 61 protected $unsure_message = "To complete this form, please complete the word verification below."; 62 63 /** 64 * The public key used during testing. 65 */ 66 protected $public_key = ''; 67 68 /** 69 * The private key used during testing. 70 */ 71 protected $private_key = ''; 72 73 /** 74 * A boolean that is TRUE if the above keys are for a reseller account. 75 */ 76 protected $is_reseller = FALSE; 77 78 /** 79 * Set up an administrative user account and testing keys. 80 */ 81 function setUp() { 82 // Re-initialize stored session_id and watchdog messages. 83 $this->resetSessionID(); 84 $this->messages = array(); 85 86 // If not explicitly disabled by a test, setup with Mollom and default admin 87 // user. 88 if (empty($this->disableDefaultSetup)) { 89 // Call parent::setUp() allowing Mollom test cases to pass further modules. 90 $modules = func_get_args(); 91 $modules[] = 'mollom'; 92 $modules[] = 'dblog'; 93 call_user_func_array(array($this, 'parent::setUp'), $modules); 94 95 $this->admin_user = $this->drupalCreateUser(array( 96 'administer mollom', 97 'access administration pages', 98 'administer content types', 99 'administer comments', 100 'administer permissions', 101 'administer users', 102 )); 103 } 104 else { 105 $modules = func_get_args(); 106 $modules[] = 'dblog'; 107 call_user_func_array(array($this, 'parent::setUp'), $modules); 108 } 109 110 // If not explicitly disabled by a test, setup and validate testing keys. 111 if (empty($this->disableDefaultSetup)) { 112 $this->setKeys(); 113 $this->assertValidKeys(); 114 } 115 } 116 117 function tearDown() { 118 // Capture any (remaining) watchdog messages. 119 $this->assertMollomWatchdogMessages(); 120 parent::tearDown(); 121 } 122 123 /** 124 * Assert any watchdog messages based on their severity. 125 * 126 * This function can be (repeatedly) invoked to assert new watchdog messages. 127 * All watchdog messages with a higher severity than WATCHDOG_NOTICE are 128 * considered as fails. 129 * 130 * @param $no_fail_expected 131 * (optional) Boolean whether a failing watchdog message is expected. 132 * Defaults to TRUE (no fail expected). If FALSE is passed, the logic for 133 * assertion messages is flipped. 134 * 135 * @todo Add this to D7 core. 136 */ 137 protected function assertMollomWatchdogMessages($no_fail_expected = TRUE) { 138 module_load_include('inc', 'dblog', 'dblog.admin'); 139 140 $this->messages = array(); 141 $result = db_query("SELECT * FROM {watchdog} WHERE type = 'mollom' ORDER BY timestamp ASC"); 142 while ($row = db_fetch_object($result)) { 143 if ($no_fail_expected ? $row->severity >= WATCHDOG_NOTICE : $row->severity < WATCHDOG_NOTICE) { 144 $this->pass(_dblog_format_message($row), t('Watchdog')); 145 } 146 else { 147 $this->fail(_dblog_format_message($row), t('Watchdog')); 148 } 149 $this->messages[$row->wid] = $row; 150 } 151 // Delete processed watchdog messages. 152 if (!empty($this->messages)) { 153 $seen_ids = array_keys($this->messages); 154 db_query("DELETE FROM {watchdog} WHERE wid IN (" . db_placeholders($seen_ids) . ")", $seen_ids); 155 } 156 } 157 158 /** 159 * Assert that the Mollom session id remains the same. 160 * 161 * The Mollom session id is only known to one server. If we are communicating 162 * with a different Mollom server (due to a refreshed server list or being 163 * redirected), then we will get a new session_id. 164 * 165 * @param $session_id 166 * A Mollom session_id of the last request, as contained in the XML-RPC 167 * response. 168 */ 169 protected function assertSessionID($session_id) { 170 // Check whether watchdog messages indicate a refresh or redirect. 171 foreach ($this->messages as $message) { 172 if ($message->message == 'Refreshed servers: %servers' || $message->message == 'Server %server redirected to: %next.') { 173 $this->resetSessionID(); 174 } 175 } 176 177 if (!isset($this->session_id)) { 178 // Use assertTrue() instead of pass(), to test !empty(). 179 $this->assertTrue($session_id, t('New session_id: %session_id', array('%session_id' => $session_id))); 180 $this->session_id = $session_id; 181 } 182 else { 183 $this->assertSame('session_id', $session_id, $this->session_id); 184 } 185 return $this->session_id; 186 } 187 188 /** 189 * Reset the statically cached Mollom session id. 190 */ 191 protected function resetSessionID() { 192 $this->session_id = NULL; 193 } 194 195 /** 196 * Assert a Mollom session id in a form. 197 * 198 * This is a wrapper around assertSessionID() allows to assert that a proper 199 * Mollom session id is found in the form contained in the internal browser 200 * output. The usual flow is: 201 * - drupalGet() or drupalPost() requests or submits a form. 202 * - drupalGet() and drupalPost() invoke assertMollomWatchdogMessages() 203 * internally, which records all new watchdog messages. 204 * - This function, assertSessionIDInForm(), is invoked to assert that there 205 * is a Mollom session id and, depending on the recorded watchdog messages, 206 * that it either equals the last known session id or the new session id is 207 * used for future comparisons in case of a server redirect. 208 * - The return value of this function is used to invoke assertMollomData(), 209 * to verify that the proper session id was stored in the database. 210 */ 211 protected function assertSessionIDInForm() { 212 // The session id found in the form element value is prefixed with the UNIX 213 // timestamp denoting the time it was generated/output. The form element 214 // #process callback mollom_process_mollom_session_id() uses this timestamp 215 // to additionally validate its age. 216 list($timestamp, $session_id) = explode('-', $this->getFieldValueByName('mollom[session_id]')); 217 return $this->assertSessionID($session_id); 218 } 219 220 /** 221 * Assign the Mollom API keys to internal variables and reset the server list. 222 * 223 * @param $public 224 * The public Mollom API key. 225 * @param $private 226 * The private Mollom API key. 227 * @param $reseller 228 * A boolean that is TRUE if the keys are for a reseller account, or FALSE 229 * otherwise. 230 */ 231 protected function setKeys($public = MOLLOM_TEST_PUBLIC_KEY, $private = MOLLOM_TEST_PRIVATE_KEY, $reseller = MOLLOM_TEST_RESELLER_KEY) { 232 // Save internal properties. 233 $this->public_key = $public; 234 $this->private_key = $private; 235 $this->is_reseller = $reseller; 236 237 // Set the module key settings. 238 variable_set('mollom_public_key', $public); 239 variable_set('mollom_private_key', $private); 240 241 // Enable testing mode. 242 variable_set('mollom_testing_mode', 1); 243 244 // Delete any previously set Mollom servers to make sure we are using 245 // the default ones. 246 variable_del('mollom_servers'); 247 } 248 249 /** 250 * Call the mollom.verifyKey function directly and check that the current 251 * keys are valid. 252 */ 253 protected function assertValidKeys() { 254 $status = _mollom_status(TRUE); 255 $this->assertMollomWatchdogMessages(); 256 $this->assertIdentical($status, TRUE, t('Mollom servers can be contacted and testing API keys are valid.')); 257 } 258 259 /** 260 * Configure Mollom protection for a given form. 261 * 262 * @param $form_id 263 * The form id to configure. 264 * @param $mode 265 * The Mollom protection mode for the form. 266 * @param $fields 267 * (optional) A list of form elements to enable for text analysis. If 268 * omitted and the form registers individual elements, all fields are 269 * enabled by default. 270 * @param $edit 271 * (optional) An array of POST data to pass through to drupalPost() when 272 * configuring the form's protection. 273 */ 274 protected function setProtection($form_id, $mode = MOLLOM_MODE_ANALYSIS, $fields = NULL, $edit = array()) { 275 // Always start from overview page, also to make debugging easier. 276 $this->drupalGet('admin/settings/mollom'); 277 // Determine whether the form is already protected. 278 $exists = db_result(db_query_range("SELECT 1 FROM {mollom_form} WHERE form_id = '%s'", $form_id, 0, 1)); 279 // Add a new form. 280 if (!$exists) { 281 $this->clickLink(t('Add form')); 282 $add_form_edit = array( 283 'mollom[form_id]' => $form_id, 284 ); 285 $this->drupalPost(NULL, $add_form_edit, t('Next')); 286 } 287 // Edit an existing form. 288 else { 289 $this->drupalGet('admin/settings/mollom/manage/' . $form_id); 290 } 291 292 $edit += array( 293 'mollom[mode]' => $mode, 294 ); 295 296 // Process the enabled fields. 297 $form_list = mollom_form_list(); 298 $form_info = mollom_form_info($form_id, $form_list[$form_id]['module']); 299 foreach (array_keys($form_info['elements']) as $field) { 300 if (!isset($fields) || in_array($field, $fields)) { 301 // If the user specified all fields by default or to include this 302 // field, set its checkbox value to TRUE. 303 $edit['mollom[enabled_fields][' . rawurlencode($field) . ']'] = TRUE; 304 } 305 else { 306 // Otherwise set the field's checkbox value to FALSE. 307 $edit['mollom[enabled_fields][' . rawurlencode($field) . ']'] = FALSE; 308 } 309 } 310 $this->drupalPost(NULL, $edit, t('Save')); 311 if (!$exists) { 312 $this->assertText(t('The form protection has been added.')); 313 } 314 else { 315 $this->assertText(t('The form protection has been updated.')); 316 } 317 } 318 319 /** 320 * Remove Mollom protection for a given form. 321 * 322 * @param $form_id 323 * The form id to configure. 324 */ 325 protected function delProtection($form_id) { 326 // Determine whether the form is protected. 327 $exists = db_result(db_query_range("SELECT 1 FROM {mollom_form} WHERE form_id = '%s'", $form_id, 0, 1)); 328 if ($exists) { 329 $this->drupalGet('admin/settings/mollom/unprotect/' . $form_id); 330 $this->assertText(t('Mollom will no longer protect this form from spam.'), t('Unprotect confirmation form found.')); 331 $this->drupalPost(NULL, array(), t('Confirm')); 332 } 333 } 334 335 /** 336 * Assert that Mollom session data was stored for a submission. 337 * 338 * @param $entity 339 * The entity type to search for in {mollom}. 340 * @param $id 341 * The entity id to search for in {mollom}. 342 * @param $session_id 343 * (optional) The Mollom session id to assert additionally. 344 */ 345 protected function assertMollomData($entity, $id, $session_id = NULL) { 346 $data = mollom_data_load($entity, $id); 347 $this->assertTrue($data->session, t('Mollom session data for %entity @id exists: <pre>@data</pre>', array('%entity' => $entity, '@id' => $id, '@data' => var_export($data, TRUE)))); 348 if (isset($session_id)) { 349 $this->assertSame(t('Stored session id'), $data->session, $session_id); 350 } 351 return $data; 352 } 353 354 /** 355 * Assert that no Mollom session data exists for a certain entity. 356 */ 357 protected function assertNoMollomData($entity, $id) { 358 $data = mollom_data_load($entity, $id); 359 $this->assertFalse($data, t('No Mollom session data exists for %entity @id.', array('%entity' => $entity, '@id' => $id))); 360 } 361 362 /** 363 * Assert that the CAPTCHA field is found on the current page. 364 */ 365 protected function assertCaptchaField() { 366 $this->assertFieldByXPath('//input[@type="text"][@name="mollom[captcha]"]', '', 'CAPTCHA field found.'); 367 $image = $this->xpath('//img[@alt="' . t('Type the characters you see in this picture.') . '"]'); 368 $this->assert(!empty($image), 'CAPTCHA image found.'); 369 } 370 371 /** 372 * Assert that the CAPTCHA field is not found on the current page. 373 */ 374 protected function assertNoCaptchaField() { 375 $this->assertNoFieldByXPath('//input[@type="text"][@name="mollom[captcha]"]', '', 'CAPTCHA field not found.'); 376 $image = $this->xpath('//img[@alt="' . t('Type the characters you see in this picture.') . '"]'); 377 $this->assert(empty($image), 'CAPTCHA image not found.'); 378 } 379 380 /** 381 * Assert that the privacy policy link is found on the current page. 382 */ 383 protected function assertPrivacyLink() { 384 $elements = $this->xpath('//div[contains(@class, "mollom-privacy")]'); 385 $this->assertTrue($elements, t('Privacy policy container found.')); 386 } 387 388 /** 389 * Assert that the privacy policy link is not found on the current page. 390 */ 391 protected function assertNoPrivacyLink() { 392 $elements = $this->xpath('//div[contains(@class, "mollom-privacy")]'); 393 $this->assertFalse($elements, t('Privacy policy container not found.')); 394 } 395 396 /** 397 * Test submitting a form with a correct CAPTCHA value. 398 * 399 * @param $url 400 * The URL of the form, or NULL to use the current page. 401 * @param $edit 402 * An array of form values used in drupalPost(). 403 * @param $button 404 * The text of the form button to click in drupalPost(). 405 * @param $success_message 406 * An optional message to test does appear after submission. 407 */ 408 protected function postCorrectCaptcha($url, array $edit = array(), $button, $success_message = '') { 409 $edit['mollom[captcha]'] = 'correct'; 410 $this->drupalPost($url, $edit, $button); 411 $this->assertNoCaptchaField(); 412 $this->assertNoText($this->incorrect_message); 413 if ($success_message) { 414 $this->assertText($success_message); 415 } 416 } 417 418 /** 419 * Test submitting a form with an incorrect CAPTCHA value. 420 * 421 * @param $url 422 * The URL of the form, or NULL to use the current page. 423 * @param $edit 424 * An array of form values used in drupalPost(). 425 * @param $button 426 * The text of the form button to click in drupalPost(). 427 * @param $success_message 428 * An optional message to test does not appear after submission. 429 */ 430 protected function postIncorrectCaptcha($url, array $edit = array(), $button, $success_message = '') { 431 $edit['mollom[captcha]'] = 'incorrect'; 432 $before_url = $this->getUrl(); 433 $this->drupalPost($url, $edit, $button); 434 if ($this->getUrl() == $before_url) { 435 $this->assertCaptchaField(); 436 } 437 $this->assertText($this->incorrect_message); 438 if ($success_message) { 439 $this->assertNoText($success_message); 440 } 441 } 442 443 /** 444 * Test submitting a form with 'spam' values. 445 * 446 * @param $url 447 * The URL of the form, or NULL to use the current page. 448 * @param $spam_fields 449 * An array of form field names to inject spam content into. 450 * @param $edit 451 * An array of non-spam form values used in drupalPost(). 452 * @param $button 453 * The text of the form button to click in drupalPost(). 454 * @param $success_message 455 * An optional message to test does not appear after submission. 456 */ 457 protected function assertSpamSubmit($url, array $spam_fields, array $edit = array(), $button, $success_message = '') { 458 $edit += array_fill_keys($spam_fields, 'spam'); 459 $this->drupalPost($url, $edit, $button); 460 $this->assertNoCaptchaField($url); 461 $this->assertText($this->spam_message); 462 if ($success_message) { 463 $this->assertNoText($success_message); 464 } 465 } 466 467 /** 468 * Test submitting a form with 'ham' values. 469 * 470 * @param $url 471 * The URL of the form, or NULL to use the current page. 472 * @param $ham_fields 473 * An array of form field names to inject ham content into. 474 * @param $edit 475 * An array of non-spam form values used in drupalPost(). 476 * @param $button 477 * The text of the form button to click in drupalPost(). 478 * @param $success_message 479 * An optional message to test does appear after submission. 480 */ 481 protected function assertHamSubmit($url, array $ham_fields, array $edit = array(), $button, $success_message = '') { 482 $edit += array_fill_keys($ham_fields, 'ham'); 483 $this->drupalPost($url, $edit, $button); 484 $this->assertNoCaptchaField($url); 485 $this->assertNoText($this->spam_message); 486 if ($success_message) { 487 $this->assertText($success_message); 488 } 489 } 490 491 /** 492 * Test submitting a form with unsure values and resulting CAPTCHA submissions. 493 * 494 * @param $url 495 * The URL of the form, or NULL to use the current page. 496 * @param $unsure_fields 497 * An array of form field names to inject unsure content into. 498 * @param $edit 499 * An array of non-spam form values used in drupalPost(). 500 * @param $button 501 * The text of the form button to click in drupalPost(). 502 * @param $success_message 503 * An optional message to test does appear after sucessful form and CAPTCHA 504 * submission. 505 */ 506 protected function assertUnsureSubmit($url, array $unsure_fields, array $edit = array(), $button, $success_message = '') { 507 $edit += array_fill_keys($unsure_fields, 'unsure'); 508 $before_url = $this->getUrl(); 509 $this->drupalPost($url, $edit, $button); 510 if ($this->getUrl() == $before_url) { 511 $this->assertCaptchaField(); 512 } 513 $this->assertText($this->unsure_message); 514 if ($success_message) { 515 $this->assertNoText($success_message); 516 } 517 518 $this->postIncorrectCaptcha(NULL, $edit, $button, $success_message); 519 $this->postCorrectCaptcha(NULL, $edit, $button, $success_message); 520 } 521 522 /** 523 * Retrieve a field value by ID. 524 */ 525 protected function getFieldValueByID($id) { 526 $fields = $this->xpath($this->constructFieldXpath('id', $id)); 527 return (string) $fields[0]['value']; 528 } 529 530 /** 531 * Retrieve a field value by name. 532 */ 533 protected function getFieldValueByName($name) { 534 $fields = $this->xpath($this->constructFieldXpath('name', $name)); 535 return (string) $fields[0]['value']; 536 } 537 538 /** 539 * Retrieve submitted XML-RPC values from testing server implementation. 540 * 541 * @param $method 542 * (optional) The XML-RPC method name to retrieve submitted values from. 543 * Defaults to 'mollom.checkContent'. 544 * 545 * @see MollomWebTestCase::resetServerRecords() 546 * @see mollom_test_xmlrpc() 547 */ 548 protected function getServerRecord($method = 'mollom.checkContent') { 549 // Map the XML-RPC method name to the corresponding function callback name. 550 drupal_load('module', 'mollom_test'); 551 $method_function_map = mollom_test_xmlrpc(); 552 $function = $method_function_map[$method]; 553 554 // Retrieve last recorded values. 555 $storage = variable_get($function, array()); 556 $return = array_shift($storage); 557 variable_set($function, $storage); 558 559 return $return; 560 } 561 562 /** 563 * Resets recorded XML-RPC values. 564 * 565 * @param $method 566 * (optional) The XML-RPC method name to reset records of. Defaults to 567 * 'mollom.checkContent'. 568 * 569 * @see MollomWebTestCase::getServerRecord() 570 * @see mollom_test_xmlrpc() 571 */ 572 protected function resetServerRecords($method = 'mollom.checkContent') { 573 // Map the XML-RPC method name to the corresponding function callback name. 574 drupal_load('module', 'mollom_test'); 575 $method_function_map = mollom_test_xmlrpc(); 576 $function = $method_function_map[$method]; 577 578 // Delete the variable. 579 variable_del($function); 580 } 581 582 /** 583 * Wraps drupalGet() for additional watchdog message assertion. 584 * 585 * @param $options 586 * In addition to regular $options that are passed to url(): 587 * - watchdog: (optional) Boolean whether to assert that only non-severe 588 * watchdog messages have been logged. Defaults to TRUE. Use FALSE to 589 * negate the watchdog message severity assertion. 590 * 591 * @see DrupalWebTestCase->drupalGet() 592 * @see MollomWebTestCase->assertMollomWatchdogMessages() 593 * @see MollomWebTestCase->assertSessionID() 594 */ 595 protected function drupalGet($path, array $options = array(), array $headers = array()) { 596 $output = parent::drupalGet($path, $options, $headers); 597 $options += array('watchdog' => TRUE); 598 $this->assertMollomWatchdogMessages($options['watchdog']); 599 return $output; 600 } 601 602 /** 603 * Wraps drupalPost() for additional watchdog message assertion. 604 * 605 * @param $options 606 * In addition to regular $options that are passed to url(): 607 * - watchdog: (optional) Boolean whether to assert that only non-severe 608 * watchdog messages have been logged. Defaults to TRUE. Use FALSE to 609 * negate the watchdog message severity assertion. 610 * 611 * @see MollomWebTestCase->assertMollomWatchdogMessages() 612 * @see MollomWebTestCase->assertSessionID() 613 * @see DrupalWebTestCase->drupalPost() 614 */ 615 protected function drupalPost($path, $edit, $submit, array $options = array(), array $headers = array()) { 616 $output = parent::drupalPost($path, $edit, $submit, $options, $headers); 617 $options += array('watchdog' => TRUE); 618 $this->assertMollomWatchdogMessages($options['watchdog']); 619 return $output; 620 } 621 622 /** 623 * Asserts that two values belonging to the same variable are equal. 624 * 625 * Checks to see whether two values, which belong to the same variable name or 626 * identifier, are equal and logs a readable assertion message. 627 * 628 * @param $name 629 * A name or identifier to use in the assertion message. 630 * @param $first 631 * The first value to check. 632 * @param $second 633 * The second value to check. 634 * 635 * @return 636 * TRUE if the assertion succeeded, FALSE otherwise. 637 * 638 * @see MollomWebTestCase::assertNotSame() 639 * 640 * @todo D8: Move into core. This improved assertEqual() did not get into D7, 641 * since the function signature differs and it's plenty of work to manually 642 * update all assertEqual() invocations throughout all tests. 643 */ 644 protected function assertSame($name, $first, $second) { 645 $message = t("@name: @first is equal to @second.", array( 646 '@name' => $name, 647 '@first' => var_export($first, TRUE), 648 '@second' => var_export($second, TRUE), 649 )); 650 $this->assertEqual($first, $second, $message); 651 } 652 653 /** 654 * Asserts that two values belonging to the same variable are not equal. 655 * 656 * Checks to see whether two values, which belong to the same variable name or 657 * identifier, are not equal and logs a readable assertion message. 658 * 659 * @param $name 660 * A name or identifier to use in the assertion message. 661 * @param $first 662 * The first value to check. 663 * @param $second 664 * The second value to check. 665 * 666 * @return 667 * TRUE if the assertion succeeded, FALSE otherwise. 668 * 669 * @see MollomWebTestCase::assertSame() 670 */ 671 protected function assertNotSame($name, $first, $second) { 672 $message = t("@name: '@first' is not equal to '@second'.", array( 673 '@name' => $name, 674 '@first' => var_export($first, TRUE), 675 '@second' => var_export($second, TRUE), 676 )); 677 $this->assertNotEqual($first, $second, $message); 678 } 679 } 680 681 /** 682 * Tests module installation and global status handling. 683 */ 684 class MollomInstallationTestCase extends MollomWebTestCase { 685 public static function getInfo() { 686 return array( 687 'name' => 'Installation and key handling', 688 'description' => 'Tests module installation and key error handling.', 689 'group' => 'Mollom', 690 ); 691 } 692 693 function setUp() { 694 // Re-initialize stored session_id and watchdog messages. 695 $this->resetSessionID(); 696 $this->messages = array(); 697 698 $this->disableDefaultSetup = TRUE; 699 parent::setUp('comment'); 700 701 $this->admin_user = $this->drupalCreateUser(array( 702 'access administration pages', 703 'administer site configuration', 704 'administer permissions', 705 )); 706 $this->web_user = $this->drupalCreateUser(); 707 } 708 709 /** 710 * Tests status handling after installation. 711 * 712 * We walk through a regular installation of the Mollom module instead of using 713 * setUp() to ensure that everything works as expected. 714 * 715 * Note: Partial error messages tested here; hence, no t(). 716 */ 717 function testInstallationProcess() { 718 $admin_message = t('Visit the <a href="@settings-url">Mollom settings page</a> to configure your keys.', array( 719 '@settings-url' => url('admin/settings/mollom/settings'), 720 )); 721 $this->drupalLogin($this->admin_user); 722 723 // Ensure there is no requirements error by default. 724 $this->drupalGet('admin/reports/status'); 725 $this->clickLink('run cron manually'); 726 727 // Install the Mollom module. 728 $this->drupalPost('admin/build/modules', array('status[mollom]' => TRUE), t('Save configuration')); 729 $this->assertRaw(t('The Mollom API keys are not configured yet. !admin-message', array( 730 '!admin-message' => $admin_message, 731 )), t('Post installation warning found.')); 732 733 // Verify that forms can be submitted without valid Mollom module configuration. 734 $node = $this->drupalCreateNode(array('type' => 'story', 'promoted' => TRUE)); 735 $this->drupalLogin($this->web_user); 736 $this->drupalGet('comment/reply/' . $node->nid); 737 $edit = array( 738 'comment' => 'spam', 739 ); 740 $this->drupalPost(NULL, $edit, t('Preview')); 741 $this->drupalPost(NULL, array(), t('Save')); 742 $this->assertRaw('<p>' . $edit['comment'] . '</p>', t('Comment found.')); 743 744 // Assign the 'administer mollom' permission and log in a user. 745 $this->drupalLogin($this->admin_user); 746 $edit = array( 747 DRUPAL_AUTHENTICATED_RID . '[administer mollom]' => TRUE, 748 ); 749 $this->drupalPost('admin/user/permissions', $edit, t('Save permissions')); 750 751 // Verify presence of 'empty keys' error message. 752 $this->drupalGet('admin/settings/mollom'); 753 $this->assertText('The Mollom API keys are not configured yet.'); 754 $this->assertNoText('The configured Mollom API keys are invalid.'); 755 756 // Verify requirements error about missing API keys. 757 $this->drupalGet('admin/reports/status'); 758 $this->assertRaw(t('The Mollom API keys are not configured yet. !admin-message', array( 759 '!admin-message' => $admin_message, 760 )), t('Requirements error found.')); 761 762 // Configure invalid keys. 763 $edit = array( 764 'mollom_public_key' => 'foo', 765 'mollom_private_key' => 'bar', 766 ); 767 $this->drupalPost('admin/settings/mollom/settings', $edit, t('Save configuration'), array('watchdog' => FALSE)); 768 $this->assertText(t('The configuration options have been saved.')); 769 $this->assertNoText($this->fallback_message, t('Fallback message not found.')); 770 771 // Verify presence of 'incorrect keys' error message. 772 $this->assertText('The configured Mollom API keys are invalid.'); 773 $this->assertNoText('The Mollom API keys are not configured yet.'); 774 $this->assertNoText(t('The Mollom servers could not be contacted. Please make sure that your web server can make outgoing HTTP requests.')); 775 776 // Verify requirements error about invalid API keys. 777 $this->drupalGet('admin/reports/status', array('watchdog' => FALSE)); 778 $this->assertText('The configured Mollom API keys are invalid.'); 779 780 // Ensure unreachable servers. 781 variable_set('mollom_servers', array('http://fake-host')); 782 783 // Verify presence of 'network error' message. 784 $this->drupalGet('admin/settings/mollom/settings', array('watchdog' => FALSE)); 785 $this->assertText(t('The Mollom servers could not be contacted. Please make sure that your web server can make outgoing HTTP requests.')); 786 787 // Ensure unreachable servers. 788 variable_set('mollom_servers', array('http://fake-host')); 789 790 // Verify requirements error about network error. 791 $this->drupalGet('admin/reports/status', array('watchdog' => FALSE)); 792 $this->assertText(t('The Mollom servers could not be contacted. Please make sure that your web server can make outgoing HTTP requests.')); 793 $this->assertNoText($this->fallback_message, t('Fallback message not found.')); 794 795 // Verify that valid keys work. 796 $this->drupalGet('admin/settings/mollom/settings', array('watchdog' => FALSE)); 797 $edit = array( 798 'mollom_public_key' => MOLLOM_TEST_PUBLIC_KEY, 799 'mollom_private_key' => MOLLOM_TEST_PRIVATE_KEY, 800 'mollom_testing_mode' => 1, 801 ); 802 $this->drupalPost(NULL, $edit, t('Save configuration')); 803 $this->assertText(t('The configuration options have been saved.')); 804 $this->assertText('We are now blocking spam.'); 805 $this->assertNoText('The Mollom API keys are not configured yet.'); 806 $this->assertNoText('The configured Mollom API keys are invalid.'); 807 808 // Verify presence of testing mode warning. 809 $this->drupalGet('admin/settings/mollom'); 810 $this->assertText('Mollom testing mode is still enabled.'); 811 } 812 } 813 814 /** 815 * Tests low-level XML-RPC communication with Mollom servers. 816 */ 817 class MollomResponseTestCase extends MollomWebTestCase { 818 public static function getInfo() { 819 return array( 820 'name' => 'Server responses', 821 'description' => 'Tests that Mollom server responses match expectations.', 822 'group' => 'Mollom', 823 ); 824 } 825 826 /** 827 * Tests mollom.checkContent(). 828 */ 829 function testCheckContent() { 830 $data = array( 831 'author_name' => $this->admin_user->name, 832 'author_mail' => $this->admin_user->mail, 833 'author_id' => $this->admin_user->uid, 834 'author_ip' => ip_address(), 835 ); 836 837 // Ensure proper response for 'ham' submissions. 838 // By default (i.e., omitting 'checks') we expect spam and quality checking 839 // only. 840 $data['post_body'] = 'ham'; 841 $result = mollom('mollom.checkContent', $data); 842 $this->assertMollomWatchdogMessages(); 843 $this->assertSame('spam', $result['spam'], MOLLOM_ANALYSIS_HAM); 844 $this->assertSame('quality', $result['quality'], 1); 845 $this->assertTrue(!isset($result['profanity']), 'profanity not returned.'); 846 $session_id = $this->assertSessionID($result['session_id']); 847 848 // Ensure proper response for 'spam' submissions, re-using session_id. 849 $data['post_body'] = 'spam'; 850 $data['session_id'] = $session_id; 851 $result = mollom('mollom.checkContent', $data); 852 $this->assertMollomWatchdogMessages(); 853 $this->assertSame('spam', $result['spam'], MOLLOM_ANALYSIS_SPAM); 854 $this->assertSame('quality', $result['quality'], 0); 855 $this->assertTrue(!isset($result['profanity']), 'profanity not returned.'); 856 $session_id = $this->assertSessionID($result['session_id']); 857 858 // Ensure proper response for 'unsure' submissions, re-using session_id. 859 $data['post_body'] = 'unsure'; 860 $data['session_id'] = $session_id; 861 $result = mollom('mollom.checkContent', $data); 862 $this->assertMollomWatchdogMessages(); 863 $this->assertSame('spam', $result['spam'], MOLLOM_ANALYSIS_UNSURE); 864 $this->assertSame('quality', $result['quality'], 0.5); 865 $this->assertTrue(!isset($result['profanity']), 'profanity not returned.'); 866 $session_id = $this->assertSessionID($result['session_id']); 867 868 // Additionally enable profanity checking. 869 $data['post_body'] = 'spam profanity'; 870 $data['checks'] = 'spam,quality,profanity'; 871 $data['session_id'] = $session_id; 872 $result = mollom('mollom.checkContent', $data); 873 $this->assertMollomWatchdogMessages(); 874 $this->assertSame('spam', $result['spam'], MOLLOM_ANALYSIS_SPAM); 875 $this->assertSame('quality', $result['quality'], 0); 876 $this->assertSame('profanity', $result['profanity'], 1); 877 $session_id = $this->assertSessionID($result['session_id']); 878 879 // Change the string to contain profanity only. 880 $data['post_body'] = 'profanity'; 881 $data['checks'] = 'spam,quality,profanity'; 882 $data['session_id'] = $session_id; 883 $result = mollom('mollom.checkContent', $data); 884 $this->assertMollomWatchdogMessages(); 885 $this->assertSame('spam', $result['spam'], MOLLOM_ANALYSIS_UNSURE); 886 $this->assertSame('quality', $result['quality'], 0); 887 $this->assertSame('profanity', $result['profanity'], 1); 888 $session_id = $this->assertSessionID($result['session_id']); 889 890 // Disable spam checking, only do profanity checking. 891 $data['post_body'] = 'spam profanity'; 892 $data['checks'] = 'profanity'; 893 $data['session_id'] = $session_id; 894 $result = mollom('mollom.checkContent', $data); 895 $this->assertMollomWatchdogMessages(); 896 $this->assertTrue(!isset($result['spam']), 'spam not returned.'); 897 $this->assertTrue(!isset($result['quality']), 'quality not returned.'); 898 $this->assertSame('profanity', $result['profanity'], 1); 899 $session_id = $this->assertSessionID($result['session_id']); 900 901 // Pass arbitrary string to profanity checking. 902 $data['post_body'] = $this->randomString(12); 903 $data['session_id'] = $session_id; 904 $result = mollom('mollom.checkContent', $data); 905 $this->assertMollomWatchdogMessages(); 906 $this->assertTrue(!isset($result['spam']), 'spam not returned.'); 907 $this->assertTrue(!isset($result['quality']), 'quality not returned.'); 908 $this->assertSame('profanity', $result['profanity'], 0); 909 $session_id = $this->assertSessionID($result['session_id']); 910 } 911 912 /** 913 * Tests results of mollom.checkContent() across requests for a single session. 914 */ 915 function testCheckContentSession() { 916 $data = array( 917 'author_name' => $this->admin_user->name, 918 'author_mail' => $this->admin_user->mail, 919 'author_id' => $this->admin_user->uid, 920 'author_ip' => ip_address(), 921 ); 922 923 // Sequence: Post unsure spam, correct CAPTCHA, change post into spam, 924 // expect it to be ham (due to correct CAPTCHA). 925 $data['post_body'] = 'unsure'; 926 $result = mollom('mollom.checkContent', $data); 927 $this->assertMollomWatchdogMessages(); 928 $this->assertSame('spam', $result['spam'], MOLLOM_ANALYSIS_UNSURE); 929 $data['session_id'] = $this->assertSessionID($result['session_id']); 930 931 $captcha_data = array( 932 'session_id' => $data['session_id'], 933 'author_ip' => $data['author_ip'], 934 ); 935 $result = mollom('mollom.getImageCaptcha', $captcha_data); 936 $this->assertMollomWatchdogMessages(); 937 $data['session_id'] = $this->assertSessionID($result['session_id']); 938 939 $captcha_data = array( 940 'session_id' => $data['session_id'], 941 'author_ip' => $data['author_ip'], 942 'author_id' => $data['author_id'], 943 'captcha_result' => 'correct', 944 ); 945 $result = mollom('mollom.checkCaptcha', $captcha_data); 946 $this->assertMollomWatchdogMessages(); 947 $this->assertIdentical($result, TRUE, t('CAPTCHA response was correct.')); 948 949 $data['post_body'] = 'spam'; 950 $result = mollom('mollom.checkContent', $data); 951 $this->assertMollomWatchdogMessages(); 952 $this->assertSame('spam', $result['spam'], MOLLOM_ANALYSIS_HAM); 953 $data['session_id'] = $this->assertSessionID($result['session_id']); 954 } 955 956 /** 957 * Tests mollom.getImageCaptcha(). 958 */ 959 function testGetImageCaptcha() { 960 // Ensure we get no SSL URL by default. 961 $data = array( 962 'author_ip' => ip_address(), 963 ); 964 $result = mollom('mollom.getImageCaptcha', $data); 965 $this->assertMollomWatchdogMessages(); 966 $this->assertTrue(strpos($result['url'], 'http://') === 0, t('CAPTCHA URL uses HTTP protocol.')); 967 968 // Ensure we get a SSL URL when passing the 'ssl' parameter. 969 $data = array( 970 'author_ip' => ip_address(), 971 'ssl' => TRUE, 972 ); 973 $result = mollom('mollom.getImageCaptcha', $data); 974 $this->assertMollomWatchdogMessages(); 975 $this->assertTrue(strpos($result['url'], 'https://') === 0, t('CAPTCHA URL uses HTTPS protocol.')); 976 } 977 978 /** 979 * Tests mollom.checkCaptcha(). 980 */ 981 function testCheckCaptcha() { 982 // Ensure we can send an 'author_id'. 983 // Verifying no severe watchdog messages is sufficient, as unsupported 984 // parameters would trigger a XML-RPC error. 985 $uid = rand(); 986 $data = array( 987 'author_ip' => ip_address(), 988 'author_id' => $uid, 989 ); 990 $result = mollom('mollom.getImageCaptcha', $data); 991 $this->assertMollomWatchdogMessages(); 992 993 $data += array( 994 'session_id' => $result['session_id'], 995 'captcha_result' => 'correct', 996 ); 997 $result = mollom('mollom.checkCaptcha', $data); 998 $this->assertMollomWatchdogMessages(); 999 } 1000 } 1001 1002 class MollomAccessTestCase extends MollomWebTestCase { 1003 public static function getInfo() { 1004 return array( 1005 'name' => 'Access checking', 1006 'description' => 'Confirm that there is a working key pair and that this status is correctly indicated on the module settings page for appropriate users.', 1007 'group' => 'Mollom', 1008 ); 1009 } 1010 1011 /** 1012 * Configure an invalid key pair and ensure error message. 1013 */ 1014 function testKeyPairs() { 1015 // No error message or watchdog messages should be thrown with default 1016 // testing keys. 1017 $this->drupalLogin($this->admin_user); 1018 $this->drupalGet('admin/settings/mollom/settings'); 1019 1020 // Set up invalid test keys and check that an error message is shown. 1021 $edit = array( 1022 'mollom_public_key' => 'invalid-public-key', 1023 'mollom_private_key' => 'invalid-private-key', 1024 ); 1025 $this->drupalPost(NULL, $edit, t('Save configuration'), array('watchdog' => FALSE)); 1026 $this->assertText(t('The configuration options have been saved.')); 1027 $this->assertText('The configured Mollom API keys are invalid.'); 1028 } 1029 1030 /** 1031 * Make sure that the Mollom settings page works for users with the 1032 * 'administer mollom' permission but not those without 1033 * it. 1034 */ 1035 function testAdminAccessRights() { 1036 // Check access for a user that only has access to the 'administer 1037 // site configuration' permission. This user should have access to 1038 // the Mollom settings page. 1039 $this->drupalLogin($this->admin_user); 1040 $this->drupalGet('admin/settings/mollom'); 1041 $this->assertResponse(200); 1042 1043 // Check access for a user that has everything except the 'administer 1044 // mollom' permission. This user should not have access to the Mollom 1045 // settings page. 1046 $this->web_user = $this->drupalCreateUser(array_diff(module_invoke_all('perm'), array('administer mollom'))); 1047 $this->drupalLogin($this->web_user); 1048 $this->drupalGet('admin/settings/mollom'); 1049 $this->assertResponse(403); 1050 } 1051 1052 /** 1053 * Tests 'bypass access' property of registered forms. 1054 */ 1055 function testBypassAccess() { 1056 $this->drupalLogin($this->admin_user); 1057 $this->setProtection('comment_form'); 1058 $this->drupalLogout(); 1059 1060 $node = $this->drupalCreateNode(array('body' => 'node body', 'type' => 'story')); 1061 1062 // Create a regular user and post a comment. 1063 $this->web_user = $this->drupalCreateUser(); 1064 $this->drupalLogin($this->web_user); 1065 $edit = array( 1066 'comment' => 'ham', 1067 ); 1068 $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview')); 1069 1070 $this->drupalPost(NULL, array(), t('Save')); 1071 $this->assertText('node body'); 1072 $this->assertText($edit['comment']); 1073 1074 // Ensure a user having one of the permissions to bypass access can post 1075 // spam without triggering the spam protection. 1076 $this->drupalLogin($this->admin_user); 1077 $this->drupalGet('node/' . $node->nid); 1078 $this->clickLink('edit'); 1079 1080 $this->drupalPost(NULL, array('subject' => '', 'comment' => 'spam'), t('Preview')); 1081 $this->assertNoText($this->spam_message); 1082 1083 $this->drupalPost(NULL, array(), t('Save')); 1084 $this->assertNoText($this->spam_message); 1085 $this->assertText('node body'); 1086 1087 // Log in back the regular user and try to edit the comment containing spam. 1088 $this->drupalLogin($this->web_user); 1089 $this->drupalGet('node/' . $node->nid); 1090 $this->clickLink('edit'); 1091 1092 $this->drupalPost(NULL, array(), t('Preview')); 1093 $this->assertText($this->spam_message); 1094 1095 $this->drupalPost(NULL, array(), t('Save')); 1096 $this->assertText($this->spam_message); 1097 $this->assertNoText('node body'); 1098 } 1099 } 1100 1101 class MollomFallbackTestCase extends MollomWebTestCase { 1102 public static function getInfo() { 1103 return array( 1104 'name' => 'Fallback behavior', 1105 'description' => 'Check that the module uses the correct fallback mechanism when one or more of the specified Mollom servers are not available.', 1106 'group' => 'Mollom', 1107 ); 1108 } 1109 1110 function setUp() { 1111 // Enable testing server implementation. 1112 parent::setUp('mollom_test'); 1113 } 1114 1115 /** 1116 * Make sure that "request new password" submissions can be blocked when 1117 * the Mollom servers are unreachable. 1118 */ 1119 function testFallbackMechanismBlock() { 1120 // Enable Mollom for the request password form. 1121 $this->drupalLogin($this->admin_user); 1122 $this->setProtection('user_pass', MOLLOM_MODE_CAPTCHA); 1123 // Set the fallback strategy to 'blocking mode'. 1124 $this->drupalPost('admin/settings/mollom/settings', array('mollom_fallback' => MOLLOM_FALLBACK_BLOCK), t('Save configuration')); 1125 $this->assertText('The configuration options have been saved.'); 1126 $this->drupalLogout(); 1127 1128 // Configure Mollom to use a non-existent server as that should trigger 1129 // the fallback mechanism. 1130 variable_set('mollom_servers', array('http://fake-host')); 1131 1132 // Check the password request form. 1133 // @todo Test mail sending with assertMail() now that it is available. 1134 $this->drupalGet('user/password', array('watchdog' => FALSE)); 1135 $this->assertNoCaptchaField(); 1136 $this->assertText($this->fallback_message); 1137 } 1138 1139 /** 1140 * Make sure that "request new password" submissions can be allowed when 1141 * the Mollom servers are unreachable. 1142 */ 1143 function testFallbackMechanismAccept() { 1144 // Enable Mollom for the request password form. 1145 $this->drupalLogin($this->admin_user); 1146 $this->setProtection('user_pass', MOLLOM_MODE_CAPTCHA); 1147 // Set the fallback strategy to 'accept mode'. 1148 $this->drupalPost('admin/settings/mollom/settings', array('mollom_fallback' => MOLLOM_FALLBACK_ACCEPT), t('Save configuration')); 1149 $this->assertText('The configuration options have been saved.'); 1150 $this->drupalLogout(); 1151 1152 // Configure Mollom to use a non-existent server as that should trigger 1153 // the fallback mechanism. 1154 variable_set('mollom_servers', array('http://fake-host')); 1155 1156 // Check the password request form. 1157 $this->drupalGet('user/password', array('watchdog' => FALSE)); 1158 $this->assertNoCaptchaField(); 1159 $this->assertNoText($this->fallback_message); 1160 } 1161 1162 /** 1163 * Make sure that spam protection is still active even when some of the 1164 * Mollom servers are unavailable. 1165 * 1166 * @todo Test mail sending with assertMail() now that it is available. 1167 */ 1168 function testFailoverMechanism() { 1169 $this->drupalLogin($this->admin_user); 1170 $this->setProtection('user_pass', MOLLOM_MODE_CAPTCHA); 1171 $this->drupalLogout(); 1172 1173 // Set the fallback strategy to 'blocking mode', so that if the failover 1174 // mechanism does not work, we would expect to get a warning. 1175 variable_set('mollom_fallback', MOLLOM_FALLBACK_BLOCK); 1176 1177 // Configure Mollom to use a list of servers that have a number of 1178 // unknown servers, but one real server. 1179 variable_set('mollom_servers', array( 1180 'http://fake-host-1', 1181 'http://fake-host-2', 1182 $GLOBALS['base_url'] . '/xmlrpc.php?version=', 1183 'http://xmlrpc1.mollom.com', // The real server. 1184 'http://fake-host-3', 1185 )); 1186 1187 // Validate that the request password form has a CAPTCHA text field and 1188 // that a user is not blocked from submitting it. 1189 $this->drupalGet('user/password'); 1190 $this->assertCaptchaField(); 1191 $this->assertNoText($this->fallback_message); 1192 1193 $this->postCorrectCaptcha('user/password', array('name' => $this->admin_user->name), t('E-mail new password')); 1194 $this->assertText(t('Further instructions have been sent to your e-mail address.')); 1195 } 1196 } 1197 1198 class MollomServerListRecoveryTestCase extends MollomWebTestCase { 1199 public static function getInfo() { 1200 return array( 1201 'name' => 'Server list recovery', 1202 'description' => 'Check that the module can recover from an invalid server list.', 1203 'group' => 'Mollom', 1204 ); 1205 } 1206 1207 /** 1208 * Make sure the server list is reset when the Mollom servers are unavailable or incorrect. 1209 */ 1210 function testServerListRecovery() { 1211 $list = array( 1212 array( 1213 'http://not-a-valid-server-1', 1214 'http://not-a-valid-server-2', 1215 ), 1216 // The lack of the http://-schema results in different error codes 1217 array( 1218 'not-a-valid-server-url-1', 1219 'not-a-valid-server-url-2', 1220 ), 1221 ); 1222 1223 foreach ($list as $servers) { 1224 // Call mollom.verifyKey with an invalid server list. The expected behavior 1225 // is that the first call fails, but that the second call succeeds because 1226 // the server list is automatically reset or recovered by the Mollom module. 1227 variable_set('mollom_servers', $servers); 1228 1229 $key_is_valid = mollom('mollom.verifyKey'); 1230 $this->assertIdentical($key_is_valid, NETWORK_ERROR, t('The Mollom servers could not be contacted.')); 1231 $this->assertMollomWatchdogMessages(FALSE); 1232 1233 $key_is_valid = mollom('mollom.verifyKey'); 1234 $this->assertIdentical($key_is_valid, TRUE, t('The Mollom servers could be contacted.')); 1235 $this->assertMollomWatchdogMessages(); 1236 } 1237 } 1238 } 1239 1240 class MollomLanguageDetectionTestCase extends MollomWebTestCase { 1241 public static function getInfo() { 1242 return array( 1243 'name' => 'Language detection', 1244 'description' => 'Tests language detection functionality.', 1245 'group' => 'Mollom', 1246 ); 1247 } 1248 1249 /** 1250 * Test the language detection functionality at the API level without using a web interface. 1251 */ 1252 function testLanguageDetectionAPI() { 1253 // Note that Mollom supports more languages than those tested. 1254 $strings = array( 1255 'en' => "Hi, this is a test of the language detection code to see if it works well.", 1256 'nl' => "Hallo, dit is een test van de taaldetectiecode om te controleren of het werkt.", 1257 'fr' => "Bonjour, ceci est un test du detecteur langue automatique pour voir ci ça marche bien.", 1258 'de' => "Bedecke deinen Himmel, Zeus, Mit Wolkendunst Und übe, dem Knaben gleich, der Disteln köpft, An Eichen dich und Bergeshöhn.", 1259 'ko' => "'엄마야 누나야 강변살자. 뜰에는 반짝이는 금모래 빛. 뒷문 밖에는 갈잎의 노래", 1260 'ru' => "Холуй трясется. Раб хохочет. Палач свою секиру точит. Тиран кромсает каплуна. Сверкает зимняя луна.", 1261 'hu' => "Földszintiek mászófámról pillantva fejjel lefelé ti lógtok bele nézőim az űrbe ki tudja így kölcsönös kíváncsiak a helyes felelet kié", 1262 'el' => "Σαν να 'χουνε την όψη της αιώνες οργωμένη. Κάτι άναρχο κι ατέλειωτο στο πρόσωπό της μένει.", 1263 'ja' => "吹くからに秋の草木のしをるれば", 1264 'th' => "ทั่วประเทศ ประมาณ ๔๐,๐๐๐ แห่ง ชาวไทยนับตั้งแต่ครั้งอดีตมีวิถี ชีวิตผูกพันกับพุทธศาสนาอย่างใกล้ชิด แสดงออกมาเป็น ขนบธรรมเนียมประเพณี", 1265 'zh' => "螽斯羽,诜诜兮。宜尔子孙,振振兮", 1266 ); 1267 1268 foreach ($strings as $language => $text) { 1269 $result = mollom('mollom.detectLanguage', array('text' => $text)); 1270 $this->assertEqual($result[0]['language'], $language, t('A language code was specified and they match.')); 1271 $this->assertTrue($result[0]['confidence'] > 0, t('A confidence value was specified and it is greater than 0.')); 1272 } 1273 } 1274 } 1275 1276 /** 1277 * Tests blacklist functionality. 1278 * 1279 * The blacklists are stored on the server. These tests can fail when 1280 * different people run the tests at the same time because all tests share 1281 * the same blacklist. You can configure a custom key to avoid this. 1282 */ 1283 class MollomBlacklistTestCase extends MollomWebTestCase { 1284 public static function getInfo() { 1285 return array( 1286 'name' => 'Blacklisting', 1287 'description' => 'Tests URL and text blacklist functionality.', 1288 'group' => 'Mollom', 1289 ); 1290 } 1291 1292 /** 1293 * Test the URL blacklist functionality at the API level without using a web interface. 1294 */ 1295 function testUrlBlacklistAPI() { 1296 // Remove any stale blacklist entries from test runs that did not finish. 1297 $blacklist = mollom('mollom.listBlacklistURL'); 1298 foreach ($blacklist as $entry) { 1299 if (strtotime($entry['created']) - time() > 86400) { 1300 mollom('mollom.removeBlacklistURL', array('url' => $entry['url'])); 1301 } 1302 } 1303 1304 // Blacklist a URL. 1305 $domain = $this->randomName() . '.com'; 1306 $result = mollom('mollom.addBlacklistURL', array('url' => 'http://' . $domain)); 1307 $this->assertTrue($result, t('The URL was blacklisted.')); 1308 1309 // Check whether posts containing the blacklisted URL are properly blocked. 1310 $result = mollom('mollom.checkContent', array( 1311 'post_body' => "When the exact URL is present, the post should get blocked: http://{$domain}", 1312 )); 1313 $this->assertEqual($result['spam'], MOLLOM_ANALYSIS_SPAM, t('Exact URL match was blocked.')); 1314 1315 $result = mollom('mollom.checkContent', array( 1316 'post_body' => "When the URL is expanded in the back, the post should get blocked: http://{$domain}/oh-my", 1317 )); 1318 $this->assertEqual($result['spam'], MOLLOM_ANALYSIS_SPAM, t('Partial URL match was blocked.')); 1319 1320 $result = mollom('mollom.checkContent', array( 1321 'post_body' => "When the URL is expanded in the front, the post should get blocked: http://www.{$domain}", 1322 )); 1323 $this->assertEqual($result['spam'], MOLLOM_ANALYSIS_SPAM, t('URL with www-prefix was blocked.')); 1324 1325 $result = mollom('mollom.checkContent', array( 1326 'post_body' => "When the URL has a different schema, the post should get blocked: ftp://www.{$domain}", 1327 )); 1328 $this->assertEqual($result['spam'], MOLLOM_ANALYSIS_SPAM, t('URL with different schema was blocked.')); 1329 1330 // @todo Not implemented yet. 1331 /* 1332 $result = mollom('mollom.checkContent', array( 1333 'post_body' => "When the domain appears on its own, the post should get blocked: www.{$domain}", 1334 )); 1335 $this->assertEqual($result['spam'], MOLLOM_ANALYSIS_SPAM, t('Plain domain name with www-prefix was blocked.')); 1336 */ 1337 1338 $result = mollom('mollom.removeBlacklistURL', array('url' => 'http://' . $domain)); 1339 $this->assertTrue($result, t('The blacklisted URL was removed.')); 1340 } 1341 1342 /** 1343 * Test the text blacklist functionality at the API level without using a web interface. 1344 */ 1345 function testTextBlacklistAPI() { 1346 // Remove any stale blacklist entries from test runs that did not finish. 1347 $blacklist = mollom('mollom.listBlacklistText'); 1348 foreach ($blacklist as $entry) { 1349 if (strtotime($entry['created']) - time() > 86400) { 1350 mollom('mollom.removeBlacklistText', array('text' => $entry['text'])); 1351 } 1352 } 1353 1354 // Blacklist a word. 1355 // @todo As of now, only non-numeric, lower-case text seems to be supported. 1356 $term = drupal_strtolower(preg_replace('/[^a-zA-Z]/', '', $this->randomName())); 1357 $result = mollom('mollom.addBlacklistText', array( 1358 'text' => $term, 1359 'match' => 'contains', 1360 'reason' => 'spam', 1361 )); 1362 $this->assertIdentical($result, TRUE, t('The text was blacklisted.')); 1363 1364 // Check whether posts containing the blacklisted word are properly blocked. 1365 $result = mollom('mollom.checkContent', array( 1366 'post_body' => $term, 1367 )); 1368 $this->assertEqual($result['spam'], MOLLOM_ANALYSIS_SPAM, t('Identical match was blocked.')); 1369 1370 $result = mollom('mollom.checkContent', array( 1371 'post_body' => "When the term is present, the post should get blocked: " . $term, 1372 )); 1373 $this->assertEqual($result['spam'], MOLLOM_ANALYSIS_SPAM, t('Exact match was blocked.')); 1374 1375 $result = mollom('mollom.checkContent', array( 1376 'post_body' => "When match is 'contains', the word can be surrounded by other text: abc" . $term . "def", 1377 )); 1378 $this->assertEqual($result['spam'], MOLLOM_ANALYSIS_SPAM, t('Partial match was blocked.')); 1379 1380 // To update the work (i.e. to change the 'match' property), we simply 1381 // overwrite it. 1382 $result = mollom('mollom.addBlacklistText', array( 1383 'text' => $term, 1384 'match' => 'exact', 1385 'reason' => 'spam', 1386 )); 1387 $this->assertTrue($result, t('The text was blacklisted.')); 1388 1389 $result = mollom('mollom.checkContent', array( 1390 'post_body' => "When match is 'exact', it has to be exact: " . $term, 1391 )); 1392 $this->assertEqual($result['spam'], MOLLOM_ANALYSIS_SPAM, t('Exact match was blocked.')); 1393 1394 $result = mollom('mollom.checkContent', array( 1395 'post_body' => "When match is 'exact', it has to be exact: abc{$term}def", 1396 )); 1397 $this->assertNotEqual($result['spam'], MOLLOM_ANALYSIS_SPAM, t('Partial match was not blocked.')); 1398 1399 $result = mollom('mollom.removeBlacklistText', array('text' => $term)); 1400 $this->assertTrue($result, t('The blacklisted text was removed.')); 1401 } 1402 1403 /** 1404 * Test the blacklist administration interface. 1405 * 1406 * We don't need to check whether the blacklisting actually works 1407 * (i.e. blocks posts) because that is tested in testTextBlacklistAPI() and 1408 * testURLBlacklistAPI(). 1409 */ 1410 function testBlacklistUI() { 1411 // Log in as an administrator and access the blacklist administration page. 1412 $this->drupalLogin($this->admin_user); 1413 1414 // Add a word to the spam blacklist. 1415 $this->drupalGet('admin/settings/mollom/blacklist'); 1416 $text = $this->randomName(); 1417 $edit = array( 1418 'entry[context]' => 'everything', 1419 'entry[text]' => $text, 1420 ); 1421 $this->drupalPost(NULL, $edit, t('Add')); 1422 $this->assertText(t('The entry was added to the blacklist.')); 1423 $this->assertText($text); 1424 1425 // Remove the word from the spam blacklist. 1426 $links = $this->xpath('//td[contains(., "' . $text . '")]/following-sibling::td/a'); 1427 $delete_url = $GLOBALS['base_root'] . (string) $links[0]['href']; 1428 $this->drupalGet($delete_url); 1429 $this->drupalPost(NULL, array(), t('Delete')); 1430 $this->assertEqual($this->getUrl(), url('admin/settings/mollom/blacklist', array('absolute' => TRUE)), t('Correct page redirection.')); 1431 $this->assertNoText($text, 'Text blacklist removed.'); 1432 1433 // Add a word to the profanity blacklist. 1434 $this->drupalGet('admin/settings/mollom/blacklist/profanity'); 1435 $text = $this->randomName(); 1436 $edit = array( 1437 'entry[context]' => 'everything', 1438 'entry[text]' => $text, 1439 ); 1440 $this->drupalPost(NULL, $edit, t('Add')); 1441 $this->assertText(t('The entry was added to the blacklist.')); 1442 $this->assertText($text); 1443 1444 // Remove the word from the profanity blacklist. 1445 $links = $this->xpath('//td[contains(., "' . $text . '")]/following-sibling::td/a'); 1446 $delete_url = $GLOBALS['base_root'] . (string) $links[0]['href']; 1447 $this->drupalGet($delete_url); 1448 $this->drupalPost(NULL, array(), t('Delete')); 1449 $this->assertEqual($this->getUrl(), url('admin/settings/mollom/blacklist/profanity', array('absolute' => TRUE)), t('Correct page redirection.')); 1450 $this->assertNoText($text, 'Text blacklist removed.'); 1451 } 1452 } 1453 1454 /** 1455 * Tests Mollom form configuration functionality. 1456 */ 1457 class MollomFormConfigurationTestCase extends MollomWebTestCase { 1458 public static function getInfo() { 1459 return array( 1460 'name' => 'Form administration', 1461 'description' => 'Verify that forms can be properly protected and unprotected.', 1462 'group' => 'Mollom', 1463 ); 1464 } 1465 1466 function setUp() { 1467 parent::setUp('mollom_test'); 1468 // Re-route Mollom communication to this testing site. 1469 variable_set('mollom_servers', array($GLOBALS['base_url'] . '/xmlrpc.php?version=')); 1470 1471 $this->drupalLogin($this->admin_user); 1472 } 1473 1474 /** 1475 * Tests configuration of form fields for textual analysis. 1476 */ 1477 function testFormFieldsConfiguration() { 1478 // Protect Mollom test form. 1479 $this->drupalGet('admin/settings/mollom/add'); 1480 $edit = array( 1481 'mollom[form_id]' => 'mollom_test_form', 1482 ); 1483 $this->drupalPost(NULL, $edit, t('Next')); 1484 $this->assertText('Mollom test form'); 1485 $edit = array( 1486 'mollom[mode]' => MOLLOM_MODE_ANALYSIS, 1487 'mollom[enabled_fields][title]' => TRUE, 1488 'mollom[enabled_fields][body]' => TRUE, 1489 'mollom[enabled_fields][exclude]' => FALSE, 1490 'mollom[enabled_fields][' . rawurlencode('parent][child') . ']' => TRUE, 1491 'mollom[enabled_fields][field]' => TRUE, 1492 ); 1493 $this->drupalPost(NULL, $edit, t('Save')); 1494 1495 // Verify that mollom_test_form form was protected. 1496 $this->assertText(t('The form protection has been added.')); 1497 $this->assertText('Mollom test form'); 1498 $mollom_form = mollom_form_load('mollom_test_form'); 1499 $this->assertTrue($mollom_form, t('Form configuration exists.')); 1500 1501 // Verify that field configuration was properly stored. 1502 $this->drupalGet('admin/settings/mollom/manage/mollom_test_form'); 1503 foreach ($edit as $name => $value) { 1504 // Skip any inputs that are not the fields for analysis checkboxes. 1505 if (strpos($name, '[enabled_fields]') === FALSE) { 1506 continue; 1507 } 1508 // assertFieldByName() does not work for checkboxes. 1509 // @see assertFieldChecked() 1510 $elements = $this->xpath('//input[@name="' . $name . '"]'); 1511 if (isset($elements[0])) { 1512 if ($value) { 1513 $this->assertTrue(!empty($elements[0]['checked']), t('Field @name is checked', array('@name' => $name))); 1514 } 1515 else { 1516 $this->assertTrue(empty($elements[0]['checked']), t('Field @name is not checked', array('@name' => $name))); 1517 } 1518 } 1519 else { 1520 $this->fail(t('Field @name not found.', array('@name' => $name))); 1521 } 1522 } 1523 1524 // Add a field to the stored configuration that existed previously. 1525 $mollom_form['enabled_fields'][] = 'orphan_field'; 1526 mollom_form_save($mollom_form); 1527 1528 // Verify that field configuration contains only available elements. 1529 $this->drupalGet('admin/settings/mollom/manage/mollom_test_form'); 1530 $form_info = mollom_form_info('mollom_test_form', 'mollom_test'); 1531 $fields = $this->xpath('//input[starts-with(@name, "mollom[enabled_fields]")]'); 1532 $elements = array(); 1533 foreach ($fields as $field) { 1534 $elements[] = substr(substr(rawurldecode($field['name']), 0, -1), 23); 1535 } 1536 $this->assertEqual($elements, array_keys($form_info['elements']), t('Field list only contains available form elements.')); 1537 1538 // Try a simple submit of the form. 1539 $this->drupalLogout(); 1540 $edit = array( 1541 'title' => 'unsure', 1542 ); 1543 $this->drupalPost('mollom-test/form', $edit, 'Submit'); 1544 $this->assertNoText('Successful form submission.'); 1545 $this->assertText($this->unsure_message); 1546 $this->postCorrectCaptcha(NULL, array(), 'Submit', 'Successful form submission.'); 1547 1548 // Try to submit values for top-level fields. 1549 $edit = array( 1550 'title' => 'spam', 1551 'body' => 'spam', 1552 ); 1553 $this->drupalPost('mollom-test/form', $edit, 'Submit'); 1554 $this->assertNoText('Successful form submission.'); 1555 $this->assertNoText($this->unsure_message); 1556 $this->assertText($this->spam_message); 1557 1558 // Try to submit values for nested field. 1559 $edit = array( 1560 'title' => $this->randomString(), 1561 'parent[child]' => 'spam', 1562 ); 1563 $this->drupalPost('mollom-test/form', $edit, 'Submit'); 1564 $this->assertNoText('Successful form submission.'); 1565 $this->assertNoText($this->unsure_message); 1566 $this->assertText($this->spam_message); 1567 1568 // Try to submit values for nested field and multiple value field. 1569 // Start with ham values for simple, nested, and first multiple field. 1570 $edit = array( 1571 'title' => 'ham', 1572 'parent[child]' => 'ham', 1573 'field[new]' => 'ham', 1574 ); 1575 $this->drupalPost('mollom-test/form', $edit, 'Add'); 1576 1577 // Verify that the form was rebuilt. 1578 $this->assertNoText('Successful form submission.'); 1579 $this->assertNoText($this->unsure_message); 1580 $this->assertNoText($this->spam_message); 1581 1582 // Add another value for multiple field. 1583 $edit = array( 1584 'field[new]' => 'ham', 1585 ); 1586 $this->drupalPost(NULL, $edit, 'Add'); 1587 1588 // Verify that the form was rebuilt. 1589 $this->assertNoText('Successful form submission.'); 1590 $this->assertNoText($this->unsure_message); 1591 $this->assertNoText($this->spam_message); 1592 1593 // Now replace all ham values with random values, add a spam value to the 1594 // multiple field and submit the form. 1595 $edit = array( 1596 'title' => $this->randomString(), 1597 'parent[child]' => $this->randomString(), 1598 'field[0]' => $this->randomString(), 1599 'field[1]' => $this->randomString(), 1600 'field[new]' => 'spam', 1601 ); 1602 $this->drupalPost(NULL, $edit, 'Submit'); 1603 1604 // Verify that the form was not submitted and cannot be submitted. 1605 $this->assertNoText('Successful form submission.'); 1606 $this->assertText($this->spam_message); 1607 } 1608 1609 /** 1610 * Tests default configuration, protecting, and unprotecting forms. 1611 */ 1612 function testFormAdministration() { 1613 $form_info = mollom_form_list(); 1614 foreach ($form_info as $form_id => $info) { 1615 $form_info[$form_id] += mollom_form_info($form_id, $info['module']); 1616 } 1617 1618 // Verify that user registration form is not protected. 1619 $this->drupalGet('admin/settings/mollom'); 1620 $this->assertNoText($form_info['user_register']['title']); 1621 $this->assertFalse(mollom_form_load('user_register'), t('Form configuration does not exist.')); 1622 1623 // Re-protect user registration form. 1624 $this->drupalGet('admin/settings/mollom/add'); 1625 $this->assertNoText(t('All available forms are protected already.')); 1626 $edit = array( 1627 'mollom[form_id]' => 'user_register', 1628 ); 1629 $this->drupalPost(NULL, $edit, t('Next')); 1630 $this->assertText($form_info['user_register']['title']); 1631 $this->assertNoText(t('Text fields to analyze')); 1632 $this->drupalPost(NULL, array(), t('Save')); 1633 1634 // Verify that user registration form was protected. 1635 $this->assertText(t('The form protection has been added.')); 1636 $this->assertText($form_info['user_register']['title']); 1637 $this->assertTrue(mollom_form_load('user_register'), t('Form configuration exists.')); 1638 1639 // Iterate over all unconfigured forms and protect them. 1640 foreach ($form_info as $form_id => $info) { 1641 if (!mollom_form_load($form_id)) { 1642 $edit = array( 1643 'mollom[form_id]' => $form_id, 1644 ); 1645 $this->drupalPost('admin/settings/mollom/add', $edit, t('Next')); 1646 $this->assertText($info['title']); 1647 // Verify that forms specifying elements have all possible elements 1648 // preselected for textual analysis. 1649 $edit = array(); 1650 if (!empty($info['elements'])) { 1651 foreach ($info['elements'] as $field => $label) { 1652 $field = rawurlencode($field); 1653 $this->assertFieldByName("mollom[enabled_fields][$field]", TRUE); 1654 } 1655 } 1656 // Verify that CAPTCHA-only forms contain no configurable fields. 1657 else { 1658 $this->assertNoText(t('Analyze text for')); 1659 $this->assertNoText(t('Text fields to analyze')); 1660 } 1661 $this->drupalPost(NULL, $edit, t('Save')); 1662 $this->assertText(t('The form protection has been added.')); 1663 } 1664 } 1665 1666 // Verify that trying to add a form redirects to the overview. 1667 $this->drupalGet('admin/settings/mollom/add'); 1668 $this->assertText(t('All available forms are protected already.')); 1669 $this->assertText(t('Operations')); 1670 } 1671 1672 /** 1673 * Tests programmatically, conditionally disabling Mollom. 1674 */ 1675 function testFormAlter() { 1676 // Enable CAPTCHA-only protection for request user password form. 1677 $this->drupalLogin($this->admin_user); 1678 $this->setProtection('user_pass', MOLLOM_MODE_CAPTCHA); 1679 $this->drupalLogout(); 1680 1681 // Verify regular form protection. 1682 $this->drupalGet('user/password'); 1683 $this->assertCaptchaField(); 1684 1685 // Conditionally disable protection and verify again. 1686 variable_set('mollom_test_disable_mollom', TRUE); 1687 $this->drupalGet('user/password'); 1688 $this->assertNoCaptchaField(); 1689 } 1690 } 1691 1692 class MollomUserFormsTestCase extends MollomWebTestCase { 1693 public static function getInfo() { 1694 return array( 1695 'name' => 'User registration and password protection', 1696 'description' => 'Check that the user registration and password request forms can be protected.', 1697 'group' => 'Mollom', 1698 ); 1699 } 1700 1701 /** 1702 * Make sure that the request password form is protected correctly. 1703 * 1704 * @todo Test mail sending with assertMail() now that it is available. 1705 */ 1706 function testProtectRequestPassword() { 1707 // We first enable Mollom for the request password form. 1708 $this->drupalLogin($this->admin_user); 1709 $this->setProtection('user_pass', MOLLOM_MODE_CAPTCHA); 1710 $this->drupalLogout(); 1711 1712 // Create a new user. 1713 $this->web_user = $this->drupalCreateUser(); 1714 1715 $this->drupalGet('user/password'); 1716 1717 // Try to reset the user's password by specifying an invalid CAPTCHA. 1718 $edit = array('name' => $this->web_user->name); 1719 $this->postIncorrectCaptcha('user/password', $edit, t('E-mail new password')); 1720 $this->postCorrectCaptcha(NULL, array(), t('E-mail new password')); 1721 1722 // Try to reset the user's password by specifying a valid CAPTCHA. 1723 $this->postCorrectCaptcha('user/password', $edit, t('E-mail new password')); 1724 $this->assertText(t('Further instructions have been sent to your e-mail address.')); 1725 } 1726 1727 /** 1728 * Make sure that the user registration form is protected correctly. 1729 */ 1730 function testProtectRegisterUser() { 1731 // We first enable Mollom for the user registration form. 1732 $this->drupalLogin($this->admin_user); 1733 $this->setProtection('user_register', MOLLOM_MODE_CAPTCHA); 1734 $this->drupalLogout(); 1735 1736 // Validate that the user registration form has a CAPTCHA text field. 1737 $this->drupalGet('user/register'); 1738 $this->assertCaptchaField(); 1739 1740 // Try to register with an invalid CAPTCHA. Make sure the user did not 1741 // successfully register. 1742 $name = $this->randomName(); 1743 $edit = array( 1744 'name' => $name, 1745 'mail' => $name . '@example.com', 1746 ); 1747 $this->postIncorrectCaptcha('user/register', $edit, t('Create new account')); 1748 $this->assertFalse(user_load(array('name' => $name)), t('The user who attempted to register cannot be found in the database when the CAPTCHA is invalid.')); 1749 1750 // Try to register with a valid CAPTCHA. Make sure the user was able 1751 // to successfully register. 1752 $this->postCorrectCaptcha('user/register', $edit, t('Create new account')); 1753 $this->assertText(t('Your password and further instructions have been sent to your e-mail address.')); 1754 $this->assertTrue(user_load(array('name' => $name)), t('The user who attempted to register appears in the database when the CAPTCHA is valid.')); 1755 } 1756 } 1757 1758 class MollomCommentFormTestCase extends MollomWebTestCase { 1759 private $node; 1760 1761 public static function getInfo() { 1762 return array( 1763 'name' => 'Comment form protection', 1764 'description' => 'Check that the comment submission form can be protected.', 1765 'group' => 'Mollom', 1766 ); 1767 } 1768 1769 function setUp() { 1770 parent::setUp('comment'); 1771 1772 $this->web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'post comments without approval', 'create story content')); 1773 $this->node = $this->drupalCreateNode(array('type' => 'story', 'uid' => $this->web_user->uid)); 1774 variable_set('comment_preview_story', COMMENT_PREVIEW_OPTIONAL); 1775 } 1776 1777 /** 1778 * Make sure that the comment submission form can be unprotected. 1779 */ 1780 function testUnprotectedCommentForm() { 1781 // Request the comment reply form. There should be no CAPTCHA. 1782 $this->drupalLogin($this->web_user); 1783 $this->drupalGet('comment/reply/'. $this->node->nid); 1784 $this->assertNoCaptchaField(); 1785 $this->assertNoPrivacyLink(); 1786 1787 // Preview a comment that is 'spam' and make sure there is still no CAPTCHA. 1788 $this->drupalPost(NULL, array('comment' => 'spam'), t('Preview')); 1789 $this->assertNoCaptchaField(); 1790 $this->assertNoPrivacyLink(); 1791 1792 // Save the comment and make sure it appears. 1793 $this->drupalPost(NULL, array(), t('Save')); 1794 $this->assertRaw('<p>spam</p>', t('A comment that is known to be spam appears on the screen after it is submitted.')); 1795 } 1796 1797 /** 1798 * Make sure that the comment submission form can be protected by captcha only. 1799 */ 1800 function testCaptchaProtectedCommentForm() { 1801 // Enable Mollom CAPTCHA protection for comments. 1802 $this->drupalLogin($this->admin_user); 1803 $this->setProtection('comment_form', MOLLOM_MODE_CAPTCHA); 1804 $this->drupalLogout(); 1805 1806 // Request the comment reply form. There should be a CAPTCHA form. 1807 $this->drupalLogin($this->web_user); 1808 $this->drupalGet('comment/reply/' . $this->node->nid); 1809 $this->assertCaptchaField(); 1810 $this->assertSessionIDInForm(); 1811 $this->assertNoPrivacyLink(); 1812 1813 // Try to submit an incorrect answer for the CAPTCHA, without value for 1814 // required field. 1815 $this->postIncorrectCaptcha(NULL, array(), t('Preview')); 1816 $this->assertText(t('Comment field is required.')); 1817 $this->assertSessionIDInForm(); 1818 $this->assertNoPrivacyLink(); 1819 1820 // Try to submit a correct answer for the CAPTCHA, still without required 1821 // field value. 1822 $this->postCorrectCaptcha(NULL, array(), t('Preview')); 1823 $this->assertText(t('Comment field is required.')); 1824 $session_id = $this->assertSessionIDInForm(); 1825 $this->assertNoPrivacyLink(); 1826 1827 // Finally, we should be able to submit a comment. 1828 $this->drupalPost(NULL, array('comment' => 'spam'), t('Save')); 1829 $this->assertRaw('<p>spam</p>', t('Spam comment could be posted with correct CAPTCHA.')); 1830 $cid = db_result(db_query("SELECT cid FROM {comments} WHERE comment = '%s' ORDER BY timestamp DESC", array('spam'))); 1831 $this->assertMollomData('comment', $cid, $session_id); 1832 } 1833 1834 /** 1835 * Make sure that the comment submission form can be fully protected. 1836 */ 1837 function testTextAnalysisProtectedCommentForm() { 1838 // Enable Mollom text-classification for comments. 1839 $this->drupalLogin($this->admin_user); 1840 $this->setProtection('comment_form'); 1841 $this->drupalLogout(); 1842 1843 // Request the comment reply form. Initially, there should be no CAPTCHA. 1844 $this->drupalLogin($this->web_user); 1845 $this->drupalGet('comment/reply/'. $this->node->nid); 1846 $this->assertNoCaptchaField(); 1847 $this->assertPrivacyLink(); 1848 1849 // Try to save a comment that is 'unsure' and make sure there is a CAPTCHA. 1850 $edit = array( 1851 'comment' => 'unsure', 1852 ); 1853 $this->drupalPost(NULL, $edit, t('Save')); 1854 $this->assertCaptchaField(); 1855 $session_id = $this->assertSessionIDInForm(); 1856 $this->assertPrivacyLink(); 1857 1858 // Try to submit the form by solving the CAPTCHA incorrectly. At this point, 1859 // the submission should be blocked and a new CAPTCHA generated, but only if 1860 // the comment is still neither ham or spam. 1861 $this->postIncorrectCaptcha(NULL, array(), t('Save')); 1862 $this->assertCaptchaField(); 1863 $session_id = $this->assertSessionIDInForm(); 1864 $this->assertPrivacyLink(); 1865 1866 // Correctly solving the CAPTCHA should accept the form submission. 1867 $this->postCorrectCaptcha(NULL, array(), t('Save')); 1868 $this->assertRaw('<p>' . $edit['comment'] . '</p>', t('A comment that may contain spam was found.')); 1869 $cid = db_result(db_query("SELECT cid FROM {comments} WHERE comment = '%s' ORDER BY timestamp DESC", array($edit['comment']))); 1870 $this->assertMollomData('comment', $cid, $session_id); 1871 1872 // Try to save a new 'spam' comment; it should be rejected, with no CAPTCHA 1873 // appearing on the page. 1874 $this->resetSessionID(); 1875 $this->drupalGet('comment/reply/' . $this->node->nid); 1876 $this->assertPrivacyLink(); 1877 $original_number_of_comments = $this->getCommentCount($this->node->nid); 1878 $this->assertSpamSubmit(NULL, array('comment'), array(), t('Save')); 1879 $session_id = $this->assertSessionIDInForm(); 1880 $this->assertCommentCount($this->node->nid, $original_number_of_comments); 1881 $this->assertPrivacyLink(); 1882 1883 // Try to save again; it should be rejected, with no CAPTCHA. 1884 $this->assertSpamSubmit(NULL, array('comment'), array(), t('Save')); 1885 $session_id = $this->assertSessionIDInForm(); 1886 $this->assertCommentCount($this->node->nid, $original_number_of_comments); 1887 $this->assertPrivacyLink(); 1888 1889 // Save a new 'ham' comment. 1890 $this->resetSessionID(); 1891 $this->drupalGet('comment/reply/' . $this->node->nid); 1892 $this->assertPrivacyLink(); 1893 $original_number_of_comments = $this->getCommentCount($this->node->nid); 1894 $this->assertHamSubmit(NULL, array('comment'), array(), t('Save')); 1895 $this->assertRaw('<p>ham</p>', t('A comment that is known to be ham appears on the screen after it is submitted.')); 1896 $this->assertCommentCount($this->node->nid, $original_number_of_comments + 1); 1897 $cid = db_result(db_query("SELECT cid FROM {comments} WHERE comment = '%s' ORDER BY timestamp DESC", array('ham'))); 1898 $this->assertMollomData('comment', $cid); 1899 } 1900 1901 /** 1902 * Return the number of comments for a node of the given node ID. We 1903 * can't use comment_num_all() here, because that is statically cached 1904 * and therefore will not work correctly with the SimpleTest browser. 1905 */ 1906 private function getCommentCount($nid) { 1907 return db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $nid)); 1908 } 1909 1910 /** 1911 * Test that the number of comments for a node matches an expected value. 1912 * 1913 * @param $nid 1914 * A node ID 1915 * @param $expected 1916 * An integer with the expected number of comments for the node. 1917 * @param $message 1918 * An optional string with the message to be used in the assertion. 1919 */ 1920 protected function assertCommentCount($nid, $expected, $message = '') { 1921 $actual = $this->getCommentCount($nid); 1922 if (!$message) { 1923 $message = t('Node @nid has @actual comment(s), expected @expected.', array('@nid' => $nid, '@actual' => $actual, '@expected' => $expected)); 1924 } 1925 $this->assertEqual($actual, $expected, $message); 1926 } 1927 } 1928 1929 class MollomContactFormTestCase extends MollomWebTestCase { 1930 public static function getInfo() { 1931 return array( 1932 'name' => 'Contact form protection', 1933 'description' => 'Check that the contact form can be protected.', 1934 'group' => 'Mollom', 1935 ); 1936 } 1937 1938 function setUp() { 1939 parent::setUp('contact'); 1940 1941 $this->web_user = $this->drupalCreateUser(array('access site-wide contact form', 'access user profiles')); 1942 } 1943 1944 /** 1945 * Make sure that the user contact form is protected correctly. 1946 * 1947 * @todo Test mail sending with assertMail() now that it is available. 1948 */ 1949 function testProtectContactUserForm() { 1950 // Enable Mollom for the contact form. 1951 $this->drupalLogin($this->admin_user); 1952 $this->setProtection('contact_mail_user'); 1953 $this->drupalLogout(); 1954 1955 $this->drupalLogin($this->web_user); 1956 $url = 'user/' . $this->admin_user->uid . '/contact'; 1957 $button = t('Send e-mail'); 1958 $success = t('The message has been sent.'); 1959 1960 // Submit a 'spam' message. This should be blocked. 1961 $this->assertSpamSubmit($url, array('subject', 'message'), array(), $button); 1962 $this->assertNoText($success); 1963 1964 // Submit a 'ham' message. This should be accepted. 1965 $this->assertHamSubmit($url, array('subject', 'message'), array(), $button); 1966 $this->assertText($success); 1967 1968 // Submit an 'unsure' message. This should be accepted only after the 1969 // CAPTCHA has been solved. 1970 $this->assertUnsureSubmit($url, array('subject', 'message'), array(), $button, $success); 1971 } 1972 1973 /** 1974 * Make sure that the site-wide contact form is protected correctly. 1975 * 1976 * @todo Test mail sending with assertMail() now that it is available. 1977 */ 1978 function testProtectContactSiteForm() { 1979 // Enable Mollom for the contact form. 1980 $this->drupalLogin($this->admin_user); 1981 $this->setProtection('contact_mail_page'); 1982 $this->drupalLogout(); 1983 1984 // Add some fields to the contact form so that it is active. 1985 // Empty 'reply' so as to not have to fiddle with auto-reply messages. 1986 $this->drupalLogin($this->web_user); 1987 db_query("INSERT INTO {contact} (category, recipients, reply) VALUES ('%s', '%s', '%s')", 'test category', $this->web_user->mail, ''); 1988 1989 $url = 'contact'; 1990 $button = t('Send e-mail'); 1991 $success = t('Your message has been sent.'); 1992 1993 // Submit a 'spam' message. This should be blocked. 1994 $this->assertSpamSubmit($url, array('subject', 'message'), array(), $button); 1995 $this->assertNoText($success); 1996 1997 // Submit a 'ham' message. This should be accepted. 1998 $this->assertHamSubmit($url, array('subject', 'message'), array(), $button); 1999 $this->assertText($success); 2000 $report_link = $this->parseMollomMailReportLink(); 2001 $this->assertTrue($report_link, t('Report to Mollom link found in e-mail.')); 2002 $this->assertEqual($report_link['entity'], 'session', t('Report link in e-mail uses entity type "session".')); 2003 $this->assertMollomData($report_link['entity'], $report_link['session_id']); 2004 2005 // Submit an 'unsure' message. This should be accepted only after the 2006 // CAPTCHA has been solved. 2007 $this->assertUnsureSubmit($url, array('subject', 'message'), array(), $button, $success); 2008 $report_link = $this->parseMollomMailReportLink(); 2009 $this->assertTrue($report_link, t('Report to Mollom link found in e-mail.')); 2010 $this->assertEqual($report_link['entity'], 'session', t('Report link in e-mail uses entity type "session".')); 2011 $this->assertMollomData($report_link['entity'], $report_link['session_id']); 2012 2013 // Report the mail to Mollom. 2014 $this->drupalGet($report_link['url']); 2015 $edit = array( 2016 'feedback' => 'spam', 2017 ); 2018 $this->drupalPost(NULL, $edit, t('Delete')); 2019 $this->assertText(t('The content was successfully reported as inappropriate.')); 2020 } 2021 2022 /** 2023 * Returns data about the report to Mollom link in the last sent mail. 2024 * 2025 * Contrary to DrupalWebTestCase::assertMail(), this function removes the last 2026 * sent mail from the internally recorded stack. 2027 */ 2028 function parseMollomMailReportLink() { 2029 // Grab the last sent mail. 2030 // @see DrupalWebTestCase::assertMail() 2031 $captured_emails = variable_get('drupal_test_email_collector', array()); 2032 $email = array_pop($captured_emails); 2033 variable_set('drupal_test_email_collector', $captured_emails); 2034 2035 $found = FALSE; 2036 if (preg_match('@http.+?mollom/report/([^/]+)/([^\s]+)@', $email['body'], $matches)) { 2037 $found = array( 2038 'url' => $matches[0], 2039 'entity' => $matches[1], 2040 'session_id' => $matches[2], 2041 'mail' => $email, 2042 ); 2043 } 2044 return $found; 2045 } 2046 } 2047 2048 class MollomResellerTestCase extends MollomWebTestCase { 2049 public static function getInfo() { 2050 return array( 2051 'name' => 'Reseller functionality', 2052 'description' => 'Check that the reseller APIs are working properly.', 2053 'group' => 'Mollom', 2054 ); 2055 } 2056 2057 /** 2058 * Make sure that resellers can create a new site. 2059 */ 2060 function testKeyManagement() { 2061 if (!$this->is_reseller) { 2062 // If the current test keys are not reseller keys, skip this test. 2063 return; 2064 } 2065 2066 // Create 3 test sites: 2067 for ($i = 1; $i <= 3; $i++) { 2068 $keys[] = mollom('mollom.createSite', array( 2069 'url' => 'http://example.com/site-'. $i, 2070 'mail' => 'mail@example.com', 2071 'status' => 0, 2072 'testing' => 1, 2073 )); 2074 } 2075 2076 // Assert that there were no XML-RPC errors or watchdog messages. 2077 $this->assertMollomWatchdogMessages(); 2078 2079 $sites = mollom('mollom.listSites'); 2080 foreach ($sites as $site) { 2081 // Retrieve the site information: 2082 $details = mollom('mollom.getSite', array('client_key' => $site)); 2083 2084 $this->assertEqual($details['mail'], 'mail@example.com', t('The original information is correctly retrieved from Mollom.')); 2085 $this->assertEqual($details['status'], 0, t('The original information is correctly retrieved from Mollom.')); 2086 $this->assertEqual($details['testing'], 1, t('The original information is correctly retrieved from Mollom.')); 2087 2088 // Perform a safety check to avoid that the tests would delete 2089 // valid sites in case someone messed up their Mollom settings! 2090 if ($details['mail'] == 'mail@example.com' || $details['mail'] == 'root@example.com') { 2091 // Update the information on the site and verify that it was updated. 2092 mollom('mollom.updateSite', array('client_key' => $site, 'mail' => 'root@example.com')); 2093 $details = mollom('mollom.getSite', array('client_key' => $site)); 2094 $this->assertEqual($details['mail'], 'root@example.com', t('The updated information is correctly retrieved from Mollom.')); 2095 2096 // Verify that the existing information did not change (partial updates). 2097 $this->assertEqual($details['status'], 0, t('The original information is correctly retrieved from Mollom.')); 2098 $this->assertEqual($details['testing'], 1, t('The original information is correctly retrieved from Mollom.')); 2099 2100 // Delete the test site: 2101 mollom('mollom.deleteSite', array('client_key' => $site)); 2102 } 2103 else { 2104 $this->fail(t('We tried to delete a non-test site.')); 2105 } 2106 } 2107 2108 // Assert that there were no XML-RPC errors or watchdog messages. 2109 $this->assertMollomWatchdogMessages(); 2110 2111 // Retrieve information about a non-existing site: 2112 $details = mollom('mollom.getSite', array('client_key' => 'bogus')); 2113 $this->assertEqual(xmlrpc_errno(), TRUE, t('Retrieving information from a non-existing site returned an XML-RPC error.')); 2114 $this->assertMollomWatchdogMessages(FALSE); 2115 2116 // Verify that all sites have been deleted: 2117 $sites = mollom('mollom.listSites'); 2118 $this->assertEqual(count($sites), 0, t('All Mollom sites have been deleted.')); 2119 } 2120 } 2121 2122 /** 2123 * Tests form value processing. 2124 */ 2125 class MollomDataTestCase extends MollomWebTestCase { 2126 public static function getInfo() { 2127 return array( 2128 'name' => 'Data processing', 2129 'description' => 'Verify that form registry information is properly transformed into data that is sent to Mollom servers.', 2130 'group' => 'Mollom', 2131 ); 2132 } 2133 2134 function setUp() { 2135 // Enable testing server implementation. 2136 parent::setUp('mollom_test'); 2137 // Re-route Mollom communication to this testing site. 2138 variable_set('mollom_servers', array($GLOBALS['base_url'] . '/xmlrpc.php?version=')); 2139 } 2140 2141 /** 2142 * Test mollom_form_get_values(). 2143 */ 2144 function testFormGetValues() { 2145 global $user; 2146 2147 // Form registry information. 2148 $form_info = array( 2149 'elements' => array( 2150 'subject' => 'Subject', 2151 'message' => 'Message', 2152 'parent][child' => 'Some nested element', 2153 ), 2154 'mapping' => array( 2155 'post_title' => 'subject', 2156 'author_name' => 'name', 2157 'author_mail' => 'mail', 2158 ), 2159 ); 2160 // Fields configured via Mollom admin UI based on $form_info['elements']. 2161 $fields = array( 2162 'subject', 2163 'message', 2164 'parent][child', 2165 ); 2166 2167 // Verify submitted form values for an anonymous/arbitrary user. 2168 $values = array( 2169 'subject' => 'Foo', 2170 'message' => 'Bar', 2171 'parent' => array( 2172 'child' => 'Beer', 2173 ), 2174 'name' => 'Drupaler', 2175 'mail' => 'drupaler@example.com', 2176 ); 2177 $data = mollom_form_get_values($values, $fields, $form_info['mapping']); 2178 2179 $this->assertSame('post_title', $data['post_title'], $values['subject']); 2180 $this->assertSame('post_body', $data['post_body'], $values['message'] . "\n" . $values['parent']['child']); 2181 $this->assertSame('author_name', $data['author_name'], $values['name']); 2182 $this->assertSame('author_mail', $data['author_mail'], $values['mail']); 2183 $this->assertFalse(isset($data['author_url']), t('author_url: Undefined.')); 2184 $this->assertFalse(isset($data['author_openid']), t('author_openid: Undefined.')); 2185 $this->assertFalse(isset($data['author_id']), t('author_id: Undefined.')); 2186 $this->assertSame('author_ip', $data['author_ip'], ip_address()); 2187 2188 // Verify submitted form values for an registered user. 2189 $values = array( 2190 'subject' => 'Foo', 2191 'message' => 'Bar', 2192 'name' => $this->admin_user->name, 2193 ); 2194 $data = mollom_form_get_values($values, $fields, $form_info['mapping']); 2195 2196 $this->assertSame('post_title', $data['post_title'], $values['subject']); 2197 $this->assertSame('post_body', $data['post_body'], $values['message']); 2198 $this->assertSame('author_name', $data['author_name'], $this->admin_user->name); 2199 $this->assertSame('author_mail', $data['author_mail'], $this->admin_user->mail); 2200 $this->assertFalse(isset($data['author_url']), t('author_url: Undefined.')); 2201 // @todo Test this. 2202 $this->assertFalse(isset($data['author_openid']), t('author_openid: Undefined.')); 2203 $this->assertSame('author_id', $data['author_id'], $this->admin_user->uid); 2204 $this->assertSame('author_ip', $data['author_ip'], ip_address()); 2205 } 2206 2207 /** 2208 * Test submitted post and author information for textual analysis. 2209 */ 2210 function testAnalysis() { 2211 $this->drupalLogin($this->admin_user); 2212 $this->setProtection('comment_form'); 2213 2214 // Make comment preview optional. 2215 $edit = array( 2216 'comment_preview' => 0, 2217 ); 2218 $this->drupalPost('admin/content/node-type/story', $edit, t('Save content type')); 2219 2220 // Create a node we can comment on. 2221 $node = $this->drupalCreateNode(array('type' => 'story', 'promote' => 1)); 2222 $this->drupalGet(''); 2223 $this->assertText($node->title); 2224 2225 // Log in regular user and post a comment. 2226 $this->drupalLogout(); 2227 $this->web_user = $this->drupalCreateUser(); 2228 $this->drupalLogin($this->web_user); 2229 $this->drupalGet(''); 2230 $this->clickLink(t('Add new comment')); 2231 2232 $edit = array( 2233 'subject' => $this->randomString(), 2234 'comment' => 'unsure', 2235 ); 2236 $this->drupalPost(NULL, $edit, t('Save')); 2237 $this->assertText($this->unsure_message); 2238 2239 // Verify that submitted data equals post data. 2240 $data = $this->getServerRecord(); 2241 $this->assertSame('post_title', $data['post_title'], $edit['subject']); 2242 $this->assertSame('post_body', $data['post_body'], $edit['comment']); 2243 $this->assertSame('author_name', $data['author_name'], $this->web_user->name); 2244 $this->assertSame('author_mail', $data['author_mail'], $this->web_user->mail); 2245 $this->assertSame('author_id', $data['author_id'], $this->web_user->uid); 2246 2247 $this->PostCorrectCaptcha(NULL, array(), t('Save')); 2248 $comment = db_fetch_object(db_query("SELECT * FROM {comments} WHERE subject = '%s'", $edit['subject'])); 2249 $this->assertTrue($comment, t('Comment exists in database.')); 2250 2251 // Verify that submitted data equals post data. 2252 $data = $this->getServerRecord('mollom.checkCaptcha'); 2253 $this->assertSame('author_id', $data['author_id'], $this->web_user->uid); 2254 2255 // Allow anonymous users to post comments without approval. 2256 $this->drupalLogin($this->admin_user); 2257 $edit = array( 2258 DRUPAL_ANONYMOUS_RID . '[access comments]' => TRUE, 2259 DRUPAL_ANONYMOUS_RID . '[post comments]' => TRUE, 2260 DRUPAL_ANONYMOUS_RID . '[post comments without approval]' => TRUE, 2261 ); 2262 $this->drupalPost('admin/user/permissions', $edit, t('Save permissions')); 2263 2264 // Allow anonymous users to post contact information. 2265 $edit = array( 2266 'comment_anonymous' => COMMENT_ANONYMOUS_MAY_CONTACT, 2267 ); 2268 $this->drupalPost('admin/content/node-type/story', $edit, t('Save content type')); 2269 2270 // Log out and post a comment as anonymous user. 2271 $this->resetServerRecords(); 2272 $this->drupalLogout(); 2273 $this->drupalGet('node/' . $node->nid); 2274 $this->clickLink(t('Add new comment')); 2275 // Ensure we have some potentially escaped characters in the values. 2276 $edit = array( 2277 'name' => $this->randomString(6) . ' & ' . $this->randomString(8), 2278 'mail' => 'mollom@example.com', 2279 'homepage' => 'http://mollom.com', 2280 'subject' => '"' . $this->randomString() . '"', 2281 'comment' => 'unsure', 2282 ); 2283 $this->drupalPost(NULL, $edit, t('Save')); 2284 $this->assertText($this->unsure_message); 2285 2286 // Verify that submitted data equals post data. 2287 $data = $this->getServerRecord(); 2288 $this->assertSame('post_title', $data['post_title'], $edit['subject']); 2289 $this->assertSame('post_body', $data['post_body'], $edit['comment']); 2290 $this->assertSame('author_name', $data['author_name'], $edit['name']); 2291 $this->assertSame('author_mail', $data['author_mail'], $edit['mail']); 2292 $this->assertSame('author_url', $data['author_url'], $edit['homepage']); 2293 $this->assertFalse(isset($data['author_id']), t('author_id: Undefined.')); 2294 2295 $this->PostCorrectCaptcha(NULL, array(), t('Save')); 2296 $comment = db_fetch_object(db_query("SELECT * FROM {comments} WHERE subject = '%s'", $edit['subject'])); 2297 $this->assertTrue($comment, t('Comment exists in database.')); 2298 2299 // Verify that submitted data equals post data. 2300 $data = $this->getServerRecord('mollom.checkCaptcha'); 2301 $this->assertSame('author_id', $data['author_id'], NULL); 2302 2303 // Log in admin user and edit comment containing spam. 2304 $this->resetServerRecords(); 2305 $this->drupalLogin($this->admin_user); 2306 $this->drupalGet('comment/edit/' . $comment->cid); 2307 // Post without modification. 2308 $this->drupalPost(NULL, array(), t('Save')); 2309 2310 // Verify that no data was submitted to Mollom. 2311 $data = $this->getServerRecord(); 2312 $this->assertFalse($data, t('Administrative form submission was not validated by Mollom.')); 2313 } 2314 2315 /** 2316 * Tests automated 'post_id' mapping and session data storage. 2317 * 2318 * This is an atomic test to verify that a simple 'post_id' mapping defined 2319 * via hook_mollom_form_info() is sufficient for basic integration with 2320 * Mollom (without reporting). 2321 */ 2322 function testPostIdMapping() { 2323 // Enable protection for mollom_test_form. 2324 $this->drupalLogin($this->admin_user); 2325 $this->setProtection('mollom_test_form'); 2326 $this->drupalLogout(); 2327 2328 // Submit a mollom_test thingy. 2329 $edit = array( 2330 'title' => 'ham', 2331 'body' => $this->randomString(), 2332 ); 2333 $this->drupalPost('mollom-test/form', $edit, 'Submit'); 2334 $this->assertText('Successful form submission.'); 2335 $mid = $this->getFieldValueByName('mid'); 2336 $this->assertTrue($mid > 0, t('Submission was stored.')); 2337 $data = $this->assertMollomData('mollom_test', $mid); 2338 2339 // Ensure we were redirected to the form for the stored entry. 2340 $this->assertFieldByName('body', $edit['body'], t('Existing body value found.')); 2341 $new_mid = $this->getFieldValueByName('mid'); 2342 $this->assertEqual($new_mid, $mid, t('Existing entity id found.')); 2343 2344 // Update the stored entry. 2345 $edit['title'] = 'unsure'; 2346 $this->drupalPost(NULL, $edit, 'Submit'); 2347 $this->assertCaptchaField(); 2348 $this->postCorrectCaptcha(NULL, array(), 'Submit', 'Successful form submission.'); 2349 $new_data = $this->assertMollomData('mollom_test', $mid); 2350 2351 // Verify that only session data was updated. 2352 $this->assertSame('entity', $data->entity, $new_data->entity); 2353 $this->assertSame('id', $data->did, $new_data->did); 2354 $this->assertNotSame('session_id', $data->session, $new_data->session); 2355 $this->assertSame('quality', $data->quality, $new_data->quality); 2356 $count = db_result(db_query("SELECT COUNT(1) FROM {mollom}")); 2357 $this->assertEqual($count, 1, t('Stored data in {mollom} was updated.')); 2358 } 2359 2360 /** 2361 * Tests data sent for mollom.verifyKey. 2362 */ 2363 function testVerifyKey() { 2364 $this->drupalLogin($this->admin_user); 2365 $this->drupalGet('admin/settings/mollom/settings'); 2366 2367 // Verify that we additionally sent version data. 2368 $data = $this->getServerRecord('mollom.verifyKey'); 2369 $info = _mollom_get_version(); 2370 $this->assertTrue(!empty($info['platform_name']), t('Version information found.')); 2371 $this->assertSame('platform_name', $data['platform_name'], $info['platform_name']); 2372 $this->assertSame('platform_version', $data['platform_version'], $info['platform_version']); 2373 $this->assertSame('client_name', $data['client_name'], $info['client_name']); 2374 $this->assertSame('client_version', $data['client_version'], $info['client_version']); 2375 } 2376 } 2377 2378 /** 2379 * Tests report to Mollom functionality. 2380 */ 2381 class MollomReportTestCase extends MollomWebTestCase { 2382 public static function getInfo() { 2383 return array( 2384 'name' => 'Reporting functionality', 2385 'description' => 'Verify that session data is properly stored and content can be reported to Mollom.', 2386 'group' => 'Mollom', 2387 ); 2388 } 2389 2390 function setUp() { 2391 parent::setUp('comment'); 2392 2393 $this->web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'post comments without approval', 'create story content')); 2394 } 2395 2396 /** 2397 * Tests reporting comments. 2398 */ 2399 function testReportComment() { 2400 $this->drupalLogin($this->admin_user); 2401 $this->setProtection('comment_form'); 2402 $this->drupalLogout(); 2403 2404 $this->node = $this->drupalCreateNode(array('type' => 'story')); 2405 variable_set('comment_preview_story', COMMENT_PREVIEW_OPTIONAL); 2406 2407 // Post a comment. 2408 $this->drupalLogin($this->web_user); 2409 $edit = array( 2410 'comment' => 'ham', 2411 ); 2412 $this->drupalPost('comment/reply/' . $this->node->nid, $edit, t('Save')); 2413 $this->comment = db_fetch_object(db_query("SELECT * FROM {comments} WHERE comment = '%s' AND nid = %d", array($edit['comment'], $this->node->nid))); 2414 $this->assertTrue($this->comment, t('Comment was found in the database.')); 2415 $this->assertMollomData('comment', $this->comment->cid); 2416 2417 // Log in comment administrator and verify that we can report to Mollom. 2418 $this->drupalLogin($this->admin_user); 2419 $this->drupalGet('node/' . $this->node->nid); 2420 $this->assertText($edit['comment'], t('Comment found.')); 2421 $this->clickLink('report to Mollom'); 2422 $edit = array( 2423 'feedback' => 'spam', 2424 ); 2425 $this->drupalPost(NULL, $edit, t('Delete')); 2426 $this->assertText(t('The comment has been deleted.')); 2427 $this->assertText(t('The content was successfully reported as inappropriate.')); 2428 2429 // Verify that the comment and Mollom session data has been deleted. 2430 $this->assertFalse(_comment_load($this->comment->cid), t('Comment was deleted.')); 2431 $this->assertNoMollomData('comment', $this->comment->cid); 2432 } 2433 2434 /** 2435 * Tests mass-reporting comments. 2436 */ 2437 function testMassReportComments() { 2438 $this->drupalLogin($this->admin_user); 2439 $this->setProtection('comment_form'); 2440 $this->drupalLogout(); 2441 2442 $this->node = $this->drupalCreateNode(array('type' => 'story')); 2443 variable_set('comment_preview_story', COMMENT_PREVIEW_OPTIONAL); 2444 2445 // Post 3 comments. 2446 $this->drupalLogin($this->web_user); 2447 $this->comments = array(); 2448 foreach (range(1, 3) as $num) { 2449 $edit = array( 2450 'subject' => $this->randomName(), 2451 'comment' => 'ham', 2452 ); 2453 $this->drupalPost('comment/reply/' . $this->node->nid, $edit, t('Save')); 2454 $this->comments[$num] = db_fetch_object(db_query("SELECT * FROM {comments} WHERE subject = '%s' AND nid = %d", array($edit['subject'], $this->node->nid))); 2455 $this->assertTrue($this->comments[$num], t('Comment was found in the database.')); 2456 $this->assertMollomData('comment', $this->comments[$num]->cid); 2457 } 2458 2459 // Log in comment administrator and verify that we can mass-report all 2460 // comments to Mollom. 2461 $this->drupalLogin($this->admin_user); 2462 $this->drupalGet('admin/content/comment'); 2463 $edit = array( 2464 'operation' => 'mollom-unpublish', 2465 ); 2466 foreach ($this->comments as $comment) { 2467 $this->assertText($comment->subject, t('Comment found.')); 2468 $edit["comments[{$comment->cid}]"] = TRUE; 2469 } 2470 $this->drupalPost(NULL, $edit, t('Update')); 2471 $this->assertText(t('The selected comments have been reported as inappropriate and are unpublished.')); 2472 2473 // Verify that unpublished comments are found in approval queue and 2474 // mass-report all comments again to delete them. 2475 $this->drupalGet('admin/content/comment/approval'); 2476 $edit['operation'] = 'mollom-delete'; 2477 foreach ($this->comments as $comment) { 2478 $this->assertText($comment->subject, t('Comment found.')); 2479 } 2480 $this->drupalPost(NULL, $edit, t('Update')); 2481 $this->assertText(t('The selected comments have been reported as inappropriate and are deleted.')); 2482 2483 // Verify that the comments and Mollom session data has been deleted. 2484 foreach ($this->comments as $comment) { 2485 $this->assertFalse(_comment_load($comment->cid), t('Comment was deleted.')); 2486 $this->assertNoMollomData('comment', $comment->cid); 2487 } 2488 } 2489 } 2490
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |