diff -u b/core/misc/message.js b/core/misc/message.js --- b/core/misc/message.js +++ b/core/misc/message.js @@ -70,27 +70,30 @@ * * @name Drupal.message~messageDefinition.remove * - * @param {string|number} [messageIndex] + * @param {Number|String|Array.} [messages] * Index of the message to remove, as returned by - * {@link Drupal.message~messageDefinition.add} or a number - * corresponding to the CSS index of the element. + * {@link Drupal.message~messageDefinition.add}, a number + * corresponding to the CSS index of the element, or an + * array containing a combination of the previous two types. * * @return {number} * Number of removed messages. */ - function messageRemove(messageIndex) { - var removeSelector = '[data-drupal-message]'; - - // If it's a string, select corresponding message. - if (typeof messageIndex === 'string') { - removeSelector = '[data-drupal-message="' + messageIndex + '"]'; - } - // If the index is numeric remove the element based on the DOM index. - else if (typeof messageIndex === 'number') { - removeSelector = '[data-drupal-message]:nth-child(' + messageIndex + ')'; + function messageRemove(messages) { + if (!messages) { + throw new Error(Drupal.t('Object.message() expect a message to remove.')); } - var remove = this.element.querySelectorAll(removeSelector); + var removeSelector = (messages instanceof Array ? messages : [messages]) + .map(function (messageIndex) { + return typeof messageIndex === 'string' ? + // If it's a string, select corresponding message. + '[data-drupal-message="' + messageIndex + '"]' : + // If the index is numeric remove the element based on the DOM index. + '[data-drupal-message]:nth-child(' + messageIndex + ')'; + }); + + var remove = this.element.querySelectorAll(removeSelector.join(', ')); var length = remove.length; for (var i = 0; i < length; i += 1) { this.element.removeChild(remove[i]); diff -u b/core/modules/system/src/Tests/JsMessageTestCases.php b/core/modules/system/src/Tests/JsMessageTestCases.php --- b/core/modules/system/src/Tests/JsMessageTestCases.php +++ b/core/modules/system/src/Tests/JsMessageTestCases.php @@ -8,16 +8,6 @@ class JsMessageTestCases { /** - * Gets the test contexts. - * - * @return string[] - * The test contexts. - */ - public static function getContexts() { - return ['context1', 'context2']; - } - - /** * Gets the test types. * * @return string[] diff -u b/core/modules/system/tests/modules/js_message_test/js/js_message_test.js b/core/modules/system/tests/modules/js_message_test/js/js_message_test.js --- b/core/modules/system/tests/modules/js_message_test/js/js_message_test.js +++ b/core/modules/system/tests/modules/js_message_test/js/js_message_test.js @@ -3,7 +3,7 @@ * Testing behavior for JSMessageTest. */ -(function ($, message) { +(function ($) { 'use strict'; @@ -18,31 +18,47 @@ - var message = Drupal.message(); - var messageIndex; - var messageList = []; + var messageObjects = {}; + var messageIndexes = {}; + $('.show-link').once('show-msg').on('click', function (e) { + e.preventDefault(); var type = e.currentTarget.getAttribute('data-type'); - messageIndex = message.add('Msg-' + type, type); + messageIndexes[type] = getMessageObject(e).add('Msg-' + type, type); }); $('.remove-link').once('remove-msg').on('click', function (e) { e.preventDefault(); var type = e.currentTarget.getAttribute('data-type'); - message.remove(messageIndex); + getMessageObject(e).remove(messageIndexes[type]); }); $('.show-multiple').once('show-msg').on('click', function (e) { e.preventDefault(); for (var i = 0; i < 10; i++) { - messageList.push(message.add('Msg-' + i, 'status')); + messageIndexes[i] = getMessageObject(e).add('Msg-' + i, 'status'); } }); $('.remove-multiple').once('remove-msg').on('click', function (e) { e.preventDefault(); for (var i = 0; i < 10; i++) { - message.remove(messageList[i]); + getMessageObject(e).remove(messageIndexes[i]); } - messageList = []; }); + + /** + * Gets message object for the click event. + * + * @param {jQuery.Event} e + * The click event. + * @return {Drupal.message~messageDefinition} + * The message object for correct div. + */ + function getMessageObject(e) { + var divSelector = e.currentTarget.getAttribute('data-selector'); + if (!messageObjects.hasOwnProperty(divSelector)) { + messageObjects[divSelector] = Drupal.message(document.querySelector(divSelector)); + } + return messageObjects[divSelector]; + } } }; -})(jQuery, Drupal.message); +})(jQuery); diff -u b/core/modules/system/tests/modules/js_message_test/src/Controller/JSMessageTestController.php b/core/modules/system/tests/modules/js_message_test/src/Controller/JSMessageTestController.php --- b/core/modules/system/tests/modules/js_message_test/src/Controller/JSMessageTestController.php +++ b/core/modules/system/tests/modules/js_message_test/src/Controller/JSMessageTestController.php @@ -19,37 +19,24 @@ public function messageLinks() { $links = []; foreach (JsMessageTestCases::getMessagesSelectors() as $messagesSelector) { - foreach (JsMessageTestCases::getContexts() as $context) { - foreach (JsMessageTestCases::getTypes() as $type) { - $links["show-$messagesSelector-$context-$type"] = [ - 'title' => "Show-$messagesSelector-$context-$type", - 'url' => Url::fromRoute('js_message_test.links'), - 'attributes' => [ - 'id' => "show-$messagesSelector-$context-$type", - 'data-context' => $context, - 'data-type' => $type, - 'data-selector' => $messagesSelector, - 'class' => ['show-link'], - ], - ]; - $links["remove-$messagesSelector-$context-$type"] = [ - 'title' => "Remove-$messagesSelector-$context-$type", - 'url' => Url::fromRoute('js_message_test.links'), - 'attributes' => [ - 'id' => "remove-$messagesSelector-$context-$type", - 'data-context' => $context, - 'data-type' => $type, - 'data-selector' => $messagesSelector, - 'class' => ['remove-link'], - ], - ]; - } - $links["remove-$context"] = [ - 'title' => "Remove-$context-all", + foreach (JsMessageTestCases::getTypes() as $type) { + $links["show-$messagesSelector-$type"] = [ + 'title' => "Show-$messagesSelector-$type", 'url' => Url::fromRoute('js_message_test.links'), 'attributes' => [ - 'id' => "remove-$context", - 'data-context' => $context, + 'id' => "show-$messagesSelector-$type", + 'data-type' => $type, + 'data-selector' => $messagesSelector, + 'class' => ['show-link'], + ], + ]; + $links["remove-$messagesSelector-$type"] = [ + 'title' => "Remove-$messagesSelector-$type", + 'url' => Url::fromRoute('js_message_test.links'), + 'attributes' => [ + 'id' => "remove-$messagesSelector-$type", + 'data-type' => $type, + 'data-selector' => $messagesSelector, 'class' => ['remove-link'], ], ]; diff -u b/core/tests/Drupal/FunctionalJavascriptTests/Core/JsMessageTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Core/JsMessageTest.php --- b/core/tests/Drupal/FunctionalJavascriptTests/Core/JsMessageTest.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/Core/JsMessageTest.php @@ -17,6 +17,9 @@ */ public static $modules = ['js_message_test']; + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); @@ -27,7 +30,6 @@ $theme_config->save(); } - /** * Test click on links to show messages and remove messages. */ @@ -35,49 +37,31 @@ $web_assert = $this->assertSession(); $this->drupalGet('js_message_test_link'); + $current_messages = []; foreach (JsMessageTestCases::getMessagesSelectors() as $messagesSelector) { $web_assert->elementExists('css', $messagesSelector); - foreach (JsMessageTestCases ::getContexts() as $context) { - foreach (JsMessageTestCases::getTypes() as $type) { - $this->clickLink("Show-$messagesSelector-$context-$type"); - $selector = "$messagesSelector .messages.messages--$type.js-messages.js-messages-context--$context"; - $msg_element = $web_assert->waitForElementVisible('css', $selector); - $this->assertNotEmpty($msg_element, "Message element visible: $selector"); - $web_assert->elementContains('css', $selector, "Msg-$context-$type"); - // Click all remove links except the one that will remove the message. - $this->clickAllRemoveLinksExcept($context, $type, $messagesSelector); - // Confirm the message was not removed. - $web_assert->elementContains('css', $selector, "Msg-$context-$type"); - // Click the remove links that should remove the message. - $this->clickLink("Remove-$messagesSelector-$context-$type"); - $web_assert->elementNotExists('css', $selector); - } + foreach (JsMessageTestCases::getTypes() as $type) { + $this->clickLink("Show-$messagesSelector-$type"); + $selector = "$messagesSelector .messages.messages--$type"; + $msg_element = $web_assert->waitForElementVisible('css', $selector); + $this->assertNotEmpty($msg_element, "Message element visible: $selector"); + $web_assert->elementContains('css', $selector, "Msg-$type"); + $current_messages[$selector] = "Msg-$type"; + $this->assertCurrentMessages($current_messages); + } + // Remove messages 1 by 1 and confirm the messages are expected. + foreach (JsMessageTestCases::getTypes() as $type) { + $this->clickLink("Remove-$messagesSelector-$type"); + $selector = "$messagesSelector .messages.messages--$type"; + // The message for this selector should not be on the page. + unset($current_messages[$selector]); + $this->assertCurrentMessages($current_messages); } - // Test removing all messages of a specific context. - $this->clickLink("Show-$messagesSelector-context1-error"); - $this->clickLink("Show-$messagesSelector-context2-error"); - $this->clickLink("Show-$messagesSelector-context1-warning"); - $this->clickLink("Show-$messagesSelector-context2-warning"); - $this->waitForMessageElement('warning', 'context2'); - $this->assertCurrentMessages([ - 'Msg-context1-error', - 'Msg-context2-error', - 'Msg-context1-warning', - 'Msg-context2-warning', - ]); - $this->clickLink('Remove-context1-all'); - $web_assert->assertWaitOnAjaxRequest(); - $this->assertCurrentMessages([ - 'Msg-context2-error', - 'Msg-context2-warning', - ]); - $this->clickLink('Remove-context2-all'); - $this->assertCurrentMessages([]); } + // Test adding multiple messages at once. // @see processMessages() $this->clickLink('Show Multiple'); - $this->waitForMessageElement('status', 'context-9'); $current_messages = []; for ($i = 0; $i < 10; $i++) { @@ -86,27 +70,6 @@ $this->assertCurrentMessages($current_messages); $this->clickLink('Remove Multiple'); $this->assertCurrentMessages([]); - - - - } - - /** - * Clicks all remove message links except for combination specified. - * - * @param string $exclude_context - * The message context to exclude. - * @param string $exclude_type - * The message type to exclude. - */ - protected function clickAllRemoveLinksExcept($exclude_context, $exclude_type, $messagesSelector) { - foreach (JsMessageTestCases::getContexts() as $context) { - foreach (JsMessageTestCases::getTypes() as $type) { - if ($context !== $exclude_context || $type !== $exclude_type) { - $this->clickLink("Remove-$messagesSelector-$context-$type"); - } - } - } } /** @@ -116,6 +79,7 @@ * Expected messages. */ protected function assertCurrentMessages(array $expected_messages) { + $expected_messages = array_values($expected_messages); $current_messages = []; if ($message_divs = $this->getSession()->getPage()->findAll('css', '.messages')) { foreach ($message_divs as $message_div) { @@ -128,15 +92,2 @@ - /** - * Waits for an element message to be visible. - * - * @param string $type - * The type of the message. - * @param string $context - * The context of the message. - */ - protected function waitForMessageElement($type, $context) { - $last_msg_element = $this->assertSession()->waitForElementVisible('css', ".messages.messages--$type.js-messages.js-messages-context--$context"); - $this->assertNotEmpty($last_msg_element, "Message element visible."); - } - }