TriggeringElementTest.php 4.95 KB
Newer Older
1 2 3 4 5 6 7
<?php

namespace Drupal\system\Tests\Form;

use Drupal\simpletest\WebTestBase;

/**
8
 * Tests that FAPI correctly determines the triggering element.
9 10
 *
 * @group Form
11 12 13
 */
class TriggeringElementTest extends WebTestBase {

14 15 16 17 18
  /**
   * Modules to enable.
   *
   * @var array
   */
19
  public static $modules = ['form_test'];
20

21
  /**
22
   * Test the determination of the triggering element when no button
23 24 25
   * information is included in the POST data, as is sometimes the case when
   * the ENTER key is pressed in a textfield in Internet Explorer.
   */
26
  public function testNoButtonInfoInPost() {
27
    $path = 'form-test/clicked-button';
28
    $edit = [];
29 30
    $form_html_id = 'form-test-clicked-button';

31 32
    // Ensure submitting a form with no buttons results in no triggering element
    // and the form submit handler not running.
33
    $this->drupalPostForm($path, $edit, NULL, [], [], $form_html_id);
34
    $this->assertText('There is no clicked button.', '$form_state->getTriggeringElement() set to NULL.');
35
    $this->assertNoText('Submit handler for form_test_clicked_button executed.', 'Form submit handler did not execute.');
36

37 38 39
    // Ensure submitting a form with one or more submit buttons results in the
    // triggering element being set to the first one the user has access to. An
    // argument with 'r' in it indicates a restricted (#access=FALSE) button.
40
    $this->drupalPostForm($path . '/s', $edit, NULL, [], [], $form_html_id);
41
    $this->assertText('The clicked button is button1.', '$form_state->getTriggeringElement() set to only button.');
42
    $this->assertText('Submit handler for form_test_clicked_button executed.', 'Form submit handler executed.');
43

44
    $this->drupalPostForm($path . '/s/s', $edit, NULL, [], [], $form_html_id);
45
    $this->assertText('The clicked button is button1.', '$form_state->getTriggeringElement() set to first button.');
46
    $this->assertText('Submit handler for form_test_clicked_button executed.', 'Form submit handler executed.');
47

48
    $this->drupalPostForm($path . '/rs/s', $edit, NULL, [], [], $form_html_id);
49
    $this->assertText('The clicked button is button2.', '$form_state->getTriggeringElement() set to first available button.');
50
    $this->assertText('Submit handler for form_test_clicked_button executed.', 'Form submit handler executed.');
51

52 53 54 55
    // Ensure submitting a form with buttons of different types results in the
    // triggering element being set to the first button, regardless of type. For
    // the FAPI 'button' type, this should result in the submit handler not
    // executing. The types are 's'(ubmit), 'b'(utton), and 'i'(mage_button).
56
    $this->drupalPostForm($path . '/s/b/i', $edit, NULL, [], [], $form_html_id);
57
    $this->assertText('The clicked button is button1.', '$form_state->getTriggeringElement() set to first button.');
58
    $this->assertText('Submit handler for form_test_clicked_button executed.', 'Form submit handler executed.');
59

60
    $this->drupalPostForm($path . '/b/s/i', $edit, NULL, [], [], $form_html_id);
61
    $this->assertText('The clicked button is button1.', '$form_state->getTriggeringElement() set to first button.');
62
    $this->assertNoText('Submit handler for form_test_clicked_button executed.', 'Form submit handler did not execute.');
63

64
    $this->drupalPostForm($path . '/i/s/b', $edit, NULL, [], [], $form_html_id);
65
    $this->assertText('The clicked button is button1.', '$form_state->getTriggeringElement() set to first button.');
66
    $this->assertText('Submit handler for form_test_clicked_button executed.', 'Form submit handler executed.');
67 68 69
  }

  /**
70 71
   * Test that the triggering element does not get set to a button with
   * #access=FALSE.
72
   */
73
  public function testAttemptAccessControlBypass() {
74 75 76 77 78 79 80 81
    $path = 'form-test/clicked-button';
    $form_html_id = 'form-test-clicked-button';

    // Retrieve a form where 'button1' has #access=FALSE and 'button2' doesn't.
    $this->drupalGet($path . '/rs/s');

    // Submit the form with 'button1=button1' in the POST data, which someone
    // trying to get around security safeguards could easily do. We have to do
82
    // a little trickery here, to work around the safeguards in drupalPostForm(): by
83
    // renaming the text field that is in the form to 'button1', we can get the
84
    // data we want into \Drupal::request()->request.
85 86
    $elements = $this->xpath('//form[@id="' . $form_html_id . '"]//input[@name="text"]');
    $elements[0]['name'] = 'button1';
87
    $this->drupalPostForm(NULL, ['button1' => 'button1'], NULL, [], [], $form_html_id);
88

89 90 91
    // Ensure that the triggering element was not set to the restricted button.
    // Do this with both a negative and positive assertion, because negative
    // assertions alone can be brittle. See testNoButtonInfoInPost() for why the
92
    // triggering element gets set to 'button2'.
93 94
    $this->assertNoText('The clicked button is button1.', '$form_state->getTriggeringElement() not set to a restricted button.');
    $this->assertText('The clicked button is button2.', '$form_state->getTriggeringElement() not set to a restricted button.');
95
  }
96

97
}