diff --git a/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee b/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee
index ba1116649d..3d9fbfe62a 100644
--- a/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee
+++ b/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee
@@ -136,10 +136,10 @@ class window.Alchemy.Dialog
else
error_header = "#{xhr.statusText} (#{xhr.status})"
error_body = "Please check log and try again."
- $errorDiv = $("
")
- $errorDiv.append Alchemy.messageIcon(error_type)
- $errorDiv.append "#{error_header}
"
- $errorDiv.append "#{error_body}
"
+ $errorDiv = $("
+ #{error_header}
+ #{error_body}
+ ")
$container.html $errorDiv
# Binds close events on:
@@ -265,14 +265,3 @@ window.Alchemy.watchForDialogs = (scope = '#alchemy') ->
return
event.preventDefault()
return
-
-# Returns a Remix icon for given message type
-#
-window.Alchemy.messageIcon = (messageType) ->
- icon_name = switch messageType
- when "warning", "warn", "alert" then "alert"
- when "notice" then "check"
- when "info" then "information"
- when "error" then "bug"
- else messageType
- ""
diff --git a/app/assets/stylesheets/alchemy/flash.scss b/app/assets/stylesheets/alchemy/flash.scss
index 0a5ca3589d..a38b2cc5c4 100644
--- a/app/assets/stylesheets/alchemy/flash.scss
+++ b/app/assets/stylesheets/alchemy/flash.scss
@@ -5,74 +5,28 @@ div#flash_notices {
width: 400px;
top: 0;
- .flash.error {
- cursor: pointer;
- padding-right: 32px;
-
- alchemy-icon[name="close"] {
- position: absolute;
- left: initial;
- right: 2 * $default-padding;
+ alchemy-message {
+ font-weight: bold;
+ margin: $default-margin $default-margin 2 * $default-margin;
+ opacity: 0.95;
+ transition-property: opacity, transform;
+ transition-duration: 0.4s;
+
+ &.dismissed {
+ display: block;
+ opacity: 0;
+ transform: translate3d(0, -100%, 0);
}
- }
-}
-
-div.flash {
- border-radius: $default-border-radius;
- opacity: 0.95;
- padding: 8px 16px 8px 32px;
- font-weight: bold;
- border-width: 1px;
- border-style: solid;
- z-index: 1000;
- margin: $default-margin $default-margin 2 * $default-margin;
- position: relative;
- min-height: 2.6em;
- word-break: break-word;
- transition-property: opacity, transform;
- transition-duration: 0.4s;
- line-height: 1.5;
- alchemy-icon {
- position: absolute;
- top: 9px;
- left: 2 * $default-padding;
- vertical-align: bottom;
+ &[type="error"] {
+ cursor: pointer;
+ padding-right: 32px;
- .icon {
- fill: currentColor;
+ alchemy-icon[name="close"] {
+ position: absolute;
+ left: initial;
+ right: 2 * $default-padding;
+ }
}
}
-
- &.dismissed {
- display: block;
- opacity: 0;
- transform: translate3d(0, -100%, 0);
- }
-
- &.notice {
- border-color: $success_border_color;
- color: $success_text_color;
- background-color: $success_background_color;
- }
-
- &.error {
- border-color: $error_border_color;
- color: $error_text_color;
- background-color: $error_background_color;
- }
-
- &.info {
- border-color: $info_border_color;
- color: $info_text_color;
- background-color: $info_background_color;
- }
-
- &.warn,
- &.warning,
- &.alert {
- border-color: $warning_border_color;
- color: $warning_text_color;
- background-color: $warning_background_color;
- }
}
diff --git a/app/assets/stylesheets/alchemy/notices.scss b/app/assets/stylesheets/alchemy/notices.scss
index 2a9a512b5c..51e472d1b0 100644
--- a/app/assets/stylesheets/alchemy/notices.scss
+++ b/app/assets/stylesheets/alchemy/notices.scss
@@ -1,18 +1,51 @@
-// Some table columns also have .message class
-div.message {
- padding: 8px 8px 8px 32px;
- line-height: 17px;
+alchemy-message {
+ display: block;
border-width: $default-border-width;
border-style: $default-border-style;
border-radius: $default-border-radius;
position: relative;
+ padding: 8px 16px 8px 32px;
margin-bottom: 8px;
text-align: left;
+ min-height: 2.6em;
+ word-break: break-word;
+ line-height: 1.5;
- h1,
- h2,
- h3 {
- margin-top: 0;
+ &[type="footnote"] {
+ font-size: $small-font-size;
+ margin: 16px;
+ }
+
+ &[type="notice"] {
+ border-color: $success_border_color;
+ color: $success_text_color;
+ background-color: $success_background_color;
+ }
+
+ &[type="hint"] {
+ background-color: $hint-background-color;
+ border-color: $hint-background-color;
+ color: $hint-text-color;
+ }
+
+ &[type="info"] {
+ background-color: $info_background_color;
+ border-color: $info_border_color;
+ color: $info_text_color;
+ }
+
+ &[type="error"] {
+ background-color: $error_background_color;
+ border-color: $error_border_color;
+ color: $error_text_color;
+ }
+
+ &[type="warning"],
+ &[type="warn"],
+ &[type="alert"] {
+ background-color: $warning_background_color;
+ border-color: $warning_border_color;
+ color: $warning_text_color;
}
alchemy-icon {
@@ -26,9 +59,15 @@ div.message {
}
}
- &.footnote {
- font-size: $small-font-size;
- margin: 16px;
+ h1 {
+ font-size: 1.3rem;
+ line-height: 1.1;
+ }
+
+ h1,
+ h2,
+ h3 {
+ margin-top: 0;
}
a {
@@ -49,30 +88,4 @@ div.message {
margin-bottom: 4px;
}
}
-
- &.hint {
- background-color: $hint-background-color;
- border-color: $hint-background-color;
- color: $hint-text-color;
- }
-
- &.info {
- background-color: $info_background_color;
- border-color: $info_border_color;
- color: $info_text_color;
- }
-
- &.error {
- background-color: $error_background_color;
- border-color: $error_border_color;
- color: $error_text_color;
- }
-
- &.warning,
- &.warn,
- &.alert {
- background-color: $warning_background_color;
- border-color: $warning_border_color;
- color: $warning_text_color;
- }
}
diff --git a/app/components/alchemy/admin/message.rb b/app/components/alchemy/admin/message.rb
new file mode 100644
index 0000000000..7c9dd3bcf0
--- /dev/null
+++ b/app/components/alchemy/admin/message.rb
@@ -0,0 +1,19 @@
+module Alchemy
+ module Admin
+ class Message < ViewComponent::Base
+ attr_reader :message, :type, :dismissable
+
+ erb_template <<~ERB
+ >
+ <%= message || content %>
+
+ ERB
+
+ def initialize(message = nil, type: :info, dismissable: false)
+ @message = message
+ @dismissable = dismissable
+ @type = type
+ end
+ end
+ end
+end
diff --git a/app/helpers/alchemy/base_helper.rb b/app/helpers/alchemy/base_helper.rb
index 07a9fcf624..44124aec63 100644
--- a/app/helpers/alchemy/base_helper.rb
+++ b/app/helpers/alchemy/base_helper.rb
@@ -41,21 +41,16 @@ def render_icon(icon_name, options = {})
# <% end %>
#
def render_message(type = :info, msg = nil, &blk)
- icon_class = message_icon_class(type)
- if blk
- content_tag :div, render_icon(icon_class) + capture(&blk), class: "#{type} message"
- else
- content_tag :div, render_icon(icon_class) + msg, class: "#{type} message"
- end
+ render Alchemy::Admin::Message.new(msg || capture(&blk), type: type)
end
- # Renders the flash partial (+alchemy/admin/partials/flash+)
+ # Renders a dismissable growl message.
#
- # @param [String] notice The notice you want to display
- # @param [Symbol] style The style of this flash. Valid values are +:notice+ (default), +:warn+ and +:error+
+ # @param [String] notice - The notice you want to display
+ # @param [Symbol] type - The type of this flash. Valid values are +:notice+ (default), +:warn+, +:info+ and +:error+
#
- def render_flash_notice(notice, style = :notice)
- render("alchemy/admin/partials/flash", flash_type: style, message: notice)
+ def render_flash_notice(notice, type = :notice)
+ render Alchemy::Admin::Message.new(notice, type: type, dismissable: true)
end
# Checks if the given argument is a String or a Page object.
@@ -77,20 +72,5 @@ def page_or_find(page)
page
end
end
-
- # Returns the icon name for given message type
- #
- # @param message_type [String] The message type. One of +warning+, +info+, +notice+, +error+
- # @return [String] The icon name
- def message_icon_class(message_type)
- case message_type.to_s
- when "warning", "warn", "alert" then "exclamation"
- when "notice" then "check"
- when "error" then "bug"
- when "hint" then "info"
- else
- message_type
- end
- end
end
end
diff --git a/app/javascript/alchemy_admin.js b/app/javascript/alchemy_admin.js
index f3cee5d0ee..0e94f13757 100644
--- a/app/javascript/alchemy_admin.js
+++ b/app/javascript/alchemy_admin.js
@@ -26,6 +26,7 @@ import "alchemy_admin/components/clipboard_button"
import "alchemy_admin/components/datepicker"
import "alchemy_admin/components/dialog_link"
import "alchemy_admin/components/element_editor"
+import "alchemy_admin/components/message"
import "alchemy_admin/components/growl"
import "alchemy_admin/components/icon"
import "alchemy_admin/components/ingredient_group"
diff --git a/app/javascript/alchemy_admin/components/message.js b/app/javascript/alchemy_admin/components/message.js
new file mode 100644
index 0000000000..6380cdd45d
--- /dev/null
+++ b/app/javascript/alchemy_admin/components/message.js
@@ -0,0 +1,69 @@
+const DISMISS_DELAY = 5000
+
+class Message extends HTMLElement {
+ #message
+
+ constructor() {
+ super()
+ this.#message = this.innerHTML
+ if (this.dismissable || this.type === "error") {
+ this.addEventListener("click", this)
+ }
+ }
+
+ handleEvent(event) {
+ if (event.type === "click") {
+ this.dismiss()
+ }
+ }
+
+ connectedCallback() {
+ this.innerHTML = `
+
+ ${this.dismissable && this.type === "error" ? '' : ""}
+ ${this.#message}
+ `
+ if (this.dismissable && this.type !== "error") {
+ setTimeout(() => {
+ this.dismiss()
+ }, this.delay)
+ }
+ }
+
+ dismiss() {
+ this.addEventListener("transitionend", () => this.remove())
+ this.classList.add("dismissed")
+ }
+
+ get dismissable() {
+ return this.hasAttribute("dismissable")
+ }
+
+ get type() {
+ return this.getAttribute("type") || "notice"
+ }
+
+ get delay() {
+ return parseInt(this.getAttribute("delay") || DISMISS_DELAY)
+ }
+
+ get iconName() {
+ switch (this.type) {
+ case "warning":
+ case "warn":
+ case "alert":
+ return "alert"
+ case "notice":
+ return "check"
+ case "info":
+ case "hint":
+ return "information"
+ case "error":
+ return "bug"
+ default:
+ return this.type
+ }
+ }
+}
+
+customElements.define("alchemy-message", Message)
diff --git a/app/javascript/alchemy_admin/growler.js b/app/javascript/alchemy_admin/growler.js
index dc8c5d9e92..2b25dbdeb3 100644
--- a/app/javascript/alchemy_admin/growler.js
+++ b/app/javascript/alchemy_admin/growler.js
@@ -1,36 +1,13 @@
import { createHtmlElement } from "alchemy_admin/utils/dom_helpers"
function build(message, flashType) {
- const notices = document.getElementById("flash_notices")
- const flashContainer = createHtmlElement(
- ``
- )
- const icon = createHtmlElement(Alchemy.messageIcon(flashType))
- flashContainer.append(icon)
- if (flashType === "error") {
- const closeButton = createHtmlElement(
- ''
- )
- flashContainer.append(closeButton)
- }
- flashContainer.append(message)
- notices.append(flashContainer)
- flashContainer.addEventListener("click", () => dismiss(flashContainer))
-
- fade()
-}
-
-function dismiss(element) {
- element.addEventListener("transitionend", () => element.remove())
- element.classList.add("dismissed")
-}
-
-export function fade() {
- const notices = document.getElementById("flash_notices")
- const flashNotices = notices.querySelectorAll(".flash:not(.error)")
- setTimeout(() => {
- flashNotices.forEach((notice) => dismiss(notice))
- }, 5000)
+ const flashNotices = document.getElementById("flash_notices")
+ const flashMessage = createHtmlElement(`
+
+ ${message}
+
+ `)
+ flashNotices.append(flashMessage)
}
export function growl(message, style = "notice") {
diff --git a/app/javascript/alchemy_admin/initializer.js b/app/javascript/alchemy_admin/initializer.js
index 69e1d3fbbb..fb0fbd4017 100644
--- a/app/javascript/alchemy_admin/initializer.js
+++ b/app/javascript/alchemy_admin/initializer.js
@@ -1,5 +1,3 @@
-import { fade as fadeGrowl } from "alchemy_admin/growler"
-
/**
* add change listener to select to redirect the user after selecting another locale or site
* @param {string} selectId
@@ -27,11 +25,6 @@ function Initialize() {
// Initialize the GUI.
Alchemy.GUI.init()
- // Fade all growl notifications.
- if ($("#flash_notices").length > 0) {
- fadeGrowl()
- }
-
// Add observer for please wait overlay.
$(".please_wait")
.not("*[data-alchemy-confirm]")
diff --git a/app/views/alchemy/admin/partials/_flash.html.erb b/app/views/alchemy/admin/partials/_flash.html.erb
deleted file mode 100644
index 7a94803849..0000000000
--- a/app/views/alchemy/admin/partials/_flash.html.erb
+++ /dev/null
@@ -1,4 +0,0 @@
-
- <%= render_icon message_icon_class(flash_type) %>
- <%= message %>
-
diff --git a/app/views/alchemy/admin/partials/_flash_notices.html.erb b/app/views/alchemy/admin/partials/_flash_notices.html.erb
index 2aa7496122..3ff6440cf4 100644
--- a/app/views/alchemy/admin/partials/_flash_notices.html.erb
+++ b/app/views/alchemy/admin/partials/_flash_notices.html.erb
@@ -1,5 +1,7 @@
<% flash.keys.each do |flash_type| %>
- <%= render_flash_notice(flash[flash_type.to_sym], flash_type) if flash[flash_type.to_sym].present? %>
+ <% if flash[flash_type.to_sym].present? %>
+ <%= render_flash_notice(flash[flash_type.to_sym], flash_type) %>
+ <% end %>
<% end %>
diff --git a/app/views/alchemy/admin/styleguide/index.html.erb b/app/views/alchemy/admin/styleguide/index.html.erb
index 4ccbf7bc16..0c9fd4b87f 100644
--- a/app/views/alchemy/admin/styleguide/index.html.erb
+++ b/app/views/alchemy/admin/styleguide/index.html.erb
@@ -38,13 +38,13 @@
Info Message
<%= render_message do %>
- Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<% end %>
Warning Message
<%= render_message :warning do %>
- Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<% end %>
Error Message
@@ -53,27 +53,32 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<% end %>
+Growl Messages
+
+<%= link_to render_icon(:check), 'javascript:Alchemy.growl("Success message")', class: "icon_button" %>
+<%= link_to render_icon(:info), 'javascript:Alchemy.growl("Info message", "info")', class: "icon_button" %>
+<%= link_to render_icon(:alert), 'javascript:Alchemy.growl("Warning message", "warn")', class: "icon_button" %>
+<%= link_to render_icon(:bug), 'javascript:Alchemy.growl("Error message", "error")', class: "icon_button" %>
+
Dialog Links
-
+
+
+ <%= render_icon "window" %>
+
Forms
diff --git a/app/views/alchemy/base/error_notice.html.erb b/app/views/alchemy/base/error_notice.html.erb
index 649c79e1db..52b0cf7df7 100644
--- a/app/views/alchemy/base/error_notice.html.erb
+++ b/app/views/alchemy/base/error_notice.html.erb
@@ -1 +1,3 @@
-<%= render_flash_notice @notice, :error %>
+<%= render_message :error do %>
+ <%= @notice %>
+<% end %>
diff --git a/spec/components/alchemy/admin/message_spec.rb b/spec/components/alchemy/admin/message_spec.rb
new file mode 100644
index 0000000000..55a67bab09
--- /dev/null
+++ b/spec/components/alchemy/admin/message_spec.rb
@@ -0,0 +1,55 @@
+require "rails_helper"
+
+RSpec.describe Alchemy::Admin::Message, type: :component do
+ before do
+ render
+ end
+
+ subject(:render) do
+ render_inline described_class.new(message)
+ end
+
+ let(:message) { "This is a message" }
+
+ it "renders an alchemy-message with default type" do
+ expect(page).to have_css('alchemy-message[type="info"]', text: "This is a message")
+ end
+
+ it "renders a not-dismissable alchemy-message by default" do
+ expect(page).to_not have_css "alchemy-message[dismissable]"
+ end
+
+ context "with message given as block" do
+ subject(:render) do
+ render_inline described_class.new do
+ "This is a block message
".html_safe
+ end
+ end
+
+ it "renders an alchemy-message with default type" do
+ expect(page).to have_css('alchemy-message[type="info"] > p', text: "This is a block message")
+ end
+ end
+
+ context "with type given" do
+ subject(:render) do
+ render_inline described_class.new(message, type: type)
+ end
+
+ let(:type) { "alert" }
+
+ it "renders an alchemy-message with given type" do
+ expect(page).to have_css 'alchemy-message[type="alert"]'
+ end
+ end
+
+ context "with dismissable set to true" do
+ subject(:render) do
+ render_inline described_class.new(message, dismissable: true)
+ end
+
+ it "renders an dismissable alchemy-message" do
+ expect(page).to have_css "alchemy-message[dismissable]"
+ end
+ end
+end
diff --git a/spec/features/admin/nodes_management_spec.rb b/spec/features/admin/nodes_management_spec.rb
index 14ccb86a19..83c6d932a7 100644
--- a/spec/features/admin/nodes_management_spec.rb
+++ b/spec/features/admin/nodes_management_spec.rb
@@ -41,7 +41,7 @@ def add_menu_item
open_page_properties
click_button "Add a menu node"
- within ".flash.error" do
+ within "alchemy-message[type='error']" do
expect(page).to have_content("Menu Type can't be blank")
end
end
diff --git a/spec/helpers/alchemy/base_helper_spec.rb b/spec/helpers/alchemy/base_helper_spec.rb
index db9db94884..c08e751aa7 100644
--- a/spec/helpers/alchemy/base_helper_spec.rb
+++ b/spec/helpers/alchemy/base_helper_spec.rb
@@ -24,18 +24,44 @@ module Alchemy
describe "#render_message" do
context "if no argument is passed" do
- it "should render a div with an info icon and the given content" do
- expect(helper.render_message { content_tag(:p, "my notice") }).to match(
- /<\/alchemy-icon>my notice/
- )
+ it "should render an alchemy-message with an info icon and the given content" do
+ expect(helper.render_message { content_tag(:p, "my notice") }).to eq <<~HTML
+
+ my notice
+
+ HTML
end
end
context "if an argument is passed" do
- it "should render the passed argument as the css classname for the icon container" do
- expect(helper.render_message(:error) { content_tag(:p, "my notice") }).to match(
- /
/
- )
+ it "should render the passed argument as the type for the message" do
+ expect(helper.render_message(:error) { content_tag(:p, "my notice") }).to eq <<~HTML
+
+ my notice
+
+ HTML
+ end
+ end
+ end
+
+ describe "#render_flash_notice" do
+ context "if no argument is passed" do
+ it "should render an alchemy-message with an check icon and the given content" do
+ expect(helper.render_flash_notice("my notice")).to eq <<~HTML
+
+ my notice
+
+ HTML
+ end
+ end
+
+ context "if an argument is passed" do
+ it "should render the passed argument as the type for the message" do
+ expect(helper.render_flash_notice("A error", :error)).to eq <<~HTML
+
+ A error
+
+ HTML
end
end
end
@@ -63,43 +89,5 @@ module Alchemy
end
end
end
-
- describe "#message_icon_class" do
- subject { helper.message_icon_class(message_type) }
-
- context "when `warning`, `warn` or `alert` message type is given" do
- %w[warning warn alert].each do |type|
- let(:message_type) { type }
-
- it { is_expected.to eq "exclamation" }
- end
- end
-
- context "when `notice` message type is given" do
- let(:message_type) { "notice" }
-
- it { is_expected.to eq "check" }
- end
-
- context "when `hint` message type is given" do
- let(:message_type) { "hint" }
-
- it { is_expected.to eq "info" }
- end
-
- context "when `error` message type is given" do
- let(:message_type) { "error" }
-
- it { is_expected.to eq "bug" }
- end
-
- context "when unknown message type is given" do
- let(:message_type) { "info" }
-
- it "returns the given message type as icon name" do
- is_expected.to eq "info"
- end
- end
- end
end
end
diff --git a/spec/javascript/alchemy_admin/components/message.spec.js b/spec/javascript/alchemy_admin/components/message.spec.js
new file mode 100644
index 0000000000..43caea0770
--- /dev/null
+++ b/spec/javascript/alchemy_admin/components/message.spec.js
@@ -0,0 +1,216 @@
+import "alchemy_admin/components/message"
+import { renderComponent } from "./component.helper"
+
+describe("alchemy-message", () => {
+ describe("dismiss", () => {
+ describe("when dismissable", () => {
+ it("dismisses on click", () => {
+ const html = `
+
+ A message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ const spy = jest.spyOn(component, "dismiss")
+ component.dispatchEvent(new Event("click"))
+ expect(spy).toHaveBeenCalled()
+ })
+
+ it("dismisses after delay", () => {
+ return new Promise((resolve) => {
+ const html = `
+
+ A message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ const spy = jest.spyOn(component, "dismiss")
+ setTimeout(() => {
+ expect(spy).toHaveBeenCalled()
+ resolve()
+ }, 15)
+ })
+ }, 100)
+
+ it("when type error, does not dismis after delay", () => {
+ return new Promise((resolve) => {
+ const html = `
+
+ A message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ const spy = jest.spyOn(component, "dismiss")
+ setTimeout(() => {
+ expect(spy).not.toHaveBeenCalled()
+ resolve()
+ }, 15)
+ })
+ }, 100)
+ })
+
+ describe("when type error", () => {
+ it("dismisses on click", () => {
+ const html = `
+
+ A message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ const spy = jest.spyOn(component, "dismiss")
+ component.dispatchEvent(new Event("click"))
+ expect(spy).toHaveBeenCalled()
+ })
+ })
+
+ describe("when not type error nor dismissable", () => {
+ it("dismisses on click", () => {
+ const html = `
+
+ A message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ const spy = jest.spyOn(component, "dismiss")
+ component.dispatchEvent(new Event("click"))
+ expect(spy).not.toHaveBeenCalled()
+ })
+ })
+ })
+
+ describe("type", () => {
+ describe("when message type is given", () => {
+ it("is given type", () => {
+ const html = `
+
+ A warning message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ expect(component.type).toEqual("warning")
+ })
+ })
+
+ describe("when message type is not given", () => {
+ it("is given type", () => {
+ const html = `
+
+ A warning message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ expect(component.type).toEqual("notice")
+ })
+ })
+ })
+
+ describe("dismissable", () => {
+ describe("when dismissable is set", () => {
+ it("is dismissable", () => {
+ const html = `
+
+ A dismissable message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ expect(component.dismissable).toBe(true)
+ })
+
+ it("and type error, it shows close icon", () => {
+ const html = `
+
+ A dismissable message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ expect(
+ component.querySelector("alchemy-icon[name='close']")
+ ).toBeDefined()
+ })
+ })
+
+ describe("when dismissable is not set", () => {
+ it("is not dismissable", () => {
+ const html = `
+
+ A not dismissable message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ expect(component.dismissable).toBe(false)
+ })
+ })
+ })
+
+ describe("iconName", () => {
+ describe("when 'warning', 'warn' or 'alert' message type is given", () => {
+ ;["warning", "warn", "alert"].forEach((type) => {
+ it("is alert", () => {
+ const html = `
+
+ A ${type} message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ expect(component.iconName).toEqual("alert")
+ })
+ })
+ })
+
+ describe("when 'notice' message type is given", () => {
+ const html = `
+
+ A notice message
+
+ `
+
+ it("is check", () => {
+ const component = renderComponent("alchemy-message", html)
+
+ expect(component.iconName).toEqual("check")
+ })
+ })
+
+ describe("when 'info' or 'hint' message type is given", () => {
+ ;["hint", "info"].forEach((type) => {
+ it("is alert", () => {
+ const html = `
+
+ A ${type} message
+
+ `
+ const component = renderComponent("alchemy-message", html)
+ expect(component.iconName).toEqual("information")
+ })
+ })
+ })
+
+ describe("when 'error' message type is given", () => {
+ const html = `
+
+ A error message
+
+ `
+
+ it("is check", () => {
+ const component = renderComponent("alchemy-message", html)
+
+ expect(component.iconName).toEqual("bug")
+ })
+ })
+
+ describe("when unknown message type is given", () => {
+ const html = `
+
+ A foo message
+
+ `
+
+ it("is the given message type as icon name", () => {
+ const component = renderComponent("alchemy-message", html)
+
+ expect(component.iconName).toEqual("foo")
+ })
+ })
+ })
+})
diff --git a/spec/views/alchemy/admin/elements/element_view_spec.rb b/spec/views/alchemy/admin/elements/element_view_spec.rb
index f08b637e8c..67112b97e5 100644
--- a/spec/views/alchemy/admin/elements/element_view_spec.rb
+++ b/spec/views/alchemy/admin/elements/element_view_spec.rb
@@ -23,7 +23,7 @@
let(:element) { create(:alchemy_element, name: "with_message") }
it "renders the message" do
- is_expected.to have_css('.message:contains("One nice message")')
+ is_expected.to have_css('alchemy-message:contains("One nice message")')
end
context "that contains HTML" do
@@ -35,7 +35,7 @@
end
it "renders the HTML message" do
- is_expected.to have_css('.message h1:contains("One nice message")')
+ is_expected.to have_css('alchemy-message[type="info"] h1:contains("One nice message")')
end
end
end
@@ -51,7 +51,7 @@
end
it "renders the warning" do
- is_expected.to have_css('.warning:contains("One nice warning")')
+ is_expected.to have_css('alchemy-message[type="warning"]:contains("One nice warning")')
end
context "that contains HTML" do
@@ -63,7 +63,7 @@
end
it "renders the HTML warning" do
- is_expected.to have_css('.warning h1:contains("One nice warning")')
+ is_expected.to have_css('alchemy-message[type="warning"] h1:contains("One nice warning")')
end
end
end
diff --git a/spec/views/alchemy/ingredients/select_editor_spec.rb b/spec/views/alchemy/ingredients/select_editor_spec.rb
index cbd17173ed..548dcc3f89 100644
--- a/spec/views/alchemy/ingredients/select_editor_spec.rb
+++ b/spec/views/alchemy/ingredients/select_editor_spec.rb
@@ -30,7 +30,7 @@
end
it "renders a warning" do
- is_expected.to have_css(".warning")
+ is_expected.to have_css('alchemy-message[type="warning"]')
end
end