Version 1
[yaffs-website] / web / core / modules / system / src / Tests / Form / ElementsLabelsTest.php
1 <?php
2
3 namespace Drupal\system\Tests\Form;
4
5 use Drupal\simpletest\WebTestBase;
6
7 /**
8  * Tests form element labels, required markers and associated output.
9  *
10  * @group Form
11  */
12 class ElementsLabelsTest extends WebTestBase {
13
14   /**
15    * Modules to enable.
16    *
17    * @var array
18    */
19   public static $modules = ['form_test'];
20
21   /**
22    * Test form elements, labels, title attributes and required marks output
23    * correctly and have the correct label option class if needed.
24    */
25   public function testFormLabels() {
26     $this->drupalGet('form_test/form-labels');
27
28     // Check that the checkbox/radio processing is not interfering with
29     // basic placement.
30     $elements = $this->xpath('//input[@id="edit-form-checkboxes-test-third-checkbox"]/following-sibling::label[@for="edit-form-checkboxes-test-third-checkbox" and @class="option"]');
31     $this->assertTrue(isset($elements[0]), 'Label follows field and label option class correct for regular checkboxes.');
32
33     // Make sure the label is rendered for checkboxes.
34     $elements = $this->xpath('//input[@id="edit-form-checkboxes-test-0"]/following-sibling::label[@for="edit-form-checkboxes-test-0" and @class="option"]');
35     $this->assertTrue(isset($elements[0]), 'Label 0 found checkbox.');
36
37     $elements = $this->xpath('//input[@id="edit-form-radios-test-second-radio"]/following-sibling::label[@for="edit-form-radios-test-second-radio" and @class="option"]');
38     $this->assertTrue(isset($elements[0]), 'Label follows field and label option class correct for regular radios.');
39
40     // Make sure the label is rendered for radios.
41     $elements = $this->xpath('//input[@id="edit-form-radios-test-0"]/following-sibling::label[@for="edit-form-radios-test-0" and @class="option"]');
42     $this->assertTrue(isset($elements[0]), 'Label 0 found radios.');
43
44     // Exercise various defaults for checkboxes and modifications to ensure
45     // appropriate override and correct behavior.
46     $elements = $this->xpath('//input[@id="edit-form-checkbox-test"]/following-sibling::label[@for="edit-form-checkbox-test" and @class="option"]');
47     $this->assertTrue(isset($elements[0]), 'Label follows field and label option class correct for a checkbox by default.');
48
49     // Exercise various defaults for textboxes and modifications to ensure
50     // appropriate override and correct behavior.
51     $elements = $this->xpath('//label[@for="edit-form-textfield-test-title-and-required" and @class="js-form-required form-required"]/following-sibling::input[@id="edit-form-textfield-test-title-and-required"]');
52     $this->assertTrue(isset($elements[0]), 'Label precedes textfield, with required marker inside label.');
53
54     $elements = $this->xpath('//input[@id="edit-form-textfield-test-no-title-required"]/preceding-sibling::label[@for="edit-form-textfield-test-no-title-required" and @class="js-form-required form-required"]');
55     $this->assertTrue(isset($elements[0]), 'Label tag with required marker precedes required textfield with no title.');
56
57     $elements = $this->xpath('//input[@id="edit-form-textfield-test-title-invisible"]/preceding-sibling::label[@for="edit-form-textfield-test-title-invisible" and @class="visually-hidden"]');
58     $this->assertTrue(isset($elements[0]), 'Label preceding field and label class is visually-hidden.');
59
60     $elements = $this->xpath('//input[@id="edit-form-textfield-test-title"]/preceding-sibling::span[@class="js-form-required form-required"]');
61     $this->assertFalse(isset($elements[0]), 'No required marker on non-required field.');
62
63     $elements = $this->xpath('//input[@id="edit-form-textfield-test-title-after"]/following-sibling::label[@for="edit-form-textfield-test-title-after" and @class="option"]');
64     $this->assertTrue(isset($elements[0]), 'Label after field and label option class correct for text field.');
65
66     $elements = $this->xpath('//label[@for="edit-form-textfield-test-title-no-show"]');
67     $this->assertFalse(isset($elements[0]), 'No label tag when title set not to display.');
68
69     $elements = $this->xpath('//div[contains(@class, "js-form-item-form-textfield-test-title-invisible") and contains(@class, "form-no-label")]');
70     $this->assertTrue(isset($elements[0]), 'Field class is form-no-label when there is no label.');
71
72     // Check #field_prefix and #field_suffix placement.
73     $elements = $this->xpath('//span[@class="field-prefix"]/following-sibling::div[@id="edit-form-radios-test"]');
74     $this->assertTrue(isset($elements[0]), 'Properly placed the #field_prefix element after the label and before the field.');
75
76     $elements = $this->xpath('//span[@class="field-suffix"]/preceding-sibling::div[@id="edit-form-radios-test"]');
77     $this->assertTrue(isset($elements[0]), 'Properly places the #field_suffix element immediately after the form field.');
78
79     // Check #prefix and #suffix placement.
80     $elements = $this->xpath('//div[@id="form-test-textfield-title-prefix"]/following-sibling::div[contains(@class, \'js-form-item-form-textfield-test-title\')]');
81     $this->assertTrue(isset($elements[0]), 'Properly places the #prefix element before the form item.');
82
83     $elements = $this->xpath('//div[@id="form-test-textfield-title-suffix"]/preceding-sibling::div[contains(@class, \'js-form-item-form-textfield-test-title\')]');
84     $this->assertTrue(isset($elements[0]), 'Properly places the #suffix element before the form item.');
85
86     // Check title attribute for radios and checkboxes.
87     $elements = $this->xpath('//div[@id="edit-form-checkboxes-title-attribute"]');
88     $this->assertEqual($elements[0]['title'], 'Checkboxes test' . ' (' . t('Required') . ')', 'Title attribute found.');
89     $elements = $this->xpath('//div[@id="edit-form-radios-title-attribute"]');
90     $this->assertEqual($elements[0]['title'], 'Radios test' . ' (' . t('Required') . ')', 'Title attribute found.');
91
92     $elements = $this->xpath('//fieldset[@id="edit-form-checkboxes-title-invisible--wrapper"]/legend/span[contains(@class, "visually-hidden")]');
93     $this->assertTrue(!empty($elements), "Title/Label not displayed when 'visually-hidden' attribute is set in checkboxes.");
94
95     $elements = $this->xpath('//fieldset[@id="edit-form-radios-title-invisible--wrapper"]/legend/span[contains(@class, "visually-hidden")]');
96     $this->assertTrue(!empty($elements), "Title/Label not displayed when 'visually-hidden' attribute is set in radios.");
97   }
98
99   /**
100    * Tests different display options for form element descriptions.
101    */
102   public function testFormDescriptions() {
103     $this->drupalGet('form_test/form-descriptions');
104
105     // Check #description placement with #description_display='after'.
106     $field_id = 'edit-form-textfield-test-description-after';
107     $description_id = $field_id . '--description';
108     $elements = $this->xpath('//input[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]/following-sibling::div[@id="' . $description_id . '"]');
109     $this->assertTrue(isset($elements[0]), t('Properly places the #description element after the form item.'));
110
111     // Check #description placement with #description_display='before'.
112     $field_id = 'edit-form-textfield-test-description-before';
113     $description_id = $field_id . '--description';
114     $elements = $this->xpath('//input[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]/preceding-sibling::div[@id="' . $description_id . '"]');
115     $this->assertTrue(isset($elements[0]), t('Properly places the #description element before the form item.'));
116
117     // Check if the class is 'visually-hidden' on the form element description
118     // for the option with #description_display='invisible' and also check that
119     // the description is placed after the form element.
120     $field_id = 'edit-form-textfield-test-description-invisible';
121     $description_id = $field_id . '--description';
122     $elements = $this->xpath('//input[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]/following-sibling::div[contains(@class, "visually-hidden")]');
123     $this->assertTrue(isset($elements[0]), t('Properly renders the #description element visually-hidden.'));
124   }
125
126   /**
127    * Test forms in theme-less environments.
128    */
129   public function testFormsInThemeLessEnvironments() {
130     $form = $this->getFormWithLimitedProperties();
131     $render_service = $this->container->get('renderer');
132     // This should not throw any notices.
133     $render_service->renderPlain($form);
134   }
135
136   /**
137    * Return a form with element with not all properties defined.
138    */
139   protected function getFormWithLimitedProperties() {
140     $form = [];
141
142     $form['fieldset'] = [
143       '#type' => 'fieldset',
144       '#title' => 'Fieldset',
145     ];
146
147     return $form;
148   }
149
150 }