From 5698e6fb8bec6ea758c26a269b83e27df7ba89ff Mon Sep 17 00:00:00 2001
From: Lauri Eskola <lauri.eskola@acquia.com>
Date: Tue, 17 Aug 2021 14:46:50 +0300
Subject: [PATCH] Issue #3212975 by marcoscano, mherchel, thejimbirch,
 Gauravmahlawat, geekygnr, andy-blum, lauriii, larowlan: Olivero: Normalize
 JavaScript selectors in messages.es6.js

---
 .../Core/JsMessageTest.php                    |  8 ++-
 .../Theme/OliveroMessagesTest.php             | 62 +++++++++++++++++++
 core/themes/olivero/js/messages.es6.js        | 11 +++-
 core/themes/olivero/js/messages.js            |  7 ++-
 .../templates/misc/status-messages.html.twig  |  9 ++-
 5 files changed, 88 insertions(+), 9 deletions(-)
 create mode 100644 core/tests/Drupal/FunctionalJavascriptTests/Theme/OliveroMessagesTest.php

diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Core/JsMessageTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Core/JsMessageTest.php
index 32e6c4531c03..e52149b74f9a 100644
--- a/core/tests/Drupal/FunctionalJavascriptTests/Core/JsMessageTest.php
+++ b/core/tests/Drupal/FunctionalJavascriptTests/Core/JsMessageTest.php
@@ -118,7 +118,13 @@ protected function assertCurrentMessages(array $expected_messages, $messagesSele
         $current_messages[] = $message_div->getText();
       }
     }
-    $this->assertEquals($expected_messages, $current_messages);
+    // Check that each message text contains the expected text.
+    if (count($expected_messages) !== count($current_messages)) {
+      $this->fail('The expected messages array contains a different number of values than the current messages array.');
+    }
+    for ($i = 0; $i < count($expected_messages); $i++) {
+      $this->assertStringContainsString($expected_messages[$i], $current_messages[$i]);
+    }
   }
 
 }
diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Theme/OliveroMessagesTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Theme/OliveroMessagesTest.php
new file mode 100644
index 000000000000..31dd15db58fc
--- /dev/null
+++ b/core/tests/Drupal/FunctionalJavascriptTests/Theme/OliveroMessagesTest.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace Drupal\FunctionalJavascriptTests\Theme;
+
+use Drupal\FunctionalJavascriptTests\Core\JsMessageTest;
+use Drupal\js_message_test\Controller\JSMessageTestController;
+
+/**
+ * Runs OliveroMessagesTest in Olivero.
+ *
+ * @group olivero
+ *
+ * @see \Drupal\FunctionalJavascriptTests\Core\JsMessageTest.
+ */
+class OliveroMessagesTest extends JsMessageTest {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'js_message_test',
+    'system',
+    'block',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+
+    // Enable the theme.
+    \Drupal::service('theme_installer')->install(['olivero']);
+    $theme_config = \Drupal::configFactory()->getEditable('system.theme');
+    $theme_config->set('default', 'olivero');
+    $theme_config->save();
+  }
+
+  /**
+   * Tests data-drupal-selector="messages" exists.
+   */
+  public function testDataDrupalSelectors() {
+    $web_assert = $this->assertSession();
+    $this->drupalGet('js_message_test_link');
+
+    foreach (JSMessageTestController::getMessagesSelectors() as $messagesSelector) {
+      $web_assert->elementExists('css', $messagesSelector);
+      foreach (JSMessageTestController::getTypes() as $type) {
+        $this->click('[id="add-' . $messagesSelector . '-' . $type . '"]');
+        $selector = '[data-drupal-selector="messages"]';
+        $msg_element = $web_assert->waitForElementVisible('css', $selector);
+        $this->assertNotEmpty($msg_element, "Message element visible: $selector");
+      }
+    }
+  }
+
+}
diff --git a/core/themes/olivero/js/messages.es6.js b/core/themes/olivero/js/messages.es6.js
index 5a3ae83ab5e3..b7c16997b9f3 100644
--- a/core/themes/olivero/js/messages.es6.js
+++ b/core/themes/olivero/js/messages.es6.js
@@ -11,7 +11,9 @@
    *   The message object.
    */
   const closeMessage = (message) => {
-    const messageContainer = message.querySelector('.messages__container');
+    const messageContainer = message.querySelector(
+      '[data-drupal-selector="messages-container"]',
+    );
 
     const closeBtnWrapper = document.createElement('div');
     closeBtnWrapper.setAttribute('class', 'messages__button');
@@ -58,6 +60,7 @@
       'class',
       `messages-list__item messages messages--${type}`,
     );
+    messageWrapper.setAttribute('data-drupal-selector', 'messages');
     messageWrapper.setAttribute(
       'role',
       type === 'error' || type === 'warning' ? 'alert' : 'status',
@@ -91,7 +94,7 @@
     }
 
     messageWrapper.innerHTML = `
-    <div class="messages__container">
+    <div class="messages__container" data-drupal-selector="messages-container">
       <div class="messages__header${!svg ? ' no-icon' : ''}">
         <h2 class="visually-hidden">${messagesTypes[type]}</h2>
         ${svg}
@@ -117,7 +120,9 @@
    */
   Drupal.behaviors.messages = {
     attach(context) {
-      once('olivero-messages', '.messages', context).forEach(closeMessage);
+      once('messages', '[data-drupal-selector="messages"]', context).forEach(
+        closeMessage,
+      );
     },
   };
 })(Drupal, once);
diff --git a/core/themes/olivero/js/messages.js b/core/themes/olivero/js/messages.js
index fc465e1ec2f2..0ec14ddec287 100644
--- a/core/themes/olivero/js/messages.js
+++ b/core/themes/olivero/js/messages.js
@@ -7,7 +7,7 @@
 
 (function (Drupal, once) {
   var closeMessage = function closeMessage(message) {
-    var messageContainer = message.querySelector('.messages__container');
+    var messageContainer = message.querySelector('[data-drupal-selector="messages-container"]');
     var closeBtnWrapper = document.createElement('div');
     closeBtnWrapper.setAttribute('class', 'messages__button');
     var closeBtn = document.createElement('button');
@@ -31,6 +31,7 @@
     var messagesTypes = Drupal.Message.getMessageTypeLabels();
     var messageWrapper = document.createElement('div');
     messageWrapper.setAttribute('class', "messages-list__item messages messages--".concat(type));
+    messageWrapper.setAttribute('data-drupal-selector', 'messages');
     messageWrapper.setAttribute('role', type === 'error' || type === 'warning' ? 'alert' : 'status');
     messageWrapper.setAttribute('aria-labelledby', "".concat(id, "-title"));
     messageWrapper.setAttribute('data-drupal-message-id', id);
@@ -55,14 +56,14 @@
       svg += '</svg></div>';
     }
 
-    messageWrapper.innerHTML = "\n    <div class=\"messages__container\">\n      <div class=\"messages__header".concat(!svg ? ' no-icon' : '', "\">\n        <h2 class=\"visually-hidden\">").concat(messagesTypes[type], "</h2>\n        ").concat(svg, "\n      </div>\n      <div class=\"messages__content\">\n        ").concat(text, "\n      </div>\n    </div>\n    ");
+    messageWrapper.innerHTML = "\n    <div class=\"messages__container\" data-drupal-selector=\"messages-container\">\n      <div class=\"messages__header".concat(!svg ? ' no-icon' : '', "\">\n        <h2 class=\"visually-hidden\">").concat(messagesTypes[type], "</h2>\n        ").concat(svg, "\n      </div>\n      <div class=\"messages__content\">\n        ").concat(text, "\n      </div>\n    </div>\n    ");
     closeMessage(messageWrapper);
     return messageWrapper;
   };
 
   Drupal.behaviors.messages = {
     attach: function attach(context) {
-      once('olivero-messages', '.messages', context).forEach(closeMessage);
+      once('messages', '[data-drupal-selector="messages"]', context).forEach(closeMessage);
     }
   };
 })(Drupal, once);
\ No newline at end of file
diff --git a/core/themes/olivero/templates/misc/status-messages.html.twig b/core/themes/olivero/templates/misc/status-messages.html.twig
index a131e3c8d1a7..c607a84d941c 100644
--- a/core/themes/olivero/templates/misc/status-messages.html.twig
+++ b/core/themes/olivero/templates/misc/status-messages.html.twig
@@ -31,8 +31,13 @@
     ]
     %}
 
-    <div role="contentinfo" aria-label="{{ status_headings[type] }}"{{ attributes.addClass(classes)|without('role', 'aria-label') }}>
-      <div class="messages__container"{% if type == 'error' %} role="alert"{% endif %}>
+    <div{{ attributes
+      .addClass(classes)
+      .setAttribute('data-drupal-selector', 'messages')
+      .setAttribute('role', 'contentinfo')
+      .setAttribute('aria-label', status_headings[type])
+      }}>
+      <div class="messages__container" data-drupal-selector="messages-container"{% if type == 'error' %} role="alert"{% endif %}>
         {% if status_headings[type] %}
           <div class="messages__header">
            <h2 class="visually-hidden">{{ status_headings[type] }}</h2>
-- 
GitLab