diff --git a/core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php b/core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php index 7b166f8..f97fa9c 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php @@ -76,6 +76,15 @@ public function buildForm(array $form, FormStateInterface $form_state) { ], ], ]; + $form['textfield_required_when_checkbox_trigger_checked'] = [ + '#type' => 'textfield', + '#title' => 'Texfield required when checkbox trigger checked', + '#states' => [ + 'required' => [ + ':input[name="checkbox_trigger"]' => ['checked' => TRUE], + ], + ], + ]; $form['checkbox_unchecked_when_textfield_trigger_filled'] = [ '#type' => 'checkbox', '#title' => 'Checkbox unchecked when textfield trigger filled', diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Core/Form/JavascriptStatesTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Core/Form/JavascriptStatesTest.php index 7d686ae..83fb9b8 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/Core/Form/JavascriptStatesTest.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/Core/Form/JavascriptStatesTest.php @@ -33,6 +33,8 @@ public function testCheckboxTriggeredElements() { // Test that the details element is collapsed so the textfield inside is not // visible. $this->assertFieldNotVisible('textfield_in_details'); + // Test that the textfield is optional. + $this->assertFieldOptional('textfield_required_when_checkbox_trigger_checked'); // Change state: check the checkbox. $trigger->check(); @@ -42,6 +44,8 @@ public function testCheckboxTriggeredElements() { // Test that the details element is now open so the textfield inside is now // visible. $this->assertFieldVisible('textfield_in_details'); + // Test that the textfield is now required. + $this->assertFieldRequired('textfield_required_when_checkbox_trigger_checked'); // Change back to the initial state to avoid issues running the next tests. $trigger->uncheck(); @@ -268,4 +272,34 @@ public function assertFieldNotVisible($locator, TraversableElement $container = $this->assertSession()->assertElementNotVisible('named', ['field', $locator], $container); } + /** + * Asserts that the given field is required. + * + * @param string $locator + * One of id|name|label|value for the field. + * @param \Behat\Mink\Element\TraversableElement $container + * (optional) The document to check against. Defaults to the current page. + * + * @throws \Behat\Mink\Exception\ElementNotFoundException + * When the element doesn't exist. + */ + public function assertFieldRequired($locator, TraversableElement $container = NULL) { + $this->assertSession()->assertElementRequired('named', ['field', $locator], $container); + } + + /** + * Asserts that the given field is optional (not required). + * + * @param string $locator + * One of id|name|label|value for the field. + * @param \Behat\Mink\Element\TraversableElement $container + * (optional) The document to check against. Defaults to the current page. + * + * @throws \Behat\Mink\Exception\ElementNotFoundException + * When the element doesn't exist. + */ + public function assertFieldOptional($locator, TraversableElement $container = NULL) { + $this->assertSession()->assertElementOptional('named', ['field', $locator], $container); + } + } diff --git a/core/tests/Drupal/FunctionalJavascriptTests/JSWebAssert.php b/core/tests/Drupal/FunctionalJavascriptTests/JSWebAssert.php index a37bfbc..90043e4 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/JSWebAssert.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/JSWebAssert.php @@ -61,14 +61,8 @@ function isAjaxing(instance) { * When the element doesn't exist. */ public function assertElementVisible($selector_type, $selector, ElementInterface $container = NULL) { - $container = $container ?: $this->session->getPage(); - $node = $container->find($selector_type, $selector); - if ($node === NULL) { - if (is_array($selector)) { - $selector = implode(' ', $selector); - } - throw new ElementNotFoundException($this->session->getDriver(), 'element', $selector_type, $selector); - } + $node = $this->findNode($selector_type, $selector, $container); + $message = sprintf( 'Element "%s" is not visible.', $this->getMatchingElementRepresentation($selector_type, $selector) @@ -90,14 +84,8 @@ public function assertElementVisible($selector_type, $selector, ElementInterface * When the element doesn't exist. */ public function assertElementNotVisible($selector_type, $selector, ElementInterface $container = NULL) { - $container = $container ?: $this->session->getPage(); - $node = $container->find($selector_type, $selector); - if ($node === NULL) { - if (is_array($selector)) { - $selector = implode(' ', $selector); - } - throw new ElementNotFoundException($this->session->getDriver(), 'element', $selector_type, $selector); - } + $node = $this->findNode($selector_type, $selector, $container); + $message = sprintf( 'Element "%s" is not visible.', $this->getMatchingElementRepresentation($selector_type, $selector) @@ -106,6 +94,52 @@ public function assertElementNotVisible($selector_type, $selector, ElementInterf } /** + * Asserts that the specific element is not required on the current page. + * + * @param string $selector_type + * The element selector type (css, xpath). + * @param string|array $selector + * The element selector. + * @param \Behat\Mink\Element\ElementInterface $container + * The document to check against. + * + * @throws \Behat\Mink\Exception\ElementNotFoundException + * When the element doesn't exist. + */ + public function assertElementRequired($selector_type, $selector, ElementInterface $container = NULL) { + $node = $this->findNode($selector_type, $selector, $container); + + $message = sprintf( + 'Element "%s" is required.', + $this->getMatchingElementRepresentation($selector_type, $selector) + ); + $this->assertElement($node->getAttribute('required') == 'required', $message, $node); + } + + /** + * Asserts that the specific element is not required on the current page. + * + * @param string $selector_type + * The element selector type (css, xpath). + * @param string|array $selector + * The element selector. + * @param \Behat\Mink\Element\ElementInterface $container + * The document to check against. + * + * @throws \Behat\Mink\Exception\ElementNotFoundException + * When the element doesn't exist. + */ + public function assertElementOptional($selector_type, $selector, ElementInterface $container = NULL) { + $node = $this->findNode($selector_type, $selector, $container); + + $message = sprintf( + 'Element "%s" is optional.', + $this->getMatchingElementRepresentation($selector_type, $selector) + ); + $this->assertElement(!$node->hasAttribute('required'), $message, $node); + } + + /** * {@inheritdoc} */ protected function assertElement($condition, $message, Element $element) { @@ -117,6 +151,35 @@ protected function assertElement($condition, $message, Element $element) { } /** + * Find a node in the container specified usually the current page. + * + * @param string $selector_type + * The element selector type (CSS, XPath). + * @param string $selector + * The selector engine name. See ElementInterface::findAll() for the + * supported selectors. + * @param \Behat\Mink\Element\ElementInterface $container + * The document to check against. + * + * @return \Behat\Mink\Element\ElementInterface $node + * The node element if exists in the current container. + * + * @throws \Behat\Mink\Exception\ElementNotFoundException + * When the element doesn't exist. + */ + protected function findNode($selector_type, $selector, ElementInterface $container = NULL) { + $container = $container ?: $this->session->getPage(); + $node = $container->find($selector_type, $selector); + if ($node === NULL) { + if (is_array($selector)) { + $selector = implode(' ', $selector); + } + throw new ElementNotFoundException($this->session->getDriver(), 'element', $selector_type, $selector); + } + return $node; + } + + /** * {@inheritdoc} */ protected function getMatchingElementRepresentation($selector_type, $selector, $plural = FALSE) {