diff --git a/core/modules/content_translation/tests/src/Functional/ContentTranslationLinkTagTest.php b/core/modules/content_translation/tests/src/Functional/ContentTranslationLinkTagTest.php index e617bcbcb21745186f432758d86c19a7c30faedc..5c0f9d8d3543e938cb66b3ca400010c082590b42 100644 --- a/core/modules/content_translation/tests/src/Functional/ContentTranslationLinkTagTest.php +++ b/core/modules/content_translation/tests/src/Functional/ContentTranslationLinkTagTest.php @@ -116,10 +116,7 @@ function ($langcode) use ($url_base, $languageManager) { foreach ($urls as $langcode => $url) { $this->drupalGet($url); foreach ($urls as $langcode_alternate => $url_alternate) { - $args = [':href' => $url_alternate->toString(), ':hreflang' => $langcode_alternate]; - $links = $this->xpath('head/link[@rel = "alternate" and @href = :href and @hreflang = :hreflang]', $args); - $message = sprintf('The "%s" translation has the correct alternate hreflang link for "%s": %s.', $langcode, $langcode_alternate, $url->toString()); - $this->assertTrue(isset($links[0]), $message); + $this->assertSession()->elementAttributeContains('xpath', "head/link[@rel='alternate' and @hreflang='$langcode_alternate']", 'href', $url_alternate->toString()); } } @@ -135,12 +132,7 @@ function ($langcode) use ($url_base, $languageManager) { 'absolute' => TRUE, 'language' => $language, ])->toString(); - $args = [ - ':href' => $frontpage_path, - ':hreflang' => $language->getId(), - ]; - $links = $this->xpath('head/link[@rel = "alternate" and @href = :href and @hreflang = :hreflang]', $args); - $this->assertArrayHasKey(0, $links); + $this->assertSession()->elementAttributeContains('xpath', "head/link[@rel='alternate' and @hreflang='{$language->getId()}']", 'href', $frontpage_path); } } } diff --git a/core/modules/field/tests/src/Functional/FormTest.php b/core/modules/field/tests/src/Functional/FormTest.php index 7942498b8fc3614d5fda8323fc7b41116cb12c0b..edbd3d0d7527284fe4ac6a6ba6a496d1d4e026ab 100644 --- a/core/modules/field/tests/src/Functional/FormTest.php +++ b/core/modules/field/tests/src/Functional/FormTest.php @@ -275,8 +275,7 @@ public function testFieldFormUnlimited() { $this->assertSession()->fieldNotExists("{$field_name}[1][value]"); // Check if aria-describedby attribute is placed on multiple value widgets. - $elements = $this->xpath('//table[@id="field-unlimited-values" and @aria-describedby="edit-field-unlimited--description"]'); - $this->assertTrue(isset($elements[0]), 'aria-describedby attribute is properly placed on multiple value widgets.'); + $this->assertSession()->elementAttributeContains('xpath', '//table[@id="field-unlimited-values"]', 'aria-describedby', 'edit-field-unlimited--description'); // Press 'add more' button -> 2 widgets. $this->submitForm([], 'Add another item'); @@ -362,8 +361,7 @@ public function testFieldFormUnlimitedRequired() { // Display creation form -> 1 widget. $this->drupalGet('entity_test/add'); // Check that the Required symbol is present for the multifield label. - $element = $this->xpath('//h4[contains(@class, "label") and contains(@class, "js-form-required") and contains(text(), :value)]', [':value' => $this->field['label']]); - $this->assertTrue(isset($element[0]), 'Required symbol added field label.'); + $this->assertSession()->elementAttributeContains('xpath', "//h4[contains(@class, 'label') and contains(text(), '{$this->field['label']}')]", 'class', 'js-form-required'); // Check that the label of the field input is visually hidden and contains // the field title and an indication of the delta for a11y. $this->assertSession()->elementExists('xpath', "//label[@for='edit-field-unlimited-0-value' and contains(@class, 'visually-hidden') and contains(text(), '{$this->field['label']} (value 1)')]"); diff --git a/core/modules/field_ui/tests/src/Functional/FieldUIDeleteTest.php b/core/modules/field_ui/tests/src/Functional/FieldUIDeleteTest.php index 00746fc6e41a9d8de62465074ae196d6e750ae1f..a8e2c254c0c3abc4ab2bec886fda157da57b3014 100644 --- a/core/modules/field_ui/tests/src/Functional/FieldUIDeleteTest.php +++ b/core/modules/field_ui/tests/src/Functional/FieldUIDeleteTest.php @@ -124,9 +124,8 @@ public function testDeleteField() { $this->assertSession()->pageTextContains('The listed configuration will be updated.'); $this->assertSession()->elementTextEquals('xpath', '//ul[@data-drupal-selector="edit-view"]', 'test_view_field_delete'); - $xml = $this->cssSelect('#edit-entity-deletes'); // Test that nothing is scheduled for deletion. - $this->assertFalse(isset($xml[0]), 'The field currently being deleted is not shown in the entity deletions.'); + $this->assertSession()->elementNotExists('css', '#edit-entity-deletes'); // Delete the second field. $this->fieldUIDeleteField($bundle_path2, "node.$type_name2.$field_name", $field_label, $type_name2); diff --git a/core/modules/forum/tests/src/Functional/ForumTest.php b/core/modules/forum/tests/src/Functional/ForumTest.php index 29135c74837ed545e2fd2b9326274b0ce6952309..1f0cac216ca40beb10f0a884baca93001fe13e38 100644 --- a/core/modules/forum/tests/src/Functional/ForumTest.php +++ b/core/modules/forum/tests/src/Functional/ForumTest.php @@ -382,8 +382,7 @@ private function doAdminTests($user) { $this->drupalGet('admin/structure/taxonomy/manage/tags/add'); $this->assertSession()->fieldExists('parent[]'); // Test relations widget exists. - $relations_widget = $this->xpath("//details[@id='edit-relations']"); - $this->assertTrue(isset($relations_widget[0]), 'Relations widget element found.'); + $this->assertSession()->elementExists('xpath', "//details[@id='edit-relations']"); } /** diff --git a/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php b/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php index 98a2bd4352fb1597ad2a01cfbf3ba5efc2b08036..7082f30164707dfe8977ae209c60bac5d397c978 100644 --- a/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php +++ b/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php @@ -260,8 +260,6 @@ public function testLanguageLinkActiveClass() { * Check the path-admin class, as same as on default language. */ public function testLanguageBodyClass() { - $searched_class = 'path-admin'; - // Add language. $edit = [ 'predefined_langcode' => 'fr', @@ -276,13 +274,11 @@ public function testLanguageBodyClass() { // Check if the default (English) admin/config page has the right class. $this->drupalGet('admin/config'); - $class = $this->xpath('//body[contains(@class, :class)]', [':class' => $searched_class]); - $this->assertTrue(isset($class[0]), 'The path-admin class appears on default language.'); + $this->assertSession()->elementAttributeContains('xpath', '//body', 'class', 'path-admin'); // Check if the French admin/config page has the right class. $this->drupalGet('fr/admin/config'); - $class = $this->xpath('//body[contains(@class, :class)]', [':class' => $searched_class]); - $this->assertTrue(isset($class[0]), 'The path-admin class same as on default language.'); + $this->assertSession()->elementAttributeContains('xpath', '//body', 'class', 'path-admin'); // The testing profile sets the user/login page as the frontpage. That // redirects authenticated users to their profile page, so check with an @@ -291,14 +287,11 @@ public function testLanguageBodyClass() { // Check if the default (English) frontpage has the right class. $this->drupalGet('<front>'); - $class = $this->xpath('//body[contains(@class, :class)]', [':class' => 'path-frontpage']); - $this->assertTrue(isset($class[0]), 'path-frontpage class found on the body tag'); + $this->assertSession()->elementAttributeContains('xpath', '//body', 'class', 'path-frontpage'); // Check if the French frontpage has the right class. $this->drupalGet('fr'); - $class = $this->xpath('//body[contains(@class, :class)]', [':class' => 'path-frontpage']); - $this->assertTrue(isset($class[0]), 'path-frontpage class found on the body tag with french as the active language'); - + $this->assertSession()->elementAttributeContains('xpath', '//body', 'class', 'path-frontpage'); } /** diff --git a/core/modules/system/tests/src/Functional/Form/ConfirmFormTest.php b/core/modules/system/tests/src/Functional/Form/ConfirmFormTest.php index 1cd9a8eb7482cb0a0efc71dffcff184c03b56ed1..e6d33b41c2a694d48b936530ffed6227bfb39c5c 100644 --- a/core/modules/system/tests/src/Functional/Form/ConfirmFormTest.php +++ b/core/modules/system/tests/src/Functional/Form/ConfirmFormTest.php @@ -2,7 +2,6 @@ namespace Drupal\Tests\system\Functional\Form; -use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Url; use Drupal\Tests\BrowserTestBase; @@ -60,32 +59,16 @@ public function testConfirmForm() { */ public function testConfirmFormWithExternalDestination() { $this->drupalGet('form-test/confirm-form'); - $this->assertCancelLinkUrl(Url::fromRoute('form_test.route8')); + $this->assertSession()->linkByHrefExists(Url::fromRoute('form_test.route8')->toString()); $this->drupalGet('form-test/confirm-form', ['query' => ['destination' => 'node']]); - $this->assertCancelLinkUrl(Url::fromUri('internal:/node')); + $this->assertSession()->linkByHrefExists(Url::fromUri('internal:/node')->toString()); $this->drupalGet('form-test/confirm-form', ['query' => ['destination' => 'http://example.com']]); - $this->assertCancelLinkUrl(Url::fromRoute('form_test.route8')); + $this->assertSession()->linkByHrefExists(Url::fromRoute('form_test.route8')->toString()); $this->drupalGet('form-test/confirm-form', ['query' => ['destination' => '<front>']]); - $this->assertCancelLinkUrl(Url::fromRoute('<front>')); + $this->assertSession()->linkByHrefExists(Url::fromRoute('<front>')->toString()); // Other invalid destinations, should fall back to the form default. $this->drupalGet('form-test/confirm-form', ['query' => ['destination' => '/http://example.com']]); - $this->assertCancelLinkUrl(Url::fromRoute('form_test.route8')); - } - - /** - * Asserts that a cancel link is present pointing to the provided URL. - * - * @param \Drupal\Core\Url $url - * The url to check for. - * @param string $message - * The assert message. - * - * @internal - */ - public function assertCancelLinkUrl(Url $url, string $message = ''): void { - $links = $this->xpath('//a[@href=:url]', [':url' => $url->toString()]); - $message = ($message ? $message : new FormattableMarkup('Cancel link with URL %url found.', ['%url' => $url->toString()])); - $this->assertTrue(isset($links[0]), $message); + $this->assertSession()->linkByHrefExists(Url::fromRoute('form_test.route8')->toString()); } } diff --git a/core/modules/system/tests/src/Functional/Form/ElementsLabelsTest.php b/core/modules/system/tests/src/Functional/Form/ElementsLabelsTest.php index 4eb3d96fb7c06a2cbe7cf725f97aa016ef85fed3..21771b87210cbe229488c1407874008ef58076c2 100644 --- a/core/modules/system/tests/src/Functional/Form/ElementsLabelsTest.php +++ b/core/modules/system/tests/src/Functional/Form/ElementsLabelsTest.php @@ -52,11 +52,18 @@ public function testFormLabels() { // Verify that label precedes textfield, with required marker inside label. $this->assertSession()->elementExists('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"]'); + // Verify that label tag with required marker precedes required textfield + // with no title. $this->assertSession()->elementExists('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"]'); + + // Verify that label preceding field and label class is visually-hidden. $this->assertSession()->elementExists('xpath', '//input[@id="edit-form-textfield-test-title-invisible"]/preceding-sibling::label[@for="edit-form-textfield-test-title-invisible" and @class="visually-hidden"]'); + // Verify that no required marker on non-required field. $this->assertSession()->elementNotExists('xpath', '//input[@id="edit-form-textfield-test-title"]/preceding-sibling::span[@class="js-form-required form-required"]'); + // Verify that label after field and label option class correct for text + // field. $this->assertSession()->elementExists('xpath', '//input[@id="edit-form-textfield-test-title-after"]/following-sibling::label[@for="edit-form-textfield-test-title-after" and @class="option"]'); // Verify that no label tag exists when title set not to display. @@ -107,11 +114,13 @@ public function testFormDescriptions() { // Check #description placement with #description_display='after'. $field_id = 'edit-form-textfield-test-description-after'; $description_id = $field_id . '--description'; + // Verify the #description element is placed after the form item. $this->assertSession()->elementExists('xpath', '//input[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]/following-sibling::div[@id="' . $description_id . '"]'); // Check #description placement with #description_display='before'. $field_id = 'edit-form-textfield-test-description-before'; $description_id = $field_id . '--description'; + // Verify the #description element is placed before the form item. $this->assertSession()->elementExists('xpath', '//input[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]/preceding-sibling::div[@id="' . $description_id . '"]'); // Check if the class is 'visually-hidden' on the form element description @@ -119,6 +128,7 @@ public function testFormDescriptions() { // the description is placed after the form element. $field_id = 'edit-form-textfield-test-description-invisible'; $description_id = $field_id . '--description'; + // Verify that the #description element is visually-hidden. $this->assertSession()->elementExists('xpath', '//input[@id="' . $field_id . '" and @aria-describedby="' . $description_id . '"]/following-sibling::div[contains(@class, "visually-hidden")]'); } diff --git a/core/modules/system/tests/src/Functional/Form/FormTest.php b/core/modules/system/tests/src/Functional/Form/FormTest.php index d1b00eea3650a0791b0c1bcfbf8c1f88ba49c340..471f30390496d56d7da8ba2fca4e647f65a28833 100644 --- a/core/modules/system/tests/src/Functional/Form/FormTest.php +++ b/core/modules/system/tests/src/Functional/Form/FormTest.php @@ -859,12 +859,11 @@ public function testDisabledMarkup() { } $path = strtr($path, ['!type' => $type]); // Verify that the element exists. - $element = $this->xpath($path, [ + $this->assertSession()->elementExists('xpath', $this->assertSession()->buildXPathQuery($path, [ ':name' => Html::escape($name), ':div-class' => $class, ':value' => $item['#value'] ?? '', - ]); - $this->assertTrue(isset($element[0]), new FormattableMarkup('Disabled form element class found for #type %type.', ['%type' => $item['#type']])); + ])); } // Verify special element #type text-format. diff --git a/core/modules/system/tests/src/Functional/Routing/RouterTest.php b/core/modules/system/tests/src/Functional/Routing/RouterTest.php index cc40407a76a0ad4788733e725ceaa2335bfecf9d..8dc066434415baba96b2bc5aae8748516e66488d 100644 --- a/core/modules/system/tests/src/Functional/Routing/RouterTest.php +++ b/core/modules/system/tests/src/Functional/Routing/RouterTest.php @@ -81,16 +81,14 @@ public function testFinishResponseSubscriber() { $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Tags', 'config:user.role.anonymous foo http_response rendered'); // 3. controller result: Response object, globally cacheable route access. $this->drupalGet('router_test/test1'); - $headers = $session->getResponseHeaders(); - $this->assertFalse(isset($headers['X-Drupal-Cache-Contexts'])); - $this->assertFalse(isset($headers['X-Drupal-Cache-Tags'])); - $this->assertFalse(isset($headers['X-Drupal-Cache-Max-Age'])); + $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache-Contexts'); + $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache-Tags'); + $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache-Max-Age'); // 4. controller result: Response object, per-role cacheable route access. $this->drupalGet('router_test/test20'); - $headers = $session->getResponseHeaders(); - $this->assertFalse(isset($headers['X-Drupal-Cache-Contexts'])); - $this->assertFalse(isset($headers['X-Drupal-Cache-Tags'])); - $this->assertFalse(isset($headers['X-Drupal-Cache-Max-Age'])); + $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache-Contexts'); + $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache-Tags'); + $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache-Max-Age'); // 5. controller result: CacheableResponse object, globally cacheable route access. $this->drupalGet('router_test/test21'); $this->assertSession()->responseHeaderEquals('X-Drupal-Cache-Contexts', ''); @@ -103,18 +101,16 @@ public function testFinishResponseSubscriber() { // Finally, verify that the X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags // headers are not sent when their container parameter is set to FALSE. $this->drupalGet('router_test/test18'); - $headers = $session->getResponseHeaders(); - $this->assertTrue(isset($headers['X-Drupal-Cache-Contexts'])); - $this->assertTrue(isset($headers['X-Drupal-Cache-Tags'])); - $this->assertTrue(isset($headers['X-Drupal-Cache-Max-Age'])); + $this->assertSession()->responseHeaderExists('X-Drupal-Cache-Contexts'); + $this->assertSession()->responseHeaderExists('X-Drupal-Cache-Tags'); + $this->assertSession()->responseHeaderExists('X-Drupal-Cache-Max-Age'); $this->setContainerParameter('http.response.debug_cacheability_headers', FALSE); $this->rebuildContainer(); $this->resetAll(); $this->drupalGet('router_test/test18'); - $headers = $session->getResponseHeaders(); - $this->assertFalse(isset($headers['X-Drupal-Cache-Contexts'])); - $this->assertFalse(isset($headers['X-Drupal-Cache-Tags'])); - $this->assertFalse(isset($headers['X-Drupal-Cache-Max-Age'])); + $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache-Contexts'); + $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache-Tags'); + $this->assertSession()->responseHeaderDoesNotExist('X-Drupal-Cache-Max-Age'); } /** diff --git a/core/modules/system/tests/src/Functional/System/SiteMaintenanceTest.php b/core/modules/system/tests/src/Functional/System/SiteMaintenanceTest.php index 0503da1715ec907d12834b78bd8a80ffc4d65c22..61efe6f0f83ae6709120b4a55b8b83493bdc1329 100644 --- a/core/modules/system/tests/src/Functional/System/SiteMaintenanceTest.php +++ b/core/modules/system/tests/src/Functional/System/SiteMaintenanceTest.php @@ -63,8 +63,7 @@ public function testSiteMaintenance() { $this->drupalGet(Url::fromRoute('user.page')); // JS should be aggregated, so drupal.js is not in the page source. - $links = $this->xpath('//script[contains(@src, :href)]', [':href' => '/core/misc/drupal.js']); - $this->assertFalse(isset($links[0]), 'script /core/misc/drupal.js not in page'); + $this->assertSession()->elementNotExists('xpath', '//script[contains(@src, "/core/misc/drupal.js")]'); // Turn on maintenance mode. $edit = [ 'maintenance_mode' => 1, @@ -78,8 +77,7 @@ public function testSiteMaintenance() { $this->drupalGet(Url::fromRoute('user.page')); // JS should not be aggregated, so drupal.js is expected in the page source. - $links = $this->xpath('//script[contains(@src, :href)]', [':href' => '/core/misc/drupal.js']); - $this->assertTrue(isset($links[0]), 'script /core/misc/drupal.js in page'); + $this->assertSession()->elementExists('xpath', '//script[contains(@src, "/core/misc/drupal.js")]'); $this->assertSession()->pageTextContains($admin_message); $this->assertSession()->linkExists('Go online.'); $this->assertSession()->linkByHrefExists(Url::fromRoute('system.site_maintenance_mode')->toString()); diff --git a/core/modules/views_ui/tests/src/Functional/DefaultViewsTest.php b/core/modules/views_ui/tests/src/Functional/DefaultViewsTest.php index 012841d2c1669fc3d69e326684a2b27bd6fd28fc..771f644b2a14b846fdef707d2de11a67bcec5ef5 100644 --- a/core/modules/views_ui/tests/src/Functional/DefaultViewsTest.php +++ b/core/modules/views_ui/tests/src/Functional/DefaultViewsTest.php @@ -2,7 +2,6 @@ namespace Drupal\Tests\views_ui\Functional; -use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Url; use Drupal\user\Entity\Role; use Drupal\user\RoleInterface; @@ -232,27 +231,9 @@ public function testPathDestination() { * link. For example, if the link URL is expected to look like * "admin/structure/views/view/glossary/*", then "/glossary/" could be * passed as the expected unique string. - * - * @return - * The page content that results from clicking on the link, or FALSE on - * failure. Failure also results in a failed assertion. */ public function clickViewsOperationLink($label, $unique_href_part) { - $links = $this->xpath('//a[normalize-space(text())=:label]', [':label' => (string) $label]); - foreach ($links as $link_index => $link) { - $position = strpos($link->getAttribute('href'), $unique_href_part); - if ($position !== FALSE) { - $index = $link_index; - break; - } - } - $this->assertTrue(isset($index), new FormattableMarkup('Link to "@label" containing @part found.', ['@label' => $label, '@part' => $unique_href_part])); - if (isset($index)) { - return $this->clickLink((string) $label, $index); - } - else { - return FALSE; - } + $this->assertSession()->elementExists('xpath', "//a[normalize-space(text())='$label' and contains(@href, '$unique_href_part')]")->click(); } }