source: sipes/modules_contrib/captcha/captcha.test @ 177a560

stableversion-3.0
Last change on this file since 177a560 was 177a560, checked in by José Gregorio Puentes <jpuentes@…>, 8 años ago

se agrego el directorio de modulos contribuidos de drupal

  • Propiedad mode establecida a 100755
File size: 43.4 KB
Línea 
1<?php
2
3/**
4 * @file
5 * Tests for CAPTCHA module.
6 */
7
8// TODO: write test for CAPTCHAs on admin pages
9// TODO: test for default challenge type
10// TODO: test about placement (comment form, node forms, log in form, etc)
11// TODO: test if captcha_cron does it work right
12// TODO: test custom CAPTCHA validation stuff
13// TODO: test if entry on status report (Already X blocked form submissions) works
14// TODO: test space ignoring validation of image CAPTCHA
15
16
17// Some constants for better reuse.
18define('CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE',
19  'The answer you entered for the CAPTCHA was not correct.');
20
21define('CAPTCHA_SESSION_REUSE_ATTACK_ERROR_MESSAGE',
22  'CAPTCHA session reuse attack detected.');
23
24define('CAPTCHA_UNKNOWN_CSID_ERROR_MESSAGE',
25  'CAPTCHA validation error: unknown CAPTCHA session ID. Contact the site administrator if this problem persists.');
26
27
28
29/**
30 * Base class for CAPTCHA tests.
31 *
32 * Provides common setup stuff and various helper functions
33 */
34abstract class CaptchaBaseWebTestCase extends DrupalWebTestCase {
35
36  /**
37   * User with various administrative permissions.
38   * @var Drupal user
39   */
40  protected $admin_user;
41
42  /**
43   * Normal visitor with limited permissions
44   * @var Drupal user;
45   */
46  protected $normal_user;
47
48  /**
49   * Form ID of comment form on standard (page) node
50   * @var string
51   */
52  const COMMENT_FORM_ID = 'comment_form';
53
54  /**
55   * Drupal path of the (general) CAPTCHA admin page
56   */
57  const CAPTCHA_ADMIN_PATH = 'admin/user/captcha';
58
59
60  function setUp() {
61    // Load two modules: the captcha module itself and the comment module for testing anonymous comments.
62    parent::setUp('captcha', 'comment');
63    module_load_include('inc', 'captcha');
64
65    // Create a normal user.
66    $permissions = array(
67      'access comments', 'post comments', 'post comments without approval',
68      'access content', 'create page content', 'edit own page content',
69    );
70    $this->normal_user = $this->drupalCreateUser($permissions);
71
72    // Create an admin user.
73    $permissions[] = 'administer CAPTCHA settings';
74    $permissions[] = 'skip CAPTCHA';
75    $permissions[] = 'administer permissions';
76    $permissions[] = 'administer content types';
77    $this->admin_user = $this->drupalCreateUser($permissions);
78
79  }
80
81  /**
82   * Assert that the response is accepted:
83   * no "unknown CSID" message, no "CSID reuse attack detection" message,
84   * no "wrong answer" message.
85   */
86  protected function assertCaptchaResponseAccepted() {
87    // There should be no error message about unknown CAPTCHA session ID.
88    $this->assertNoText(t(CAPTCHA_UNKNOWN_CSID_ERROR_MESSAGE),
89      'CAPTCHA response should be accepted (known CSID).',
90      'CAPTCHA');
91    // There should be no error message about CSID reuse attack.
92    $this->assertNoText(t(CAPTCHA_SESSION_REUSE_ATTACK_ERROR_MESSAGE),
93      'CAPTCHA response should be accepted (no CAPTCHA session reuse attack detection).',
94      'CAPTCHA');
95    // There should be no error message about wrong response.
96    $this->assertNoText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
97      'CAPTCHA response should be accepted (correct response).',
98      'CAPTCHA');
99  }
100
101  /**
102   * Assert that there is a CAPTCHA on the form or not.
103   * @param bool $presence whether there should be a CAPTCHA or not.
104   */
105  protected function assertCaptchaPresence($presence) {
106    if ($presence) {
107      $this->assertText(_captcha_get_description(),
108        'There should be a CAPTCHA on the form.', 'CAPTCHA');
109    }
110    else {
111      $this->assertNoText(_captcha_get_description(),
112        'There should be no CAPTCHA on the form.', 'CAPTCHA');
113    }
114  }
115
116  /**
117   * Helper function to create a node with comments enabled.
118   *
119   * @return
120   *   Created node object.
121   */
122  protected function createNodeWithCommentsEnabled($type='page') {
123    $node_settings = array(
124      'type' => $type,
125      'comment' => COMMENT_NODE_READ_WRITE,
126    );
127    $node = $this->drupalCreateNode($node_settings);
128    return $node;
129  }
130
131  /**
132   * Helper function to generate a form values array for comment forms
133   */
134  protected function getCommentFormValues() {
135    $edit = array(
136      'subject' => 'comment_subject ' . $this->randomName(32),
137      'comment' => 'comment_body ' . $this->randomName(256),
138    );
139    return $edit;
140  }
141
142  /**
143   * Helper function to generate a form values array for node forms
144   */
145  protected function getNodeFormValues() {
146    $edit = array(
147      'title' => 'node_title ' . $this->randomName(32),
148      'body' => 'node_body ' . $this->randomName(256),
149    );
150    return $edit;
151  }
152
153
154  /**
155   * Get the CAPTCHA session id from the current form in the browser.
156   */
157  protected function getCaptchaSidFromForm() {
158    $elements = $this->xpath('//input[@name="captcha_sid"]');
159    $captcha_sid = (int) $elements[0]['value'];
160    return $captcha_sid;
161  }
162  /**
163   * Get the CAPTCHA token from the current form in the browser.
164   */
165  protected function getCaptchaTokenFromForm() {
166    $elements = $this->xpath('//input[@name="captcha_token"]');
167    $captcha_token = (int) $elements[0]['value'];
168    return $captcha_token;
169  }
170
171  /**
172   * Get the solution of the math CAPTCHA from the current form in the browser.
173   */
174  protected function getMathCaptchaSolutionFromForm() {
175    // Get the math challenge.
176    $elements = $this->xpath('//div[@id="edit-captcha-response-wrapper"]/span[@class="field-prefix"]');
177    $challenge = (string) $elements[0];
178    // Extract terms and operator from challenge.
179    $matches = array();
180    $ret = preg_match('/\\s*(\\d+)\\s*(-|\\+)\\s*(\\d+)\\s*=\\s*/', $challenge, $matches);
181    // Solve the challenge
182    $a = (int) $matches[1];
183    $b = (int) $matches[3];
184    $solution = $matches[2] == '-' ? $a - $b : $a + $b;
185    return $solution;
186  }
187
188  /**
189   * Helper function to allow comment posting for anonymous users.
190   */
191  protected function allowCommentPostingForAnonymousVisitors() {
192    // Log in as admin.
193    $this->drupalLogin($this->admin_user);
194    // Post user permissions form
195    $edit = array(
196      '1[access comments]' => true,
197      '1[post comments]' => true,
198      '1[post comments without approval]' => true,
199    );
200    $this->drupalPost('admin/user/permissions', $edit, 'Save permissions');
201    $this->assertText('The changes have been saved.');
202    // Log admin out
203    $this->drupalLogout();
204  }
205
206}
207
208
209
210class CaptchaTestCase extends CaptchaBaseWebTestCase {
211
212  public static function getInfo() {
213    return array(
214      'name' => t('General CAPTCHA functionality'),
215      'description' => t('Testing of the basic CAPTCHA functionality.'),
216      'group' => t('CAPTCHA'),
217    );
218  }
219
220  /**
221   * Testing the protection of the user log in form.
222   */
223  function testCaptchaOnLoginForm() {
224    // Create user and test log in without CAPTCHA.
225    $user = $this->drupalCreateUser();
226    $this->drupalLogin($user);
227    // Log out again.
228    $this->drupalLogout();
229
230    // Set a CAPTCHA on login form
231    captcha_set_form_id_setting('user_login', 'captcha/Math');
232
233    // Check if there is a CAPTCHA on the login form (look for the title).
234    $this->drupalGet('user');
235    $this->assertCaptchaPresence(TRUE);
236
237    // Try to log in, which should fail.
238    $edit = array(
239      'name' => $user->name,
240      'pass' => $user->pass_raw,
241      'captcha_response' => '?',
242    );
243    $this->drupalPost('user', $edit, t('Log in'));
244    // Check for error message.
245    $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
246      'CAPTCHA should block user login form', 'CAPTCHA');
247
248    // And make sure that user is not logged in: check for name and password fields on ?q=user
249    $this->drupalGet('user');
250    $this->assertField('name', t('Username field found.'), 'CAPTCHA');
251    $this->assertField('pass', t('Password field found.'), 'CAPTCHA');
252
253  }
254
255
256  /**
257   * Assert function for testing if comment posting works as it should.
258   *
259   * Creates node with comment writing enabled, tries to post comment
260   * with given CAPTCHA response (caller should enable the desired
261   * challenge on page node comment forms) and checks if the result is as expected.
262   *
263   * @param $captcha_response the response on the CAPTCHA
264   * @param $should_pass boolean describing if the posting should pass or should be blocked
265   * @param $message message to prefix to nested asserts
266   */
267  protected function assertCommentPosting($captcha_response, $should_pass, $message) {
268    // Make sure comments on pages can be saved directely without preview.
269    variable_set('comment_preview_page', COMMENT_PREVIEW_OPTIONAL);
270
271    // Create a node with comments enabled.
272    $node = $this->createNodeWithCommentsEnabled();
273
274    // Post comment on node.
275    $edit = $this->getCommentFormValues();
276    $comment_subject = $edit['subject'];
277    $comment_body = $edit['comment'];
278    $edit['captcha_response'] = $captcha_response;
279    $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Save'));
280
281    if ($should_pass) {
282      // There should be no error message.
283      $this->assertCaptchaResponseAccepted();
284      // Get node page and check that comment shows up.
285      $this->drupalGet('node/' . $node->nid);
286      $this->assertText($comment_subject, $message .' Comment should show up on node page.', 'CAPTCHA');
287      $this->assertText($comment_body, $message .' Comment should show up on node page.', 'CAPTCHA');
288    }
289    else {
290      // Check for error message.
291      $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE), $message .' Comment submission should be blocked.', 'CAPTCHA');
292      // Get node page and check that comment is not present.
293      $this->drupalGet('node/' . $node->nid);
294      $this->assertNoText($comment_subject, $message .' Comment should not show up on node page.', 'CAPTCHA');
295      $this->assertNoText($comment_body, $message .' Comment should not show up on node page.', 'CAPTCHA');
296    }
297  }
298
299  /*
300   * Testing the case sensistive/insensitive validation.
301   */
302  function testCaseInsensitiveValidation() {
303    // Set Test CAPTCHA on comment form
304    captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Test');
305
306    // Log in as normal user.
307    $this->drupalLogin($this->normal_user);
308
309    // Test case sensitive posting.
310    variable_set('captcha_default_validation', CAPTCHA_DEFAULT_VALIDATION_CASE_SENSITIVE);
311    $this->assertCommentPosting('Test 123', TRUE, 'Case sensitive validation of right casing.');
312    $this->assertCommentPosting('test 123', FALSE, 'Case sensitive validation of wrong casing.');
313    $this->assertCommentPosting('TEST 123', FALSE, 'Case sensitive validation of wrong casing.');
314
315    // Test case insensitive posting (the default)
316    variable_set('captcha_default_validation', CAPTCHA_DEFAULT_VALIDATION_CASE_INSENSITIVE);
317    $this->assertCommentPosting('Test 123', TRUE, 'Case insensitive validation of right casing.');
318    $this->assertCommentPosting('test 123', TRUE, 'Case insensitive validation of wrong casing.');
319    $this->assertCommentPosting('TEST 123', TRUE, 'Case insensitive validation of wrong casing.');
320
321  }
322
323  /**
324   * Test if the CAPTCHA description is only shown if there are challenge widgets to show.
325   * For example, when a comment is previewed with correct CAPTCHA answer,
326   * a challenge is generated and added to the form but removed in the pre_render phase.
327   * The CAPTCHA description should not show up either.
328   *
329   * \see testCaptchaSessionReuseOnNodeForms()
330   */
331  function testCaptchaDescriptionAfterCommentPreview() {
332    // Set Test CAPTCHA on comment form.
333    captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Test');
334
335    // Log in as normal user.
336    $this->drupalLogin($this->normal_user);
337
338    // Create a node with comments enabled.
339    $node = $this->createNodeWithCommentsEnabled();
340
341    // Preview comment with correct CAPTCHA answer.
342    $edit = $this->getCommentFormValues();
343    $edit['captcha_response'] = 'Test 123';
344    $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview'));
345
346    // Check that there is no CAPTCHA after preview.
347    $this->assertCaptchaPresence(FALSE);
348  }
349
350  /**
351   * Test if the CAPTCHA session ID is reused when previewing nodes:
352   * node preview after correct response should not show CAPTCHA anymore.
353   * The preview functionality of comments and nodes works slightly different under the hood.
354   * CAPTCHA module should be able to handle both.
355   *
356   * \see testCaptchaDescriptionAfterCommentPreview()
357   */
358  function testCaptchaSessionReuseOnNodeForms() {
359    // Set Test CAPTCHA on page form.
360    captcha_set_form_id_setting('page_node_form', 'captcha/Test');
361
362    // Log in as normal user.
363    $this->drupalLogin($this->normal_user);
364
365    // Page settings to post, with correct CAPTCHA answer.
366    $edit = $this->getNodeFormValues();
367    $edit['captcha_response'] = 'Test 123';
368    // Preview the node
369    $this->drupalPost('node/add/page', $edit, t('Preview'));
370
371    // Check that there is no CAPTCHA after preview.
372    $this->assertCaptchaPresence(FALSE);
373  }
374
375
376  /**
377   * CAPTCHA should also be put on admin pages even if visitor
378   * has no access
379   */
380  function testCaptchaOnLoginBlockOnAdminPagesIssue893810() {
381    // Set a CAPTCHA on login block form
382    captcha_set_form_id_setting('user_login_block', 'captcha/Math');
383
384    // Check if there is a CAPTCHA on home page.
385    $this->drupalGet('node');
386    $this->assertCaptchaPresence(TRUE);
387
388    // Check there is a CAPTCHA on "forbidden" admin pages
389    $this->drupalGet('admin');
390    $this->assertCaptchaPresence(TRUE);
391  }
392
393}
394
395
396class CaptchaAdminTestCase extends CaptchaBaseWebTestCase {
397
398  public static function getInfo() {
399    return array(
400      'name' => t('CAPTCHA administration functionality'),
401      'description' => t('Testing of the CAPTCHA administration interface and functionality.'),
402      'group' => t('CAPTCHA'),
403    );
404  }
405
406  /**
407   * Test access to the admin pages.
408   */
409  function testAdminAccess() {
410    $this->drupalLogin($this->normal_user);
411    $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
412    file_put_contents('tmp.simpletest.html', $this->drupalGetContent());
413    $this->assertText(t('Access denied'), 'Normal users should not be able to access the CAPTCHA admin pages', 'CAPTCHA');
414
415    $this->drupalLogin($this->admin_user);
416    $this->drupalGet(self::CAPTCHA_ADMIN_PATH);
417    $this->assertNoText(t('Access denied'), 'Admin users should be able to access the CAPTCHA admin pages', 'CAPTCHA');
418  }
419
420  /**
421   * Test the CAPTCHA point setting getter/setter.
422   */
423  function testCaptchaPointSettingGetterAndSetter() {
424    $comment_form_id = self::COMMENT_FORM_ID;
425    // Set to 'none'.
426    captcha_set_form_id_setting($comment_form_id, 'none');
427    $result = captcha_get_form_id_setting($comment_form_id);
428    $this->assertNotNull($result, 'Setting and getting CAPTCHA point: none', 'CAPTCHA');
429    $this->assertNull($result->module, 'Setting and getting CAPTCHA point: none', 'CAPTCHA');
430    $this->assertNull($result->captcha_type, 'Setting and getting CAPTCHA point: none', 'CAPTCHA');
431    $result = captcha_get_form_id_setting($comment_form_id, TRUE);
432    $this->assertEqual($result, 'none', 'Setting and symbolic getting CAPTCHA point: "none"', 'CAPTCHA');
433    // Set to 'default'
434    captcha_set_form_id_setting($comment_form_id, 'default');
435    variable_set('captcha_default_challenge', 'foo/bar');
436    $result = captcha_get_form_id_setting($comment_form_id);
437    $this->assertNotNull($result, 'Setting and getting CAPTCHA point: default', 'CAPTCHA');
438    $this->assertEqual($result->module, 'foo', 'Setting and getting CAPTCHA point: default', 'CAPTCHA');
439    $this->assertEqual($result->captcha_type, 'bar', 'Setting and getting CAPTCHA point: default', 'CAPTCHA');
440    $result = captcha_get_form_id_setting($comment_form_id, TRUE);
441    $this->assertEqual($result, 'default', 'Setting and symbolic getting CAPTCHA point: "default"', 'CAPTCHA');
442    // Set to 'baz/boo'.
443    captcha_set_form_id_setting($comment_form_id, 'baz/boo');
444    $result = captcha_get_form_id_setting($comment_form_id);
445    $this->assertNotNull($result, 'Setting and getting CAPTCHA point: baz/boo', 'CAPTCHA');
446    $this->assertEqual($result->module, 'baz', 'Setting and getting CAPTCHA point: baz/boo', 'CAPTCHA');
447    $this->assertEqual($result->captcha_type, 'boo', 'Setting and getting CAPTCHA point: baz/boo', 'CAPTCHA');
448    $result = captcha_get_form_id_setting($comment_form_id, TRUE);
449    $this->assertEqual($result, 'baz/boo', 'Setting and symbolic getting CAPTCHA point: "baz/boo"', 'CAPTCHA');
450    // Set to NULL (which should delete the CAPTCHA point setting entry).
451    captcha_set_form_id_setting($comment_form_id, NULL);
452    $result = captcha_get_form_id_setting($comment_form_id);
453    $this->assertNull($result, 'Setting and getting CAPTCHA point: NULL', 'CAPTCHA');
454    $result = captcha_get_form_id_setting($comment_form_id, TRUE);
455    $this->assertNull($result, 'Setting and symbolic getting CAPTCHA point: NULL', 'CAPTCHA');
456    // Set with object.
457    $captcha_type = new stdClass;
458    $captcha_type->module = 'baba';
459    $captcha_type->captcha_type = 'fofo';
460    captcha_set_form_id_setting($comment_form_id, $captcha_type);
461    $result = captcha_get_form_id_setting($comment_form_id);
462    $this->assertNotNull($result, 'Setting and getting CAPTCHA point: baba/fofo', 'CAPTCHA');
463    $this->assertEqual($result->module, 'baba', 'Setting and getting CAPTCHA point: baba/fofo', 'CAPTCHA');
464    $this->assertEqual($result->captcha_type, 'fofo', 'Setting and getting CAPTCHA point: baba/fofo', 'CAPTCHA');
465    $result = captcha_get_form_id_setting($comment_form_id, TRUE);
466    $this->assertEqual($result, 'baba/fofo', 'Setting and symbolic getting CAPTCHA point: "baba/fofo"', 'CAPTCHA');
467
468  }
469
470
471  /**
472   * Helper function for checking CAPTCHA setting of a form.
473   *
474   * @param $form_id the form_id of the form to investigate.
475   * @param $challenge_type what the challenge type should be:
476   *   NULL, 'none', 'default' or something like 'captcha/Math'
477   */
478  protected function assertCaptchaSetting($form_id, $challenge_type) {
479    $result = captcha_get_form_id_setting(self::COMMENT_FORM_ID, TRUE);
480    $this->assertEqual($result, $challenge_type,
481      t('Check CAPTCHA setting for form: expected: @expected, received: @received.',
482      array('@expected' => var_export($challenge_type, TRUE), '@received' => var_export($result, TRUE))),
483      'CAPTCHA');
484      }
485
486  /**
487   * Testing of the CAPTCHA administration links.
488   */
489  function testCaptchAdminLinks() {
490    // Log in as admin
491    $this->drupalLogin($this->admin_user);
492
493    // Enable CAPTCHA administration links.
494    $edit = array(
495      'captcha_administration_mode' => TRUE,
496    );
497    $this->drupalPost(self::CAPTCHA_ADMIN_PATH, $edit, 'Save configuration');
498
499    // Create a node with comments enabled.
500    $node = $this->createNodeWithCommentsEnabled();
501
502    // Go to node page
503    $this->drupalGet('node/' . $node->nid);
504
505    // Click the add new comment link
506    $this->clickLink(t('Add new comment'));
507    $add_comment_url = $this->getUrl();
508    // Remove fragment part from comment URL to avoid problems with later asserts
509    $add_comment_url = strtok($add_comment_url, "#");
510
511    ////////////////////////////////////////////////////////////
512    // Click the CAPTCHA admin link to enable a challenge.
513    $this->clickLink(t('Place a CAPTCHA here for untrusted users.'));
514    // Enable Math CAPTCHA.
515    $edit = array('captcha_type' => 'captcha/Math');
516    $this->drupalPost($this->getUrl(), $edit, t('Save'));
517
518    // Check if returned to original comment form.
519    $this->assertUrl($add_comment_url, array(),
520      'After setting CAPTCHA with CAPTCHA admin links: should return to original form.', 'CAPTCHA');
521    // Check if CAPTCHA was successfully enabled (on CAPTCHA admin links fieldset).
522    $this->assertText(t('CAPTCHA: challenge "@type" enabled', array('@type' => 'Math')),
523      'Enable a challenge through the CAPTCHA admin links', 'CAPTCHA');
524    // Check if CAPTCHA was successfully enabled (through API).
525    $this->assertCaptchaSetting(self::COMMENT_FORM_ID, 'captcha/Math');
526
527    //////////////////////////////////////////////////////
528    // Edit challenge type through CAPTCHA admin links.
529    $this->clickLink(t('change'));
530    // Enable Math CAPTCHA.
531    $edit = array('captcha_type' => 'default');
532    $this->drupalPost($this->getUrl(), $edit, t('Save'));
533
534    // Check if returned to original comment form.
535    $this->assertEqual($add_comment_url, $this->getUrl(),
536      'After editing challenge type CAPTCHA admin links: should return to original form.', 'CAPTCHA');
537    // Check if CAPTCHA was successfully changed (on CAPTCHA admin links fieldset).
538    // This is actually the same as the previous setting because the captcha/Math is the
539    // default for the default challenge. TODO Make sure the edit is a real change.
540    $this->assertText(t('CAPTCHA: challenge "@type" enabled', array('@type' => 'Math')),
541      'Enable a challenge through the CAPTCHA admin links', 'CAPTCHA');
542    // Check if CAPTCHA was successfully edited (through API).
543    $this->assertCaptchaSetting(self::COMMENT_FORM_ID, 'default');
544
545
546
547    //////////////////////////////////////////////////////
548    // Disable challenge through CAPTCHA admin links.
549    $this->clickLink(t('disable'));
550    // And confirm.
551    $this->drupalPost($this->getUrl(), array(), 'Disable');
552
553    // Check if returned to original comment form.
554    $this->assertEqual($add_comment_url, $this->getUrl(),
555      'After disablin challenge with CAPTCHA admin links: should return to original form.', 'CAPTCHA');
556    // Check if CAPTCHA was successfully disabled (on CAPTCHA admin links fieldset).
557    $this->assertText(t('CAPTCHA: no challenge enabled'),
558      'Disable challenge through the CAPTCHA admin links', 'CAPTCHA');
559    // Check if CAPTCHA was successfully disabled (through API).
560    $this->assertCaptchaSetting(self::COMMENT_FORM_ID, 'none');
561
562  }
563
564
565  function testUntrustedUserPosting() {
566    // Set CAPTCHA on comment form.
567    captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Math');
568
569    // Create a node with comments enabled.
570    $node = $this->createNodeWithCommentsEnabled();
571
572    // Log in as normal (untrusted) user.
573    $this->drupalLogin($this->normal_user);
574
575    // Go to node page and click the "add comment" link.
576    $this->drupalGet('node/' . $node->nid);
577    $this->clickLink(t('Add new comment'));
578    $add_comment_url = $this->getUrl();
579
580    // Check if CAPTCHA is visible on form.
581    $this->assertCaptchaPresence(TRUE);
582    // Try to post a comment with wrong answer.
583    $edit = $this->getCommentFormValues();
584    $edit['captcha_response'] = 'xx';
585    $this->drupalPost($add_comment_url, $edit, t('Preview'));
586    $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
587      'wrong CAPTCHA should block form submission.', 'CAPTCHA');
588
589    //TODO: more testing for untrusted posts.
590  }
591
592
593
594  /**
595   * Test XSS vulnerability on CAPTCHA description.
596   */
597  function testXssOnCaptchaDescription() {
598    // Set CAPTCHA on user register form.
599    captcha_set_form_id_setting('user_register', 'captcha/Math');
600
601    // Put Javascript snippet in CAPTCHA description.
602    $this->drupalLogin($this->admin_user);
603    $xss = '<script type="text/javascript">alert("xss")</script>';
604    $edit = array('captcha_description' => $xss);
605    $this->drupalPost(self::CAPTCHA_ADMIN_PATH, $edit, 'Save configuration');
606
607    // Visit user register form and check if Javascript snippet is there.
608    $this->drupalLogout();
609    $this->drupalGet('user/register');
610    $this->assertNoRaw($xss, 'Javascript should not be allowed in CAPTCHA description.', 'CAPTCHA');
611
612  }
613
614  /**
615   * Test the CAPTCHA placement flushing.
616   */
617  function testCaptchaPlacementCacheFlushing() {
618    // Set CAPTCHA on user register form.
619    captcha_set_form_id_setting('user_register', 'captcha/Math');
620    // Visit user register form to fill the CAPTCHA placement cache.
621    $this->drupalGet('user/register');
622    // Check if there is CAPTCHA placement cache.
623    $placement_map = variable_get('captcha_placement_map_cache', NULL);
624    $this->assertNotNull($placement_map, 'CAPTCHA placement cache should be set.');
625    // Flush the cache
626    $this->drupalLogin($this->admin_user);
627    $this->drupalPost(self::CAPTCHA_ADMIN_PATH, array(), t('Flush the CAPTCHA placement cache'));
628    // Check that the placement cache is unset
629    $placement_map = variable_get('captcha_placement_map_cache', NULL);
630    $this->assertNull($placement_map, 'CAPTCHA placement cache should be unset after flush.');
631  }
632
633  /**
634   * Helper function to get the CAPTCHA point setting straight from the database.
635   * @param string $form_id
636   * @return stdClass object
637   */
638  private function getCaptchaPointSettingFromDatabase($form_id) {
639    $result = db_fetch_object(db_query(
640      "SELECT * FROM {captcha_points} WHERE form_id='%s'",
641      array($form_id)
642    ));
643    return $result;
644  }
645
646  /**
647   * Method for testing the CAPTCHA point administration
648   */
649  function testCaptchaPointAdministration() {
650    // Generate CAPTCHA point data:
651    // Drupal form ID should consist of lowercase alphanumerics and underscore)
652    $captcha_point_form_id = 'form_' . strtolower($this->randomName(32));
653    // the Math CAPTCHA by the CAPTCHA module is always available, so let's use it
654    $captcha_point_module = 'captcha';
655    $captcha_point_type = 'Math';
656
657    // Log in as admin
658    $this->drupalLogin($this->admin_user);
659
660    // Set CAPTCHA point through admin/user/captcha/captcha/captcha_point
661    $form_values = array(
662      'captcha_point_form_id' => $captcha_point_form_id,
663      'captcha_type' => $captcha_point_module .'/'. $captcha_point_type,
664    );
665    $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point', $form_values, t('Save'));
666    $this->assertText(t('Saved CAPTCHA point settings.'),
667      'Saving of CAPTCHA point settings');
668
669    // Check in database
670    $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
671    $this->assertEqual($result->module, $captcha_point_module,
672      'Enabled CAPTCHA point should have module set');
673    $this->assertEqual($result->captcha_type, $captcha_point_type,
674      'Enabled CAPTCHA point should have type set');
675
676    // Disable CAPTCHA point again
677    $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/disable', array(), t('Disable'));
678    $this->assertRaw(t('Disabled CAPTCHA for form %form_id.', array('%form_id' => $captcha_point_form_id)), 'Disabling of CAPTCHA point');
679
680    // Check in database
681    $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
682    $this->assertNull($result->module,
683      'Disabled CAPTCHA point should have NULL as module');
684    $this->assertNull($result->captcha_type,
685      'Disabled CAPTCHA point should have NULL as type');
686
687    // Set CAPTCHA point through admin/user/captcha/captcha/captcha_point/$form_id
688    $form_values = array(
689      'captcha_type' => $captcha_point_module .'/'. $captcha_point_type,
690    );
691    $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id, $form_values, t('Save'));
692    $this->assertText(t('Saved CAPTCHA point settings.'),
693      'Saving of CAPTCHA point settings');
694
695    // Check in database
696    $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
697    $this->assertEqual($result->module, $captcha_point_module,
698      'Enabled CAPTCHA point should have module set');
699    $this->assertEqual($result->captcha_type, $captcha_point_type,
700      'Enabled CAPTCHA point should have type set');
701
702    // Delete CAPTCHA point
703    $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/delete', array(), t('Delete'));
704    $this->assertRaw(t('Deleted CAPTCHA for form %form_id.', array('%form_id' => $captcha_point_form_id)),
705      'Deleting of CAPTCHA point');
706
707    // Check in database
708    $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
709    $this->assertFalse($result, 'Deleted CAPTCHA point should be in database');
710  }
711
712  /**
713   * Method for testing the CAPTCHA point administration
714   */
715  function testCaptchaPointAdministrationByNonAdmin() {
716    // First add a CAPTCHA point (as admin)
717    $this->drupalLogin($this->admin_user);
718    $captcha_point_form_id = 'form_' . strtolower($this->randomName(32));
719    $captcha_point_module = 'captcha';
720    $captcha_point_type = 'Math';
721    $form_values = array(
722      'captcha_point_form_id' => $captcha_point_form_id,
723      'captcha_type' => $captcha_point_module .'/'. $captcha_point_type,
724    );
725    $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/', $form_values, t('Save'));
726    $this->assertText(t('Saved CAPTCHA point settings.'),
727      'Saving of CAPTCHA point settings');
728
729    // Switch from admin to nonadmin
730    $this->drupalGet(url('logout', array('absolute' => TRUE)));
731    $this->drupalLogin($this->normal_user);
732
733
734    // Try to set CAPTCHA point through admin/user/captcha/captcha/captcha_point
735    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point');
736    $this->assertText(t('You are not authorized to access this page.'),
737      'Non admin should not be able to set a CAPTCHA point');
738
739    // Try to set CAPTCHA point through admin/user/captcha/captcha/captcha_point/$form_id
740    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/' . 'form_' . strtolower($this->randomName(32)));
741    $this->assertText(t('You are not authorized to access this page.'),
742      'Non admin should not be able to set a CAPTCHA point');
743
744    // Try to disable the CAPTCHA point
745    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/disable');
746    $this->assertText(t('You are not authorized to access this page.'),
747      'Non admin should not be able to disable a CAPTCHA point');
748
749    // Try to delete the CAPTCHA point
750    $this->drupalGet(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/delete');
751    $this->assertText(t('You are not authorized to access this page.'),
752      'Non admin should not be able to delete a CAPTCHA point');
753
754    // Switch from nonadmin to admin again
755    $this->drupalGet(url('logout', array('absolute' => TRUE)));
756    $this->drupalLogin($this->admin_user);
757
758    // Check if original CAPTCHA point still exists in database
759    $result = $this->getCaptchaPointSettingFromDatabase($captcha_point_form_id);
760    $this->assertEqual($result->module, $captcha_point_module,
761      'Enabled CAPTCHA point should still have module set');
762    $this->assertEqual($result->captcha_type, $captcha_point_type,
763      'Enabled CAPTCHA point should still have type set');
764
765    // Delete CAPTCHA point
766    $this->drupalPost(self::CAPTCHA_ADMIN_PATH . '/captcha/captcha_point/'. $captcha_point_form_id .'/delete', array(), t('Delete'));
767    $this->assertRaw(t('Deleted CAPTCHA for form %form_id.', array('%form_id' => $captcha_point_form_id)),
768      'Deleting of CAPTCHA point');
769  }
770
771
772
773}
774
775
776
777class CaptchaPersistenceTestCase extends CaptchaBaseWebTestCase {
778
779  public static function getInfo() {
780    return array(
781      'name' => t('CAPTCHA persistence functionality'),
782      'description' => t('Testing of the CAPTCHA persistence functionality.'),
783      'group' => t('CAPTCHA'),
784    );
785  }
786
787  /**
788   * Set up the persistence and CAPTCHA settings.
789   * @param int $persistence the persistence value.
790   */
791  private function setUpPersistence($persistence) {
792    // Log in as admin
793    $this->drupalLogin($this->admin_user);
794    // Set persistence.
795    $edit = array('captcha_persistence' => $persistence);
796    $this->drupalPost(self::CAPTCHA_ADMIN_PATH, $edit, 'Save configuration');
797    // Log admin out.
798    $this->drupalLogout();
799
800    // Set the Test123 CAPTCHA on user register and comment form.
801    // We have to do this with the function captcha_set_form_id_setting()
802    // (because the CATCHA admin form does not show the Test123 option).
803    // We also have to do this after all usage of the CAPTCHA admin form
804    // (because posting the CAPTCHA admin form would set the CAPTCHA to 'none').
805    captcha_set_form_id_setting('user_login', 'captcha/Test');
806    $this->drupalGet('user');
807    $this->assertCaptchaPresence(TRUE);
808    captcha_set_form_id_setting('user_register', 'captcha/Test');
809    $this->drupalGet('user/register');
810    $this->assertCaptchaPresence(TRUE);
811  }
812
813  protected function assertPreservedCsid($captcha_sid_initial) {
814    $captcha_sid = $this->getCaptchaSidFromForm();
815    $this->assertEqual($captcha_sid_initial, $captcha_sid,
816      "CAPTCHA session ID should be preserved (expected: $captcha_sid_initial, found: $captcha_sid).");
817  }
818
819  protected function assertDifferentCsid($captcha_sid_initial) {
820    $captcha_sid = $this->getCaptchaSidFromForm();
821    $this->assertNotEqual($captcha_sid_initial, $captcha_sid,
822      "CAPTCHA session ID should be different.");
823  }
824
825  function testPersistenceAlways(){
826    // Set up of persistence and CAPTCHAs.
827    $this->setUpPersistence(CAPTCHA_PERSISTENCE_SHOW_ALWAYS);
828
829    // Go to login form and check if there is a CAPTCHA on the login form (look for the title).
830    $this->drupalGet('user');
831    $this->assertCaptchaPresence(TRUE);
832    $captcha_sid_initial = $this->getCaptchaSidFromForm();
833
834    // Try to with wrong user name and password, but correct CAPTCHA.
835    $edit = array(
836      'name' => 'foobar',
837      'pass' => 'bazlaz',
838      'captcha_response' => 'Test 123',
839    );
840    $this->drupalPost(NULL, $edit, t('Log in'));
841    // Check that there was no error message for the CAPTCHA.
842    $this->assertCaptchaResponseAccepted();
843
844    // Name and password were wrong, we should get an updated form with a fresh CAPTCHA.
845    $this->assertCaptchaPresence(TRUE);
846    $this->assertPreservedCsid($captcha_sid_initial);
847
848    // Post from again.
849    $this->drupalPost(NULL, $edit, t('Log in'));
850    // Check that there was no error message for the CAPTCHA.
851    $this->assertCaptchaResponseAccepted();
852    $this->assertPreservedCsid($captcha_sid_initial);
853
854  }
855
856  function testPersistencePerFormInstance(){
857    // Set up of persistence and CAPTCHAs.
858    $this->setUpPersistence(CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
859
860    // Go to login form and check if there is a CAPTCHA on the login form.
861    $this->drupalGet('user');
862    $this->assertCaptchaPresence(TRUE);
863    $captcha_sid_initial = $this->getCaptchaSidFromForm();
864
865    // Try to with wrong user name and password, but correct CAPTCHA.
866    $edit = array(
867      'name' => 'foobar',
868      'pass' => 'bazlaz',
869      'captcha_response' => 'Test 123',
870    );
871    $this->drupalPost(NULL, $edit, t('Log in'));
872    // Check that there was no error message for the CAPTCHA.
873    $this->assertCaptchaResponseAccepted();
874    // There shouldn't be a CAPTCHA on the new form.
875    $this->assertCaptchaPresence(FALSE);
876    $this->assertPreservedCsid($captcha_sid_initial);
877
878    // Start a new form instance/session
879    $this->drupalGet('node');
880    $this->drupalGet('user');
881    $this->assertCaptchaPresence(TRUE);
882    $this->assertDifferentCsid($captcha_sid_initial);
883
884    // Check another form
885    $this->drupalGet('user/register');
886    $this->assertCaptchaPresence(TRUE);
887    $this->assertDifferentCsid($captcha_sid_initial);
888
889  }
890
891  function testPersistencePerFormType(){
892    // Set up of persistence and CAPTCHAs.
893    $this->setUpPersistence(CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_TYPE);
894
895    // Go to login form and check if there is a CAPTCHA on the login form.
896    $this->drupalGet('user');
897    $this->assertCaptchaPresence(TRUE);
898    $captcha_sid_initial = $this->getCaptchaSidFromForm();
899
900    // Try to with wrong user name and password, but correct CAPTCHA.
901    $edit = array(
902      'name' => 'foobar',
903      'pass' => 'bazlaz',
904      'captcha_response' => 'Test 123',
905    );
906    $this->drupalPost(NULL, $edit, t('Log in'));
907    // Check that there was no error message for the CAPTCHA.
908    $this->assertCaptchaResponseAccepted();
909    // There shouldn't be a CAPTCHA on the new form.
910    $this->assertCaptchaPresence(FALSE);
911    $this->assertPreservedCsid($captcha_sid_initial);
912
913    // Start a new form instance/session
914    $this->drupalGet('node');
915    $this->drupalGet('user');
916    $this->assertCaptchaPresence(FALSE);
917    $this->assertDifferentCsid($captcha_sid_initial);
918
919    // Check another form
920    $this->drupalGet('user/register');
921    $this->assertCaptchaPresence(TRUE);
922    $this->assertDifferentCsid($captcha_sid_initial);
923  }
924
925  function testPersistenceOnlyOnce(){
926    // Set up of persistence and CAPTCHAs.
927    $this->setUpPersistence(CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL);
928
929    // Go to login form and check if there is a CAPTCHA on the login form.
930    $this->drupalGet('user');
931    $this->assertCaptchaPresence(TRUE);
932    $captcha_sid_initial = $this->getCaptchaSidFromForm();
933
934    // Try to with wrong user name and password, but correct CAPTCHA.
935    $edit = array(
936      'name' => 'foobar',
937      'pass' => 'bazlaz',
938      'captcha_response' => 'Test 123',
939    );
940    $this->drupalPost(NULL, $edit, t('Log in'));
941    // Check that there was no error message for the CAPTCHA.
942    $this->assertCaptchaResponseAccepted();
943    // There shouldn't be a CAPTCHA on the new form.
944    $this->assertCaptchaPresence(FALSE);
945    $this->assertPreservedCsid($captcha_sid_initial);
946
947    // Start a new form instance/session
948    $this->drupalGet('node');
949    $this->drupalGet('user');
950    $this->assertCaptchaPresence(FALSE);
951    $this->assertDifferentCsid($captcha_sid_initial);
952
953    // Check another form
954    $this->drupalGet('user/register');
955    $this->assertCaptchaPresence(FALSE);
956    $this->assertDifferentCsid($captcha_sid_initial);
957  }
958
959}
960
961
962class CaptchaSessionReuseAttackTestCase extends CaptchaBaseWebTestCase {
963
964  public static function getInfo() {
965    return array(
966      'name' => t('CAPTCHA session reuse attack tests'),
967      'description' => t('Testing of the protection against CAPTCHA session reuse attacks.'),
968      'group' => t('CAPTCHA'),
969    );
970  }
971
972  /**
973   * Assert that the CAPTCHA session ID reuse attack was detected.
974   */
975  protected function assertCaptchaSessionIdReuseAttackDetection() {
976    $this->assertText(t(CAPTCHA_SESSION_REUSE_ATTACK_ERROR_MESSAGE),
977      'CAPTCHA session ID reuse attack should be detected.',
978      'CAPTCHA');
979    // There should be an error message about wrong response.
980    $this->assertText(t(CAPTCHA_WRONG_RESPONSE_ERROR_MESSAGE),
981      'CAPTCHA response should flagged as wrong.',
982      'CAPTCHA');
983  }
984
985  function testCaptchaSessionReuseAttackDetectionOnCommentPreview() {
986    // Create commentable node
987    $node = $this->createNodeWithCommentsEnabled();
988    // Set Test CAPTCHA on comment form.
989    captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Math');
990    variable_set('captcha_persistence', CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
991
992    // Log in as normal user.
993    $this->drupalLogin($this->normal_user);
994
995    // Go to comment form of commentable node.
996    $this->drupalGet('comment/reply/' . $node->nid);
997    $this->assertCaptchaPresence(TRUE);
998
999    // Get CAPTCHA session ID and solution of the challenge.
1000    $captcha_sid = $this->getCaptchaSidFromForm();
1001    $captcha_token = $this->getCaptchaTokenFromForm();
1002    $solution = $this->getMathCaptchaSolutionFromForm();
1003
1004    // Post the form with the solution.
1005    $edit = $this->getCommentFormValues();
1006    $edit['captcha_response'] = $solution;
1007    $this->drupalPost(NULL, $edit, t('Preview'));
1008    // Answer should be accepted and further CAPTCHA ommitted.
1009    $this->assertCaptchaResponseAccepted();
1010    $this->assertCaptchaPresence(FALSE);
1011
1012    // Post a new comment, reusing the previous CAPTCHA session.
1013    $edit = $this->getCommentFormValues();
1014    $edit['captcha_sid'] = $captcha_sid;
1015    $edit['captcha_token'] = $captcha_token;
1016    $edit['captcha_response'] = $solution;
1017    $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview'));
1018    // CAPTCHA session reuse attack should be detected.
1019    $this->assertCaptchaSessionIdReuseAttackDetection();
1020    // There should be a CAPTCHA.
1021    $this->assertCaptchaPresence(TRUE);
1022
1023  }
1024
1025  function testCaptchaSessionReuseAttackDetectionOnNodeForm() {
1026    // Set CAPTCHA on page form.
1027    captcha_set_form_id_setting('page_node_form', 'captcha/Math');
1028    variable_set('captcha_persistence', CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
1029
1030    // Log in as normal user.
1031    $this->drupalLogin($this->normal_user);
1032
1033    // Go to node add form.
1034    $this->drupalGet('node/add/page');
1035    $this->assertCaptchaPresence(TRUE);
1036
1037    // Get CAPTCHA session ID and solution of the challenge.
1038    $captcha_sid = $this->getCaptchaSidFromForm();
1039    $captcha_token = $this->getCaptchaTokenFromForm();
1040    $solution = $this->getMathCaptchaSolutionFromForm();
1041
1042    // Page settings to post, with correct CAPTCHA answer.
1043    $edit = $this->getNodeFormValues();
1044    $edit['captcha_response'] = $solution;
1045    // Preview the node
1046    $this->drupalPost(NULL, $edit, t('Preview'));
1047    // Answer should be accepted.
1048    $this->assertCaptchaResponseAccepted();
1049    // Check that there is no CAPTCHA after preview.
1050    $this->assertCaptchaPresence(FALSE);
1051
1052    // Post a new comment, reusing the previous CAPTCHA session.
1053    $edit = $this->getNodeFormValues();
1054    $edit['captcha_sid'] = $captcha_sid;
1055    $edit['captcha_token'] = $captcha_token;
1056    $edit['captcha_response'] = $solution;
1057    $this->drupalPost('node/add/page', $edit, t('Preview'));
1058    // CAPTCHA session reuse attack should be detected.
1059    $this->assertCaptchaSessionIdReuseAttackDetection();
1060    // There should be a CAPTCHA.
1061    $this->assertCaptchaPresence(TRUE);
1062
1063  }
1064
1065  function testCaptchaSessionReuseAttackDetectionOnLoginForm() {
1066    // Set CAPTCHA on login form.
1067    captcha_set_form_id_setting('user_login', 'captcha/Math');
1068    variable_set('captcha_persistence', CAPTCHA_PERSISTENCE_SKIP_ONCE_SUCCESSFUL_PER_FORM_INSTANCE);
1069
1070    // Go to log in form.
1071    $this->drupalGet('user');
1072    $this->assertCaptchaPresence(TRUE);
1073
1074    // Get CAPTCHA session ID and solution of the challenge.
1075    $captcha_sid = $this->getCaptchaSidFromForm();
1076    $captcha_token = $this->getCaptchaTokenFromForm();
1077    $solution = $this->getMathCaptchaSolutionFromForm();
1078
1079    // Log in through form.
1080    $edit = array(
1081      'name' => $this->normal_user->name,
1082      'pass' => $this->normal_user->pass_raw,
1083      'captcha_response' => $solution,
1084    );
1085    $this->drupalPost(NULL, $edit, t('Log in'));
1086    $this->assertCaptchaResponseAccepted();
1087    $this->assertCaptchaPresence(FALSE);
1088    // If a "log out" link appears on the page, it is almost certainly because
1089    // the login was successful.
1090    $pass = $this->assertLink(t('Log out'), 0, t('User %name successfully logged in.', array('%name' => $this->normal_user->name)), t('User login'));
1091
1092    // Log out again.
1093    $this->drupalLogout();
1094
1095    // Try to log in again, reusing the previous CAPTCHA session.
1096    $edit += array(
1097      'captcha_sid' => $captcha_sid,
1098      'captcha_token' => $captcha_token,
1099    );
1100    $this->drupalPost('user', $edit, t('Log in'));
1101    // CAPTCHA session reuse attack should be detected.
1102    $this->assertCaptchaSessionIdReuseAttackDetection();
1103    // There should be a CAPTCHA.
1104    $this->assertCaptchaPresence(TRUE);
1105  }
1106
1107
1108  public function testMultipleCaptchaProtectedFormsOnOnePage()
1109  {
1110    // Set Test CAPTCHA on comment form and login block
1111    captcha_set_form_id_setting(self::COMMENT_FORM_ID, 'captcha/Test');
1112    captcha_set_form_id_setting('user_login_block', 'captcha/Math');
1113    $this->allowCommentPostingForAnonymousVisitors();
1114
1115    // Create a node with comments enabled.
1116    $node = $this->createNodeWithCommentsEnabled();
1117
1118    // Preview comment with correct CAPTCHA answer.
1119    $edit = $this->getCommentFormValues();
1120    $comment_subject = $edit['subject'];
1121    $edit['captcha_response'] = 'Test 123';
1122    $this->drupalPost('comment/reply/' . $node->nid, $edit, t('Preview'));
1123    // Post should be accepted: no warnings,
1124    // no CAPTCHA reuse detection (which could be used by user log in block).
1125    $this->assertCaptchaResponseAccepted();
1126    $this->assertText($comment_subject);
1127
1128  }
1129
1130}
1131
1132
1133// Some tricks to debug:
1134// drupal_debug($data) // from devel module
1135// file_put_contents('tmp.simpletest.html', $this->drupalGetContent());
Nota: Vea TracBrowser para ayuda de uso del navegador del repositorio.