From 8a55c1a0c27425afb05c51b951e7d889f42afcd5 Mon Sep 17 00:00:00 2001 From: Adam G-H <32250-phenaproxima@users.noreply.drupalcode.org> Date: Fri, 21 Feb 2025 19:42:46 +0000 Subject: [PATCH] Issue #3507922 by phenaproxima, tim.plunkett: Add assertPageHasText() as a more assertive waitForText() --- .../ProjectBrowserExamplePluginTest.php | 2 +- .../ProjectBrowserInstallerUiTest.php | 11 ++--- .../ProjectBrowserPluginTest.php | 8 ++-- .../ProjectBrowserUiTest.php | 42 ++++++++++--------- .../ProjectBrowserUiTestJsonApi.php | 17 ++++---- .../ProjectBrowserUiTestTrait.php | 27 ++++++------ 6 files changed, 50 insertions(+), 57 deletions(-) diff --git a/tests/src/FunctionalJavascript/ProjectBrowserExamplePluginTest.php b/tests/src/FunctionalJavascript/ProjectBrowserExamplePluginTest.php index 29c01642e..280858eff 100644 --- a/tests/src/FunctionalJavascript/ProjectBrowserExamplePluginTest.php +++ b/tests/src/FunctionalJavascript/ProjectBrowserExamplePluginTest.php @@ -52,7 +52,7 @@ class ProjectBrowserExamplePluginTest extends WebDriverTestBase { $this->svelteInitHelper('css', '#project-browser .pb-project--grid'); $this->assertEquals('Grid', $this->getElementText('#project-browser .pb-display__button[value="Grid"]')); $this->assertElementIsVisible('css', '#project-browser .pb-project'); - $this->assertTrue($assert_session->waitForText('Project 1')); + $this->assertPageHasText('Project 1'); $assert_session->pageTextNotContains('No modules found'); $this->svelteInitHelper('css', '.pb-filter__checkbox'); $assert_session->elementsCount('css', '.pb-filter__checkbox', 2); diff --git a/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php b/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php index eaf989a41..f06182970 100644 --- a/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php +++ b/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php @@ -175,8 +175,6 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase { * @covers ::unlock */ public function testCanBreakStageWithMissingProjectBrowserLock(): void { - $assert_session = $this->assertSession(); - // Start install begin. $this->drupalGet('admin/modules/project_browser/install-begin', [ 'query' => ['source' => 'project_browser_test_mock'], @@ -188,7 +186,7 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase { $this->waitForProject('Cream cheese on a bagel') ->pressButton('Install Cream cheese on a bagel'); - $this->assertTrue($assert_session->waitForText('The process for adding projects is locked, but that lock has expired. Use unlock link to unlock the process and try to add the project again.')); + $this->assertPageHasText('The process for adding projects is locked, but that lock has expired. Use unlock link to unlock the process and try to add the project again.'); // Click Unlock Install Stage link. $this->clickWithWait('#ui-id-1 > p > a'); @@ -204,8 +202,6 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase { * @covers ::unlock */ public function testCanBreakLock(): void { - $assert_session = $this->assertSession(); - // Start install begin. $this->drupalGet('admin/modules/project_browser/install-begin', [ 'query' => ['source' => 'project_browser_test_mock'], @@ -215,7 +211,7 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase { // the applying stage. $this->waitForProject('Cream cheese on a bagel') ->pressButton('Install Cream cheese on a bagel'); - $this->assertTrue($assert_session->waitForText('The process for adding projects is locked, but that lock has expired. Use unlock link to unlock the process and try to add the project again.')); + $this->assertPageHasText('The process for adding projects is locked, but that lock has expired. Use unlock link to unlock the process and try to add the project again.'); // Click Unlock Install Stage link. $this->clickWithWait('#ui-id-1 > p > a'); // Try beginning another install after breaking lock. @@ -230,11 +226,10 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase { $this->container->get(StateInterface::class) ->set('project_browser_test.simulated_result_severity', SystemManager::REQUIREMENT_ERROR); - $assert_session = $this->assertSession(); $this->drupalGet('admin/modules/browse/project_browser_test_mock'); $cream_cheese = $this->waitForProject('Cream cheese on a bagel'); $cream_cheese->pressButton('Install Cream cheese on a bagel'); - $this->assertTrue($assert_session->waitForText('Simulate an error message for the project browser.')); + $this->assertPageHasText('Simulate an error message for the project browser.'); $this->assertTrue($cream_cheese->hasButton('Install Cream cheese on a bagel')); } diff --git a/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php b/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php index d0ea21375..4e0221e44 100644 --- a/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php +++ b/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php @@ -60,7 +60,7 @@ class ProjectBrowserPluginTest extends WebDriverTestBase { $this->svelteInitHelper('css', '#project-browser .pb-project--grid'); $this->assertEquals('Grid', $this->getElementText('#project-browser .pb-display__button[value="Grid"]')); $this->assertElementIsVisible('css', '#project-browser .pb-project'); - $this->assertTrue($assert_session->waitForText('Results')); + $this->assertPageHasText('Results'); $assert_session->pageTextNotContains('No modules found'); } @@ -154,15 +154,13 @@ class ProjectBrowserPluginTest extends WebDriverTestBase { * Tests the detail page. */ public function testDetailPageRandomDataPlugin(): void { - $assert_session = $this->assertSession(); - $this->drupalGet('admin/modules/browse/random_data'); $this->assertElementIsVisible('css', '#project-browser .pb-project'); - $this->assertTrue($assert_session->waitForText('Results')); + $this->assertPageHasText('Results'); $this->assertElementIsVisible('css', '.pb-project .pb-project__title .pb-project__link') ->click(); - $this->assertTrue($assert_session->waitForText('sites report using this module')); + $this->assertPageHasText('sites report using this module'); } } diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php index 5966812df..c79c0cc5a 100644 --- a/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php +++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Drupal\Tests\project_browser\FunctionalJavascript; +use Behat\Mink\Element\DocumentElement; use Behat\Mink\Element\NodeElement; use Drupal\Core\Extension\MissingDependencyException; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; @@ -72,7 +73,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { $this->assertNotEmpty($assert_session->waitForButton('Grid')); $this->svelteInitHelper('text', '10 Results'); $assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--grid', 10); - $this->assertTrue($assert_session->waitForText('Results')); + $this->assertPageHasText('Results'); $assert_session->pageTextNotContains('No modules found'); $page->pressButton('List'); $this->assertElementIsVisible('css', '#project-browser .pb-project.pb-project--list'); @@ -121,7 +122,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { $this->drupalGet('admin/modules/browse/project_browser_test_mock'); $this->svelteInitHelper('css', '.pb-filter__multi-dropdown'); // Initial results count on page load. - $this->assertTrue($assert_session->waitForText('10 Results')); + $this->assertPageHasText('10 Results'); // Open category drop-down. $this->clickWithWait('.pb-filter__multi-dropdown', 'E-commerce', TRUE); @@ -192,7 +193,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { 'Kangaroo', '9 Starts With a Higher Number', ]); - $this->assertTrue($assert_session->waitForText('20 Results')); + $this->assertPageHasText('20 Results'); } /** @@ -259,7 +260,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { $this->assertPagerItems([]); $page->pressButton('Clear filters'); - $this->assertTrue($assert_session->waitForText('25 Results')); + $this->assertPageHasText('25 Results'); $this->assertProjectsVisible([ 'Jazz', 'Eggman', @@ -327,17 +328,19 @@ class ProjectBrowserUiTest extends WebDriverTestBase { */ public function testPagingOptions(): void { $page = $this->getSession()->getPage(); - $assert_session = $this->assertSession(); + $await_n_projects = function (int $count) use ($page): void { + $this->assertTrue($page->waitFor( + 10, + fn (DocumentElement $page) => count($page->findAll('css', '#project-browser .pb-project.pb-project--list')) === $count, + )); + }; $this->drupalGet('admin/modules/browse/project_browser_test_mock'); $this->svelteInitHelper('css', '.pb-project.pb-project--list'); $this->pressWithWait('Clear filters'); - $assert_session->waitForText('Modules per page'); - $assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--list', 12); - $assert_session->waitForText('Modules per page'); + $await_n_projects(12); $page->selectFieldOption('num-projects', '24'); - $this->assertElementIsVisible('css', '#project-browser .pb-project.pb-project--list'); - $assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--list', 24); + $await_n_projects(24); } /** @@ -664,7 +667,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { $this->assertElementIsVisible('css', '#67'); $this->clickWithWait('#67', '', TRUE); - $this->assertTrue($assert_session->waitForText('15 Results')); + $this->assertPageHasText('15 Results'); $this->assertProjectsVisible([ 'Octopus', 'No Scrubs', @@ -694,7 +697,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { '9 Starts With a Higher Number', '1 Starts With a Number', ]); - $this->assertTrue($assert_session->waitForText('15 Results')); + $this->assertPageHasText('15 Results'); $this->assertEquals('E-commerce', $this->getElementText('p.filter-applied:first-child .filter-applied__label')); $this->assertEquals('Media', $this->getElementText('p.filter-applied:nth-child(2) .filter-applied__label')); @@ -723,7 +726,6 @@ class ProjectBrowserUiTest extends WebDriverTestBase { * Tests recommended filters. */ public function testRecommendedFilter(): void { - $assert_session = $this->assertSession(); // Clear filters. $this->drupalGet('admin/modules/browse/project_browser_test_mock'); $this->svelteInitHelper('text', 'Clear Filters'); @@ -734,7 +736,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { $this->assertEquals('Show actively maintained projects', $this->getElementText(self::MAINTENANCE_OPTION_SELECTOR . self::OPTION_CHECKED)); // Make sure the second filter applied is the security covered filter. $this->assertEquals('Show projects covered by a security policy', $this->getElementText(self::SECURITY_OPTION_SELECTOR . self::OPTION_CHECKED)); - $this->assertTrue($assert_session->waitForText('10 Results')); + $this->assertPageHasText('10 Results'); } /** @@ -835,7 +837,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { // Filter by search text. $this->inputSearchField('Number', TRUE); $this->assertElementIsVisible('css', ".search__search-submit")->click(); - $this->assertTrue($assert_session->waitForText('2 Results')); + $this->assertPageHasText('2 Results'); $this->assertProjectsVisible([ '9 Starts With a Higher Number', '1 Starts With a Number', @@ -847,7 +849,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { $this->pressWithWait('project_browser_test_mock'); $this->svelteInitHelper('css', '#project-browser .pb-project'); // Assert that the filters persist. - $this->assertTrue($assert_session->waitForText('2 Results')); + $this->assertPageHasText('2 Results'); $this->assertProjectsVisible([ '9 Starts With a Higher Number', '1 Starts With a Number', @@ -1189,7 +1191,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { // This asserts that status icon is present on the cards. $this->assertElementIsVisible('css', '.pb-project__maintenance-icon .pb-project__status-icon-btn'); $assert_session->waitForButton('Helvetica')?->click(); - $this->assertTrue($assert_session->waitForText('The module is actively maintained by the maintainers')); + $this->assertPageHasText('The module is actively maintained by the maintainers'); // This asserts that status icon is present in detail's modal. $this->assertElementIsVisible('css', '.pb-detail-modal__sidebar .pb-project__status-icon-btn'); $page->find('css', '.ui-dialog-titlebar-close')?->click(); @@ -1212,7 +1214,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { // Ensure the project list is loaded. $this->assertElementIsVisible('css', '#project-browser .pb-project'); - $this->assertTrue($assert_session->waitForText('Results')); + $this->assertPageHasText('Results'); // Expect Grapefruit to have 1 install. $this->assertElementIsVisible('xpath', '//span[contains(@class, "pb-project__install-count") and text()="1 install"]'); @@ -1222,7 +1224,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { $grapefruit_link?->click(); // Verify the text for Grapefruit (singular case). - $this->assertTrue($assert_session->waitForText('site reports using this module')); + $this->assertPageHasText('site reports using this module'); // Go back to the project list. $close_button = $page->find('xpath', '//button[contains(@class, "ui-dialog-titlebar-close") and contains(text(), "Close")]'); @@ -1236,7 +1238,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase { $octopus_link?->click(); // Verify the text for Octopus (plural case). - $this->assertTrue($assert_session->waitForText('sites report using this module')); + $this->assertPageHasText('sites report using this module'); } /** diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php index 33d802b69..8ecae7289 100644 --- a/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php +++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php @@ -77,7 +77,7 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { $this->assertElementIsVisible('css', '#project-browser .pb-display__button[value="Grid"]'); $grid_text = $this->getElementText('#project-browser .pb-display__button[value="Grid"]'); $this->assertEquals('Grid', $grid_text); - $this->assertTrue($assert_session->waitForText('Results')); + $this->assertPageHasText('Results'); $assert_session->pageTextNotContains('No records available'); $page->pressButton('List'); $this->assertElementIsVisible('css', '#project-browser .pb-project.pb-project--list'); @@ -125,7 +125,7 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { $this->drupalGet('admin/modules/browse/drupalorg_jsonapi'); $this->svelteInitHelper('css', '.pb-filter__multi-dropdown'); // Initial results count on page load. - $this->assertTrue($assert_session->waitForText(' Results')); + $this->assertPageHasText(' Results'); $assert_session->pageTextNotContains(' 0 Results'); // Open category drop-down. $this->clickWithWait('.pb-filter__multi-dropdown', 'E-commerce', TRUE); @@ -158,7 +158,7 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { // Click 'Media' checkbox. $this->clickWithWait('#68428c33-1db7-438d-b1b3-e23004e0982b'); - $this->assertTrue($assert_session->waitForText(' Results')); + $this->assertPageHasText(' Results'); $assert_session->pageTextNotContains(' 0 Results'); // Click 'Developer tools' checkbox. @@ -166,7 +166,7 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { // Make sure the 'Media' module category filter is applied. $this->assertEquals('Media', $this->getElementText('p.filter-applied:nth-child(2) .filter-applied__label')); - $this->assertTrue($assert_session->waitForText(' Results')); + $this->assertPageHasText(' Results'); $assert_session->pageTextNotContains(' 0 Results'); } @@ -193,7 +193,7 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { $this->assertPagerItems(['1', '2', '3', '4', '5', '…', 'Next', 'Last']); $page->pressButton('Clear filters'); - $this->assertTrue($assert_session->waitForText(' Results')); + $this->assertPageHasText(' Results'); $assert_session->pageTextNotContains(' 0 Results'); $this->assertPagerItems(['1', '2', '3', '4', '5', '…', 'Next', 'Last']); $assert_session->elementExists('css', '.pager__item--active > .is-active[aria-label="Page 1"]'); @@ -254,7 +254,6 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { // Make sure the correct filter was applied. $this->assertEquals('Show projects under active development', $this->getElementText(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_CHECKED)); - $assert_session->waitForText('No records available'); // Clear all filters. $this->pressWithWait('Clear filters', 'Results'); @@ -323,7 +322,7 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { $this->assertTrue($assert_session->optionExists('maintenance_status', 'Show actively maintained projects')->isSelected()); // Make sure the second filter applied is the security covered filter. $this->assertTrue($assert_session->optionExists('security_advisory_coverage', 'Show projects covered by a security policy')->isSelected()); - $this->assertTrue($assert_session->waitForText(' Results')); + $this->assertPageHasText(' Results'); $assert_session->pageTextNotContains(' 0 Results'); } @@ -354,9 +353,9 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { // Drupal.org test mock defines only two filters (actively maintained filter // and security coverage filter). $this->assertElementIsVisible('css', '.search__form-filters-container'); - $this->assertTrue($assert_session->waitForText('Maintenance status')); + $this->assertPageHasText('Maintenance status'); $this->assertElementIsVisible('css', self::MAINTENANCE_OPTION_SELECTOR); - $this->assertTrue($assert_session->waitForText('Security advisory coverage')); + $this->assertPageHasText('Security advisory coverage'); $this->assertElementIsVisible('css', self::SECURITY_OPTION_SELECTOR); // Make sure no other filters are displayed. $this->assertFalse($assert_session->waitForText('Development status')); diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTestTrait.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTestTrait.php index 0816594aa..4b0488eb4 100644 --- a/tests/src/FunctionalJavascript/ProjectBrowserUiTestTrait.php +++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTestTrait.php @@ -11,6 +11,16 @@ use Behat\Mink\Element\NodeElement; */ trait ProjectBrowserUiTestTrait { + /** + * Waits for specific text to appear on the page. + * + * @param string $text + * The text we're waiting for. + */ + protected function assertPageHasText(string $text): void { + $this->assertTrue($this->assertSession()->waitForText($text), "Expected '$text' to appear on the page but it didn't."); + } + /** * Waits for an element to be visible, and returns it. * @@ -192,7 +202,7 @@ trait ProjectBrowserUiTestTrait { } if (!empty($wait_for_text)) { - $this->waitForPageToContainText($wait_for_text); + $this->assertPageHasText($wait_for_text); } } @@ -231,7 +241,7 @@ trait ProjectBrowserUiTestTrait { } if (!empty($wait_for_text)) { - $this->assertTrue($this->assertSession()->waitForText($wait_for_text)); + $this->assertPageHasText($wait_for_text); } } @@ -331,9 +341,8 @@ trait ProjectBrowserUiTestTrait { */ protected function assertPagerItems(array $pager_items): void { $page = $this->getSession()->getPage(); - $assert_session = $this->assertSession(); - $assert_session->waitForElementVisible('css', '#project-browser .pb-project'); + $this->assertElementIsVisible('css', '#project-browser .pb-project'); $items = array_map(function ($element) { return $element->getText(); }, $page->findAll('css', '#project-browser .pager__item')); @@ -343,16 +352,6 @@ trait ProjectBrowserUiTestTrait { $this->assertSame($pager_items, $items); } - /** - * Helper to wait for text on page. - * - * @param string $text - * The expected text. - */ - protected function waitForPageToContainText(string $text): void { - $this->assertTrue($this->assertSession()->waitForText($text), "Expected '$text' to appear on the page but it didn't."); - } - /** * Helper to wait for a field to appear on the page. * -- GitLab