diff --git a/core/modules/file/tests/src/Functional/FileFieldDisplayTest.php b/core/modules/file/tests/src/Functional/FileFieldDisplayTest.php index 922985cb4e3..72d150e70f6 100644 --- a/core/modules/file/tests/src/Functional/FileFieldDisplayTest.php +++ b/core/modules/file/tests/src/Functional/FileFieldDisplayTest.php @@ -115,7 +115,7 @@ class FileFieldDisplayTest extends FileFieldTestBase { $this->assertSession()->responseContains($field_name . '[1][description]', 'Description of second file appears as expected.'); // Check that the file fields don't contain duplicate HTML IDs. - $this->assertNoDuplicateIds(); + $this->assertSession()->pageContainsNoDuplicateId(); } /** @@ -229,32 +229,4 @@ class FileFieldDisplayTest extends FileFieldTestBase { $this->assertFieldByXPath('//a[@href="' . $node->{$field_name}->entity->createFileUrl(FALSE) . '"]', $description); } - /** - * Asserts that each HTML ID is used for just a single element on the page. - * - * @param string $message - * (optional) A message to display with the assertion. - */ - protected function assertNoDuplicateIds($message = '') { - $args = ['@url' => $this->getUrl()]; - - if (!$elements = $this->xpath('//*[@id]')) { - $this->fail(new FormattableMarkup('The page @url contains no HTML IDs.', $args)); - return; - } - - $message = $message ?: new FormattableMarkup('The page @url does not contain duplicate HTML IDs', $args); - - $seen_ids = []; - foreach ($elements as $element) { - $id = $element->getAttribute('id'); - if (isset($seen_ids[$id])) { - $this->fail($message); - return; - } - $seen_ids[$id] = TRUE; - } - $this->assertTrue(TRUE, $message); - } - } diff --git a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php index 08ff6155105..c59002baf50 100644 --- a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php +++ b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php @@ -155,6 +155,56 @@ class Test { return new RedirectResponse(Url::fromRoute('test_page_test.test_page', [], ['absolute' => TRUE])->toString(), 302); } + /** + * Returns a page render array with 2 elements with the same HTML IDs. + * + * @return array + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). + */ + public function renderPageWithDuplicateIds() { + return [ + '#type' => 'container', + 'title' => [ + '#type' => 'html_tag', + '#tag' => 'h1', + '#value' => 'Hello', + '#attributes' => ['id' => 'page-element'], + ], + 'description' => [ + '#type' => 'html_tag', + '#tag' => 'h2', + '#value' => 'World', + '#attributes' => ['id' => 'page-element'], + ], + ]; + } + + /** + * Returns a page render array with 2 elements with the unique HTML IDs. + * + * @return array + * A render array as expected by + * \Drupal\Core\Render\RendererInterface::render(). + */ + public function renderPageWithoutDuplicateIds() { + return [ + '#type' => 'container', + 'title' => [ + '#type' => 'html_tag', + '#tag' => 'h1', + '#value' => 'Hello', + '#attributes' => ['id' => 'page-element-title'], + ], + 'description' => [ + '#type' => 'html_tag', + '#tag' => 'h2', + '#value' => 'World', + '#attributes' => ['id' => 'page-element-description'], + ], + ]; + } + /** * Returns a page while triggering deprecation notices. */ diff --git a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml index 336f6c704ba..2f44e099db6 100644 --- a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml +++ b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml @@ -115,6 +115,20 @@ test_page_test.meta_refresh: requirements: _access: 'TRUE' +test_page_test.page_with_duplicate_ids: + path: '/test-page-with-duplicate-ids' + defaults: + _controller: '\Drupal\test_page_test\Controller\Test::renderPageWithDuplicateIds' + requirements: + _access: 'TRUE' + +test_page_test.page_without_duplicate_ids: + path: '/test-page-without-duplicate-ids' + defaults: + _controller: '\Drupal\test_page_test\Controller\Test::renderPageWithoutDuplicateIds' + requirements: + _access: 'TRUE' + test_page_test.deprecations: path: '/test-deprecations' defaults: diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php index 8b52d89a795..680cbb0ef31 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/MultiFormTest.php @@ -2,7 +2,6 @@ namespace Drupal\FunctionalJavascriptTests\Ajax; -use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; @@ -88,7 +87,7 @@ class MultiFormTest extends WebDriverTestBase { $this->assertFieldsByValue($field->find('xpath', '.' . $button_xpath_suffix), NULL, 'Found the "add more" button on the initial page.'); } - $this->assertNoDuplicateIds(); + $this->assertSession()->pageContainsNoDuplicateId(); // Submit the "add more" button of each form twice. After each corresponding // page update, ensure the same as above. @@ -108,37 +107,9 @@ class MultiFormTest extends WebDriverTestBase { $field = $page_updated->findAll('xpath', '.' . $field_xpath); $this->assertCount($i + 2, $field[0]->find('xpath', '.' . $field_items_xpath_suffix), 'Found the correct number of field items after an AJAX submission.'); $this->assertFieldsByValue($field[0]->find('xpath', '.' . $button_xpath_suffix), NULL, 'Found the "add more" button after an AJAX submission.'); - $this->assertNoDuplicateIds(); + $this->assertSession()->pageContainsNoDuplicateId(); } } } - /** - * Asserts that each HTML ID is used for just a single element on the page. - * - * @param string $message - * (optional) A message to display with the assertion. - */ - protected function assertNoDuplicateIds($message = '') { - $args = ['@url' => $this->getUrl()]; - - if (!$elements = $this->xpath('//*[@id]')) { - $this->fail(new FormattableMarkup('The page @url contains no HTML IDs.', $args)); - return; - } - - $message = $message ?: new FormattableMarkup('The page @url does not contain duplicate HTML IDs', $args); - - $seen_ids = []; - foreach ($elements as $element) { - $id = $element->getAttribute('id'); - if (isset($seen_ids[$id])) { - $this->fail($message); - return; - } - $seen_ids[$id] = TRUE; - } - $this->assertTrue(TRUE, $message); - } - } diff --git a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php index d6d8e442462..5ff8d75f48f 100644 --- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php +++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php @@ -770,6 +770,22 @@ class BrowserTestBaseTest extends BrowserTestBase { $this->assertSession()->statusCodeEquals(403); } + /** + * Tests pageContainsNoDuplicateId() functionality. + * + * @see \Drupal\Tests\WebAssert::pageContainsNoDuplicateId() + */ + public function testPageContainsNoDuplicateId() { + $assert_session = $this->assertSession(); + $this->drupalGet(Url::fromRoute('test_page_test.page_without_duplicate_ids')); + $assert_session->pageContainsNoDuplicateId(); + + $this->drupalGet(Url::fromRoute('test_page_test.page_with_duplicate_ids')); + $this->expectException(ExpectationException::class); + $this->expectExceptionMessage('The page contains a duplicate HTML ID "page-element".'); + $assert_session->pageContainsNoDuplicateId(); + } + /** * Tests assertEscaped() and assertUnescaped(). * diff --git a/core/tests/Drupal/Tests/WebAssert.php b/core/tests/Drupal/Tests/WebAssert.php index 7b296263ae4..e296077c217 100644 --- a/core/tests/Drupal/Tests/WebAssert.php +++ b/core/tests/Drupal/Tests/WebAssert.php @@ -626,4 +626,20 @@ class WebAssert extends MinkWebAssert { throw new ResponseTextException($message, $this->session->getDriver()); } + /** + * Asserts that each HTML ID is used for just a single element on the page. + * + * @throws \Behat\Mink\Exception\ExpectationException + */ + public function pageContainsNoDuplicateId() { + $seen_ids = []; + foreach ($this->session->getPage()->findAll('xpath', '//*[@id]') as $element) { + $id = $element->getAttribute('id'); + if (isset($seen_ids[$id])) { + throw new ExpectationException(sprintf('The page contains a duplicate HTML ID "%s".', $id), $this->session->getDriver()); + } + $seen_ids[$id] = TRUE; + } + } + }