diff --git a/core/modules/content_moderation/tests/src/Functional/ModerationActionsTest.php b/core/modules/content_moderation/tests/src/Functional/ModerationActionsTest.php index 148e09a1f9..9d67a6ff68 100644 --- a/core/modules/content_moderation/tests/src/Functional/ModerationActionsTest.php +++ b/core/modules/content_moderation/tests/src/Functional/ModerationActionsTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\content_moderation\Functional; use Drupal\node\Entity\Node; -use Drupal\Tests\AssertStatusMessageTrait; use Drupal\Tests\BrowserTestBase; use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait; use Drupal\Tests\node\Traits\ContentTypeCreationTrait; @@ -17,7 +16,6 @@ class ModerationActionsTest extends BrowserTestBase { use ContentTypeCreationTrait; use ContentModerationTestTrait; - use AssertStatusMessageTrait; /** * Modules to enable. @@ -83,14 +81,14 @@ public function testNodeStatusActions($action, $bundle, $warning_appears, $start if ($warning_appears) { if ($action == 'node_publish_action') { - $this->assertStatusMessageExists(node_get_type_label($node) . ' content items were skipped as they are under moderation and may not be directly published.'); + $this->assertSession()->statusMessageExists(node_get_type_label($node) . ' content items were skipped as they are under moderation and may not be directly published.', 'warning'); } else { - $this->assertStatusMessageExists(node_get_type_label($node) . ' content items were skipped as they are under moderation and may not be directly unpublished.', 'warning'); + $this->assertSession()->statusMessageExists(node_get_type_label($node) . ' content items were skipped as they are under moderation and may not be directly unpublished.', 'warning'); } } else { - $this->assertStatusMessageNotExists(NULL, 'warning'); + $this->assertSession()->statusMessageNotExists(NULL, 'warning'); } // Ensure after the action has run, the node matches the expected status. diff --git a/core/modules/file/tests/src/FunctionalJavascript/MaximumFileSizeExceededUploadTest.php b/core/modules/file/tests/src/FunctionalJavascript/MaximumFileSizeExceededUploadTest.php index d2a79aa574..5fef582215 100644 --- a/core/modules/file/tests/src/FunctionalJavascript/MaximumFileSizeExceededUploadTest.php +++ b/core/modules/file/tests/src/FunctionalJavascript/MaximumFileSizeExceededUploadTest.php @@ -4,7 +4,6 @@ use Drupal\Component\Utility\Bytes; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; -use Drupal\Tests\AssertJavascriptStatusMessageTrait; use Drupal\Tests\TestFileCreationTrait; use Drupal\Tests\file\Functional\FileFieldCreationTrait; @@ -17,7 +16,6 @@ class MaximumFileSizeExceededUploadTest extends WebDriverTestBase { use FileFieldCreationTrait; use TestFileCreationTrait; - use AssertJavascriptStatusMessageTrait; /** * {@inheritdoc} @@ -113,13 +111,13 @@ public function testUploadFileExceedingMaximumFileSize() { // the maximum file size. The error message includes the actual file size // limit which depends on the current environment, so we check for a part // of the message. - $this->assertStatusMessageVisibleAfterWait('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size', 'error'); + $this->assertSession()->statusMessageVisibleAfterWait('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size', 'error'); // Now upload a valid file and check that the error message disappears. $valid_file = $this->generateFile('not_exceeding_post_max_size', 8, 8); $page->attachFileToField("files[field_file_0]", $this->fileSystem->realpath($valid_file)); $this->assertSession()->waitForElement('named', ['id_or_name', 'field_file_0_remove_button']); - $this->assertNoStatusMessageAfterWait(NULL, 'error'); + $this->assertSession()->statusMessageNotVisibleAfterWait(NULL, 'error'); } } diff --git a/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php b/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php index 53399192c0..ecfe7fe174 100644 --- a/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php +++ b/core/modules/system/tests/modules/system_test/src/Controller/SystemTestController.php @@ -147,12 +147,12 @@ public function messengerServiceTest() { } /** - * Sets messages for testing the AssertStatusMessageTrait. + * Sets messages for testing the WebAssert methods related to messages. * * @return string * Empty string, we just test the setting of messages. */ - public function assertStatusMessageTraitTest() { + public function statusMessagesForAssertions() { // Add a simple message of each type. $this->messenger->addMessage('My Status Message', 'status'); $this->messenger->addMessage('My Error Message', 'error'); diff --git a/core/modules/system/tests/modules/system_test/system_test.routing.yml b/core/modules/system/tests/modules/system_test/system_test.routing.yml index 80cfbebeab..59b5d9116e 100644 --- a/core/modules/system/tests/modules/system_test/system_test.routing.yml +++ b/core/modules/system/tests/modules/system_test/system_test.routing.yml @@ -21,11 +21,11 @@ system_test.messenger_service: requirements: _access: 'TRUE' -system_test.assert_status_message_trait_test: - path: '/system-test/assert-status-message-trait-test' +system_test.status_messages_for_assertions: + path: '/system-test/status-messages-for-assertions' defaults: - _title: 'Set messages with Messenger service' - _controller: '\Drupal\system_test\Controller\SystemTestController::assertStatusMessageTraitTest' + _title: 'Set various message to test status message assertion methods' + _controller: '\Drupal\system_test\Controller\SystemTestController::statusMessagesForAssertions' requirements: _access: 'TRUE' diff --git a/core/modules/system/tests/src/Functional/Bootstrap/DrupalMessengerServiceTest.php b/core/modules/system/tests/src/Functional/Bootstrap/DrupalMessengerServiceTest.php index d24af2c9de..2e1c4202f4 100644 --- a/core/modules/system/tests/src/Functional/Bootstrap/DrupalMessengerServiceTest.php +++ b/core/modules/system/tests/src/Functional/Bootstrap/DrupalMessengerServiceTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\system\Functional\Bootstrap; use Drupal\Core\Url; -use Drupal\Tests\AssertStatusMessageTrait; use Drupal\Tests\BrowserTestBase; /** @@ -13,8 +12,6 @@ */ class DrupalMessengerServiceTest extends BrowserTestBase { - use AssertStatusMessageTrait; - /** * Modules to enable. * @@ -65,45 +62,45 @@ public function testDrupalMessengerService() { } /** - * Tests the AssertStatusMessageTrait. + * Tests assertion methods in WebAssert related to status messages. */ - public function testAssertStatusMessageTrait() { - $this->drupalGet(Url::fromRoute('system_test.assert_status_message_trait_test')); + public function testStatusMessageAssertions() { + $this->drupalGet(Url::fromRoute('system_test.status_messages_for_assertions')); // Use the simple messages to test basic functionality. // Test with no args. - $this->assertStatusMessageExists(); + $this->assertSession()->statusMessageExists(); // Test with no second arg. - $this->assertStatusMessageExists('My Status Message'); - $this->assertStatusMessageExists('My Error Message'); - $this->assertStatusMessageExists('My Warning Message'); + $this->assertSession()->statusMessageExists('My Status Message'); + $this->assertSession()->statusMessageExists('My Error Message'); + $this->assertSession()->statusMessageExists('My Warning Message'); // Test partial match. - $this->assertStatusMessageExists('My Status'); + $this->assertSession()->statusMessageExists('My Status'); // Test with second arg. - $this->assertStatusMessageExists('My Status Message', 'status'); - $this->assertStatusMessageExists('My Error Message', 'error'); - $this->assertStatusMessageExists('My Warning Message', 'warning'); + $this->assertSession()->statusMessageExists('My Status Message', 'status'); + $this->assertSession()->statusMessageExists('My Error Message', 'error'); + $this->assertSession()->statusMessageExists('My Warning Message', 'warning'); // Test with no first arg. - $this->assertStatusMessageExists(NULL, 'status'); - $this->assertStatusMessageExists(NULL, 'error'); - $this->assertStatusMessageExists(NULL, 'warning'); + $this->assertSession()->statusMessageExists(NULL, 'status'); + $this->assertSession()->statusMessageExists(NULL, 'error'); + $this->assertSession()->statusMessageExists(NULL, 'warning'); // Test negative assertions. - $this->assertStatusMessageNotExists('My Status Message is fake'); - $this->assertStatusMessageNotExists('My Status Message is fake', 'status'); - $this->assertStatusMessageNotExists('My Error Message', 'status'); - $this->assertStatusMessageNotExists('My Status Message', 'error'); + $this->assertSession()->statusMessageNotExists('My Status Message is fake'); + $this->assertSession()->statusMessageNotExists('My Status Message is fake', 'status'); + $this->assertSession()->statusMessageNotExists('My Error Message', 'status'); + $this->assertSession()->statusMessageNotExists('My Status Message', 'error'); // Check that special characters get handled correctly. - $this->assertStatusMessageExists('This has " in the middle'); - $this->assertStatusMessageExists('This has \' in the middle'); - $this->assertStatusMessageExists('Thismarkup will be escaped'); - $this->assertStatusMessageExists('Peaches & cream'); - $this->assertStatusMessageNotExists('Peaches & cream'); + $this->assertSession()->statusMessageExists('This has " in the middle'); + $this->assertSession()->statusMessageExists('This has \' in the middle'); + $this->assertSession()->statusMessageExists('Thismarkup will be escaped'); + $this->assertSession()->statusMessageExists('Peaches & cream'); + $this->assertSession()->statusMessageNotExists('Peaches & cream'); // Test with bad message type. $this->expectException(\InvalidArgumentException::class); - $this->assertStatusMessageExists('Any old message', 'something bad'); + $this->assertSession()->statusMessageExists('Any old message', 'something bad'); } } diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/MessageCommandTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/MessageCommandTest.php index 8867a69ae7..013aae6d7c 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/MessageCommandTest.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/MessageCommandTest.php @@ -3,7 +3,6 @@ namespace Drupal\FunctionalJavascriptTests\Ajax; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; -use Drupal\Tests\AssertJavascriptStatusMessageTrait; /** * Tests adding messages via AJAX command. @@ -12,8 +11,6 @@ */ class MessageCommandTest extends WebDriverTestBase { - use AssertJavascriptStatusMessageTrait; - /** * {@inheritdoc} */ @@ -80,53 +77,52 @@ public function testMessageCommand() { } /** - * Tests AssertJavascriptStatusMessageTrait. + * Tests methods in JsWebAssert related to status messages. */ - public function testAssertJavascriptStatusMessageTrait() { + public function testJsStatusMessageAssertions() { $page = $this->getSession()->getPage(); - $assert_session = $this->assertSession(); $this->drupalGet('ajax-test/message'); $page->pressButton('Make Message In Default Location'); - $this->assertStatusMessageVisibleAfterWait('I am a message in the default location.'); + $this->assertSession()->statusMessageVisibleAfterWait('I am a message in the default location.'); $page->pressButton('Make Message In Alternate Location'); - $this->assertStatusMessageVisibleAfterWait('I am a message in an alternate location.', 'status'); + $this->assertSession()->statusMessageVisibleAfterWait('I am a message in an alternate location.', 'status'); $page->pressButton('Make Warning Message'); - $this->assertStatusMessageVisibleAfterWait('I am a warning message in the default location.', 'warning'); + $this->assertSession()->statusMessageVisibleAfterWait('I am a warning message in the default location.', 'warning'); // Reload and test some negative assertions. $this->drupalGet('ajax-test/message'); $page->pressButton('Make Message In Default Location'); // Use message that is not on page. - $this->assertNoStatusMessageAfterWait('This is not a real message'); + $this->assertSession()->statusMessageNotVisibleAfterWait('This is not a real message'); $page->pressButton('Make Message In Alternate Location'); // Use message that exists but has the wrong type. - $this->assertNoStatusMessageAfterWait('I am a message in an alternate location.', 'warning'); + $this->assertSession()->statusMessageNotVisibleAfterWait('I am a message in an alternate location.', 'warning'); // Test partial match. $page->pressButton('Make Warning Message'); - $this->assertStatusMessageVisibleAfterWait('I am a warning'); + $this->assertSession()->statusMessageVisibleAfterWait('I am a warning'); // One more reload to try with different arg combinations. $this->drupalGet('ajax-test/message'); $page->pressButton('Make Message In Default Location'); - $this->assertStatusMessageVisibleAfterWait(); + $this->assertSession()->statusMessageVisibleAfterWait(); $page->pressButton('Make Message In Alternate Location'); - $this->assertNoStatusMessageAfterWait(NULL, 'error'); + $this->assertSession()->statusMessageNotVisibleAfterWait(NULL, 'error'); $page->pressButton('Make Warning Message'); - $this->assertStatusMessageVisibleAfterWait(NULL, 'warning'); + $this->assertSession()->statusMessageVisibleAfterWait(NULL, 'warning'); // Test with bad message type. $this->expectException(\InvalidArgumentException::class); - $this->assertStatusMessageVisibleAfterWait('Any old message', 'something bad'); + $this->assertSession()->statusMessageVisibleAfterWait('Any old message', 'something bad'); } /** diff --git a/core/tests/Drupal/FunctionalJavascriptTests/JSWebAssert.php b/core/tests/Drupal/FunctionalJavascriptTests/JSWebAssert.php index e9e1d9cdec..988b958849 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/JSWebAssert.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/JSWebAssert.php @@ -523,4 +523,97 @@ public static function isExceptionNotClickable(Exception $exception): bool { return (bool) preg_match('/not (clickable|interactable|visible)/', $exception->getMessage()); } + /** + * Asserts that a status message is visible after wait. + * + * @param string|null $message + * The optional message or partial message to assert. + * @param string|null $type + * The optional message type: status, error, or warning. + */ + public function statusMessageVisibleAfterWait(?string $message = NULL, ?string $type = NULL): void { + $selector = $this->buildJavascriptStatusMessageSelector($message, $type); + $status_message_element = $this->waitForElementVisible('xpath', $selector); + if ($message) { + $failure_message = sprintf('A %s message containing the text "%s" does not appear on this page, but it should.', $type, $message); + } + else { + $failure_message = sprintf('A %s message does not appear on this page, but it should.', $type); + } + $this->assert(!is_null($status_message_element), $failure_message); + } + + /** + * Asserts that a status message is not present after wait. + * + * @param string|null $message + * The optional message or partial message to assert. + * @param string|null $type + * The optional message type: status, error, or warning. + */ + public function statusMessageNotVisibleAfterWait(?string $message = NULL, ?string $type = NULL): void { + $selector = $this->buildJavascriptStatusMessageSelector($message, $type); + $status_message_element = $this->waitForElementVisible('xpath', $selector); + if ($message) { + $failure_message = sprintf('A %s message containing the text "%s" appears on this page, but it should not.', $type, $message); + } + else { + $failure_message = sprintf('A %s message appears on this page, but it should not.', $type); + } + $this->assert(is_null($status_message_element), $failure_message); + } + + /** + * Builds a xpath selector for a message with given type and text. + * + * The selector is designed to work with the Drupal.theme.message + * template defined in message.js in addition to status-messages.html.twig + * in the system module. + * + * @param string|null $message + * The optional message or partial message to assert. + * @param string|null $type + * The optional message type: status, error, or warning. + * + * @return string + * The xpath selector for the message. + * + * @throws \InvalidArgumentException + * Thrown when $type is not an allowed type. + */ + public function buildJavascriptStatusMessageSelector(?string $message = NULL, ?string $type = NULL): string { + $allowed_types = [ + 'status', + 'error', + 'warning', + NULL, + ]; + if (!in_array($type, $allowed_types, TRUE)) { + throw new \InvalidArgumentException("The allowed status message types are 'status', 'error', 'warning'. Pass NULL to match any status message type."); + } + + if ($type) { + $class = 'messages--' . $type; + } + else { + $class = 'messages__wrapper'; + } + + if ($message) { + $js_selector = $this->buildXPathQuery('//div[contains(@class, :class) and contains(., :message)]', [ + ':class' => $class, + ':message' => $message, + ]); + } + else { + $js_selector = $this->buildXPathQuery('//div[contains(@class, :class)]', [ + ':class' => $class, + ]); + } + + // We select based on WebAssert::buildStatusMessageSelector() or the + // js_selector we have just built. + return $this->buildStatusMessageSelector($message, $type) . ' | ' . $js_selector; + } + } diff --git a/core/tests/Drupal/Tests/AssertJavascriptStatusMessageTrait.php b/core/tests/Drupal/Tests/AssertJavascriptStatusMessageTrait.php deleted file mode 100644 index f019e98bd7..0000000000 --- a/core/tests/Drupal/Tests/AssertJavascriptStatusMessageTrait.php +++ /dev/null @@ -1,95 +0,0 @@ -buildJavascriptStatusMessageSelector($message, $type); - $this->assertNotEmpty($this->assertSession()->waitForElementVisible('xpath', $selector)); - } - - /** - * Asserts that a status message is not present after wait. - * - * @param string|null $message - * The optional message or partial message to assert. - * @param string|null $type - * The optional message type: status, error, or warning. - */ - protected function assertNoStatusMessageAfterWait(?string $message = NULL, ?string $type = NULL): void { - $selector = $this->buildJavascriptStatusMessageSelector($message, $type); - $this->assertSession()->assertNoElementAfterWait('xpath', $selector); - } - - /** - * Builds a xpath selector for a message with given type and text. - * - * The selector is designed to work with the Drupal.theme.message - * template defined in message.js in addition to status-messages.html.twig - * in the system module. - * - * @param string|null $message - * The optional message or partial message to assert. - * @param string|null $type - * The optional message type: status, error, or warning. - * - * @return string - * The xpath selector for the message. - * - * @throws \InvalidArgumentException - * Thrown when $type is not an allowed type. - */ - protected function buildJavascriptStatusMessageSelector(?string $message = NULL, ?string $type = NULL): string { - $allowed_types = [ - 'status', - 'error', - 'warning', - NULL, - ]; - if (!in_array($type, $allowed_types, TRUE)) { - throw new \InvalidArgumentException("The allowed status message types are 'status', 'error', 'warning'. Pass NULL to match any status message type."); - } - - if ($type) { - $class = 'messages--' . $type; - } - else { - $class = 'messages__wrapper'; - } - - if ($message) { - $js_selector = $this->assertSession()->buildXPathQuery('//div[contains(@class, :class) and contains(., :message)]', [ - ':class' => $class, - ':message' => $message, - ]); - } - else { - $js_selector = $this->assertSession()->buildXPathQuery('//div[contains(@class, :class)]', [ - ':class' => $class, - ]); - } - - // We select based on the AssertStatusMessageTrait or the js_selector we - // have just built. - return $this->buildStatusMessageSelector($message, $type) . ' | ' . $js_selector; - } - -} diff --git a/core/tests/Drupal/Tests/AssertStatusMessageTrait.php b/core/tests/Drupal/Tests/AssertStatusMessageTrait.php deleted file mode 100644 index 3744fbb82b..0000000000 --- a/core/tests/Drupal/Tests/AssertStatusMessageTrait.php +++ /dev/null @@ -1,103 +0,0 @@ -buildStatusMessageSelector($message, $type); - $this->assertSession()->elementExists('xpath', $selector); - } - - /** - * Asserts that a status message does not exist. - * - * @param string|null $message - * The optional message or partial message to assert. - * @param string|null $type - * The optional message type: status, error, or warning. - */ - protected function assertStatusMessageNotExists(?string $message = NULL, ?string $type = NULL): void { - $selector = $this->buildStatusMessageSelector($message, $type); - $this->assertSession()->elementNotExists('xpath', $selector); - } - - /** - * Builds a xpath selector for a message with given type and text. - * - * The selector is designed to work with the status-messages.html.twig - * template in the system module. - * - * See Drupal\Core\Render\Element\StatusMessages for aria label definition. - * - * @param string|null $message - * The optional message or partial message to assert. - * @param string|null $type - * The optional message type: status, error, or warning. - * - * @return string - * The xpath selector for the message. - * - * @throws \InvalidArgumentException - * Thrown when $type is not an allowed type. - */ - protected function buildStatusMessageSelector(?string $message = NULL, ?string $type = NULL): string { - $allowed_types = [ - 'status', - 'error', - 'warning', - NULL, - ]; - if (!in_array($type, $allowed_types, TRUE)) { - throw new \InvalidArgumentException("The allowed status message types are 'status', 'error', 'warning'. Pass NULL to match any status message type."); - } - $selector = '//div[@data-drupal-messages]'; - $aria_label = NULL; - switch ($type) { - case 'status': - $aria_label = 'Status message'; - break; - - case 'error': - $aria_label = 'Error message'; - break; - - case 'warning': - $aria_label = 'Warning message'; - } - - if ($message && $aria_label) { - $selector = $this->assertSession()->buildXPathQuery($selector . '//div[contains(@aria-label, :aria_label) and contains(., :message)]', [ - ':aria_label' => $aria_label, - ':message' => $message, - ]); - } - elseif ($message) { - $selector = $this->assertSession()->buildXPathQuery($selector . '//div[contains(., :message)]', [ - ':message' => $message, - ]); - } - elseif ($aria_label) { - $selector = $this->assertSession()->buildXPathQuery($selector . '//div[@aria-label=:aria_label]', [ - ':aria_label' => $aria_label, - ]); - } - - return $selector; - } - -} diff --git a/core/tests/Drupal/Tests/WebAssert.php b/core/tests/Drupal/Tests/WebAssert.php index a5d80a6e3c..96429f653a 100644 --- a/core/tests/Drupal/Tests/WebAssert.php +++ b/core/tests/Drupal/Tests/WebAssert.php @@ -1125,4 +1125,94 @@ public function checkboxNotChecked($field, TraversableElement $container = NULL) return parent::checkboxNotChecked($field, $container); } + /** + * Asserts that a status message exists. + * + * @param string|null $message + * The optional message or partial message to assert. + * @param string|null $type + * The optional message type: status, error, or warning. + */ + public function statusMessageExists(?string $message = NULL, ?string $type = NULL): void { + $selector = $this->buildStatusMessageSelector($message, $type); + $this->elementExists('xpath', $selector); + } + + /** + * Asserts that a status message does not exist. + * + * @param string|null $message + * The optional message or partial message to assert. + * @param string|null $type + * The optional message type: status, error, or warning. + */ + public function statusMessageNotExists(?string $message = NULL, ?string $type = NULL): void { + $selector = $this->buildStatusMessageSelector($message, $type); + $this->elementNotExists('xpath', $selector); + } + + /** + * Builds a xpath selector for a message with given type and text. + * + * The selector is designed to work with the status-messages.html.twig + * template in the system module. + * + * See Drupal\Core\Render\Element\StatusMessages for aria label definition. + * + * @param string|null $message + * The optional message or partial message to assert. + * @param string|null $type + * The optional message type: status, error, or warning. + * + * @return string + * The xpath selector for the message. + * + * @throws \InvalidArgumentException + * Thrown when $type is not an allowed type. + */ + public function buildStatusMessageSelector(?string $message = NULL, ?string $type = NULL): string { + $allowed_types = [ + 'status', + 'error', + 'warning', + NULL, + ]; + if (!in_array($type, $allowed_types, TRUE)) { + throw new \InvalidArgumentException("The allowed status message types are 'status', 'error', 'warning'. Pass NULL to match any status message type."); + } + $selector = '//div[@data-drupal-messages]'; + $aria_label = NULL; + switch ($type) { + case 'status': + $aria_label = 'Status message'; + break; + + case 'error': + $aria_label = 'Error message'; + break; + + case 'warning': + $aria_label = 'Warning message'; + } + + if ($message && $aria_label) { + $selector = $this->buildXPathQuery($selector . '//div[contains(@aria-label, :aria_label) and contains(., :message)]', [ + ':aria_label' => $aria_label, + ':message' => $message, + ]); + } + elseif ($message) { + $selector = $this->buildXPathQuery($selector . '//div[contains(., :message)]', [ + ':message' => $message, + ]); + } + elseif ($aria_label) { + $selector = $this->buildXPathQuery($selector . '//div[@aria-label=:aria_label]', [ + ':aria_label' => $aria_label, + ]); + } + + return $selector; + } + }