mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Merge pull request #16789 from opf/chore/primerized-flashes
Primerize all backend flashes
This commit is contained in:
@@ -31,7 +31,11 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
render(Primer::BaseComponent.new(
|
||||
tag: :div,
|
||||
classes: "op-primer-flash--item",
|
||||
data: { unique_key: @unique_key }.compact
|
||||
data: {
|
||||
"flash-target": "item",
|
||||
"autohide": @autohide,
|
||||
unique_key: @unique_key
|
||||
}.compact
|
||||
)) do
|
||||
render_parent
|
||||
end
|
||||
|
||||
@@ -35,10 +35,12 @@ module OpPrimer
|
||||
def initialize(**system_arguments)
|
||||
@unique_key = system_arguments.delete(:unique_key)
|
||||
|
||||
system_arguments[:test_selector] ||= "primer-banner-message-component"
|
||||
system_arguments[:test_selector] ||= "op-primer-flash-message"
|
||||
system_arguments[:dismiss_scheme] ||= :remove
|
||||
system_arguments[:dismiss_label] ||= I18n.t(:button_close)
|
||||
|
||||
@autohide = system_arguments[:scheme] == :success && system_arguments[:dismiss_scheme] != :none
|
||||
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
@@ -174,13 +174,13 @@ class MyController < ApplicationController
|
||||
|
||||
# rubocop:disable Rails/ActionControllerFlashBeforeRender
|
||||
result.on_success do
|
||||
flash[:op_primer_flash] = { message: t("my.access_token.notice_api_token_revoked") }
|
||||
flash[:notice] = t("my.access_token.notice_api_token_revoked")
|
||||
end
|
||||
|
||||
result.on_failure do |r|
|
||||
error = r.errors.map(&:message).join("; ")
|
||||
Rails.logger.error("Failed to revoke api token ##{current_user.id}: #{error}")
|
||||
flash[:op_primer_flash] = { message: t("my.access_token.failed_to_revoke_token", error:), scheme: :danger }
|
||||
flash[:error] = t("my.access_token.failed_to_revoke_token", error:)
|
||||
end
|
||||
# rubocop:enable Rails/ActionControllerFlashBeforeRender
|
||||
|
||||
|
||||
@@ -34,32 +34,51 @@ module ErrorMessageHelper
|
||||
object = convert_to_model(object)
|
||||
return unless object
|
||||
|
||||
render_error_messages_partial(object.errors, object)
|
||||
assign_flash_error(object.errors, object)
|
||||
|
||||
# Don't output anything for compability
|
||||
nil
|
||||
end
|
||||
|
||||
def render_error_messages_partial(errors, object)
|
||||
return "" if errors.empty?
|
||||
def assign_flash_error(errors, object)
|
||||
return if errors.empty?
|
||||
|
||||
base_error_messages = errors.full_messages_for(:base)
|
||||
fields_error_messages = errors.full_messages - base_error_messages
|
||||
|
||||
render partial: "common/validation_error",
|
||||
locals: { base_error_messages:,
|
||||
fields_error_messages:,
|
||||
object_name: object.class.model_name.human }
|
||||
flash[:error] = {
|
||||
message: error_message_header(object.class.model_name.human, base_error_messages.count + fields_error_messages.count),
|
||||
description: error_flash_description(object, base_error_messages, fields_error_messages)
|
||||
}
|
||||
end
|
||||
|
||||
def error_flash_description(_object, base_error_messages, fields_error_messages)
|
||||
capture do
|
||||
concat list_of_messages(base_error_messages)
|
||||
concat text_header_invalid_fields(base_error_messages, fields_error_messages)
|
||||
concat list_of_messages(fields_error_messages)
|
||||
end
|
||||
end
|
||||
|
||||
def error_message_header(object_name, count)
|
||||
t("activerecord.errors.template.header", model: object_name, count:)
|
||||
end
|
||||
|
||||
def text_header_invalid_fields(base_error_messages, fields_error_messages)
|
||||
return if fields_error_messages.blank?
|
||||
|
||||
i18n_key = base_error_messages.present? ? "errors.header_additional_invalid_fields" : "errors.header_invalid_fields"
|
||||
t(i18n_key, count: fields_error_messages.count)
|
||||
out = "".html_safe
|
||||
|
||||
out << t(i18n_key, count: fields_error_messages.count)
|
||||
out << "<br/>".html_safe
|
||||
|
||||
out
|
||||
end
|
||||
|
||||
def list_of_messages(messages)
|
||||
return if messages.blank?
|
||||
|
||||
messages = messages.map { |message| tag.li message }
|
||||
tag.ul { safe_join(messages, "\n") }
|
||||
safe_join(messages, "<br/>".html_safe)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,34 +27,34 @@
|
||||
#++
|
||||
|
||||
module ErrorsHelper
|
||||
def render_400(options = {})
|
||||
@project = nil
|
||||
def render_400(options = {}) # rubocop:disable Naming/VariableNumber
|
||||
unset_template_magic
|
||||
render_error({ message: :notice_bad_request, status: 400 }.merge(options))
|
||||
false
|
||||
end
|
||||
|
||||
def render_403(options = {})
|
||||
@project = nil
|
||||
def render_403(options = {}) # rubocop:disable Naming/VariableNumber
|
||||
unset_template_magic
|
||||
render_error({ message: :notice_not_authorized, status: 403 }.merge(options))
|
||||
false
|
||||
end
|
||||
|
||||
def render_404(options = {})
|
||||
def render_404(options = {}) # rubocop:disable Naming/VariableNumber
|
||||
render_error({ message: :notice_file_not_found, status: 404 }.merge(options))
|
||||
false
|
||||
end
|
||||
|
||||
def render_500(options = {})
|
||||
message = t(:notice_internal_server_error, app_title: Setting.app_title)
|
||||
|
||||
def render_500(options = {}) # rubocop:disable Naming/VariableNumber
|
||||
unset_template_magic
|
||||
|
||||
message = t(:notice_internal_server_error, app_title: Setting.app_title)
|
||||
|
||||
# Append error information
|
||||
if current_user.admin?
|
||||
options[:message_details] = get_additional_message
|
||||
end
|
||||
|
||||
render_error({ message: }.merge(options))
|
||||
render_error({ message:, status: 500 }.merge(options))
|
||||
false
|
||||
end
|
||||
|
||||
@@ -80,37 +80,34 @@ module ErrorsHelper
|
||||
end
|
||||
|
||||
# Renders an error response
|
||||
def render_error(arg)
|
||||
def render_error(arg) # rubocop:disable Metrics/AbcSize
|
||||
arg = { message: arg } unless arg.is_a?(Hash)
|
||||
|
||||
@status = arg[:status] || 500
|
||||
@message = arg[:message]
|
||||
status = arg[:status] || 500
|
||||
message = arg[:message]
|
||||
|
||||
if @status >= 500
|
||||
op_handle_error(arg[:exception] || "[Error #@status] #@message", payload: arg[:payload])
|
||||
if status >= 500
|
||||
op_handle_error(arg[:exception] || "[Error #status] #message", payload: arg[:payload])
|
||||
end
|
||||
|
||||
@message = I18n.t(@message) if @message.is_a?(Symbol)
|
||||
@message_details = arg[:message_details]
|
||||
message = I18n.t(message) if message.is_a?(Symbol)
|
||||
message_details = arg[:message_details]
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
render template: "common/error", layout: use_layout, status: @status
|
||||
error_message = "[#{I18n.t(:error_code, code: status)}] #{message}\n#{message_details}"
|
||||
flash.now[:error] = { message: error_message, dismiss_scheme: :none }
|
||||
render template: "common/error",
|
||||
layout: use_layout,
|
||||
status:,
|
||||
locals: { status:, params: }
|
||||
end
|
||||
format.any do
|
||||
head @status
|
||||
head status
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def unset_template_magic
|
||||
if $ERROR_INFO.is_a?(ActionView::ActionViewError)
|
||||
@template.instance_variable_set(:@project, nil)
|
||||
@template.instance_variable_set(:@status, 500)
|
||||
@template.instance_variable_set(:@message, message)
|
||||
else
|
||||
@project = nil
|
||||
end
|
||||
rescue StandardError
|
||||
# bad luck
|
||||
@project = nil # rubocop:disable Rails/HelperInstanceVariable
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,44 +37,46 @@ module FlashMessagesHelper
|
||||
# Renders flash messages
|
||||
def render_flash_messages
|
||||
messages = flash
|
||||
.reject { |k, _| k.to_s == "op_primer_flash" }
|
||||
.reject { |k, _| k.start_with? "_" }
|
||||
.map do |k, v|
|
||||
if k.to_sym == :modal
|
||||
component = v[:type].constantize
|
||||
component.new(**v.fetch(:parameters, {})).render_in(self)
|
||||
else
|
||||
render_flash_message(k, v)
|
||||
end
|
||||
end
|
||||
.reject { |k, _| k.to_s == "modal" }
|
||||
.map { |k, v| render_flash_content(k.to_sym, v) }
|
||||
|
||||
safe_join messages, "\n"
|
||||
end
|
||||
|
||||
def render_flash_message(type, message, html_options = {}) # rubocop:disable Metrics/AbcSize
|
||||
if type.to_s == "notice"
|
||||
type = "success"
|
||||
def render_flash_content(key, content)
|
||||
case content
|
||||
when Hash
|
||||
render_flash_message(key, **content)
|
||||
else
|
||||
render_flash_message(key, message: content)
|
||||
end
|
||||
end
|
||||
|
||||
toast_css_classes = ["op-toast -#{type}", html_options.delete(:class)]
|
||||
def render_flash_modal
|
||||
content = flash[:modal]
|
||||
return if content.blank?
|
||||
|
||||
# Add autohide class to notice flashes if configured
|
||||
if type.to_s == "success" && User.current.pref.auto_hide_popups?
|
||||
toast_css_classes << "autohide-toaster"
|
||||
component = content[:type].constantize
|
||||
component.new(**content.fetch(:parameters, {})).render_in(self)
|
||||
end
|
||||
|
||||
def mapped_flash_type(type)
|
||||
case type
|
||||
when :error, :danger
|
||||
:danger
|
||||
when :warning
|
||||
:warning
|
||||
when :success, :notice
|
||||
:success
|
||||
else
|
||||
:default
|
||||
end
|
||||
end
|
||||
|
||||
html_options = { class: toast_css_classes.join(" "), role: "alert" }.merge(html_options)
|
||||
close_button = content_tag :a, "", class: "op-toast--close icon-context icon-close",
|
||||
title: I18n.t("js.close_popup_title"),
|
||||
tabindex: "0"
|
||||
toast = content_tag(:div, join_flash_messages(message), class: "op-toast--content")
|
||||
content_tag :div, "", class: "op-toast--wrapper" do
|
||||
content_tag :div, "", class: "op-toast--casing" do
|
||||
content_tag :div, html_options do
|
||||
concat(close_button)
|
||||
concat(toast)
|
||||
end
|
||||
end
|
||||
def render_flash_message(type, message:, **args)
|
||||
render(OpPrimer::FlashComponent.new(scheme: mapped_flash_type(type), **args)) do
|
||||
join_flash_messages(message)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) the OpenProject GmbH
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 3.
|
||||
#
|
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
# Copyright (C) 2010-2013 the ChiliProject Team
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
#
|
||||
|
||||
module PrimerizedFlashHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def render_primerized_flash
|
||||
return if flash[:op_primer_flash].blank?
|
||||
|
||||
system_arguments = flash[:op_primer_flash]
|
||||
message = system_arguments.delete(:message)
|
||||
|
||||
render(OpPrimer::FlashComponent.new(**system_arguments)) do
|
||||
message
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,53 +0,0 @@
|
||||
<%#-- copyright
|
||||
OpenProject is an open source project management software.
|
||||
Copyright (C) the OpenProject GmbH
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 3.
|
||||
|
||||
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
Copyright (C) 2010-2013 the ChiliProject Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
See COPYRIGHT and LICENSE files for more details.
|
||||
|
||||
++#%>
|
||||
|
||||
<div class="op-toast--wrapper">
|
||||
<div class="op-toast--casing">
|
||||
<div id="errorExplanation"
|
||||
data-members-form-target="errorExplanation"
|
||||
class="op-toast errorExplanation -error <%= local_assigns[:classes] || '' %>"
|
||||
tabindex="0"
|
||||
role="alert">
|
||||
<div class="op-toast--content">
|
||||
<% if content_for?(:error_details) %>
|
||||
<p>
|
||||
<strong><%= error_message %></strong>
|
||||
</p>
|
||||
<%= content_for :error_details %>
|
||||
<% else %>
|
||||
<%= error_message %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<span class="close-handler" role="button" tabindex="0" aria-label="{{ ::I18n.t('js.close_popup_title') }}">
|
||||
<%= op_icon('icon-close') %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,42 +0,0 @@
|
||||
<%#-- copyright
|
||||
OpenProject is an open source project management software.
|
||||
Copyright (C) the OpenProject GmbH
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 3.
|
||||
|
||||
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
Copyright (C) 2010-2013 the ChiliProject Team
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
See COPYRIGHT and LICENSE files for more details.
|
||||
|
||||
++#%>
|
||||
|
||||
<% content_for :error_details, flush: true do %>
|
||||
<%= list_of_messages(base_error_messages) %>
|
||||
<%= text_header_invalid_fields(base_error_messages, fields_error_messages) %>
|
||||
<%= list_of_messages(fields_error_messages) %>
|
||||
<% end %>
|
||||
|
||||
<%= render partial: "common/error_base",
|
||||
locals: {
|
||||
error_message: t("activerecord.errors.template.header",
|
||||
model: object_name,
|
||||
count: base_error_messages.count + fields_error_messages.count)
|
||||
}
|
||||
%>
|
||||
@@ -27,14 +27,6 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
|
||||
++#%>
|
||||
|
||||
<% if @message_details %>
|
||||
<% content_for :error_details do %>
|
||||
<p><%= @message_details %></p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% error_message = "[#{I18n.t(:error_code, code: @status)}] #{@message}" %>
|
||||
<%= render partial: "common/error_base", locals: { error_message: error_message } %>
|
||||
<%= call_hook(:view_common_error_details, { params: params, project: ((defined? @project) ? @project : nil) }) %>
|
||||
|
||||
<% html_title h(@status) %>
|
||||
<% html_title h(status) %>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<%# Primerized flash messages are being rendered separately %>
|
||||
<div id="primerized-flash-messages"
|
||||
class="op-primer-flash"
|
||||
data-controller="flash"
|
||||
data-flash-autohide-value="<%= User.current.pref.auto_hide_popups? %>">
|
||||
<%= render_flash_messages %>
|
||||
</div>
|
||||
|
||||
<%# Flash modals render modal components %>
|
||||
<%= render_flash_modal %>
|
||||
@@ -117,14 +117,7 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
<% end %>
|
||||
<div class="content-overlay"></div>
|
||||
<%= content_tag :main, id: "content-wrapper", class: initial_classes, data: stimulus_content_data do %>
|
||||
<%# Primerized flash messages are being rendered separately %>
|
||||
<div id="primerized-flash-messages" class="op-primer-flash">
|
||||
<%= render_primerized_flash %>
|
||||
</div>
|
||||
<%# Flash messages are being rendered using the old op-flash style %>
|
||||
<turbo-frame id="flash-messages">
|
||||
<%= render_flash_messages %>
|
||||
</turbo-frame>
|
||||
<%= render partial: "layouts/flashes" %>
|
||||
<% if show_onboarding_modal? %>
|
||||
<section data-augmented-model-wrapper
|
||||
data-modal-initialize-now="true"
|
||||
|
||||
@@ -44,7 +44,10 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
<%= link_to(I18n.t('label_home'), home_url, class: 'op-logo--link') %>
|
||||
</div>
|
||||
</header>
|
||||
<%= yield %>
|
||||
<main id="content-wrapper">
|
||||
<%= render partial: "layouts/flashes" %>
|
||||
<%= yield %>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -5,8 +5,6 @@ export function setupServerResponse() {
|
||||
focusFirstErroneousField();
|
||||
activateFlashNotice();
|
||||
activateFlashError();
|
||||
autoHideFlashMessage();
|
||||
flashCloseHandler();
|
||||
|
||||
jQuery(document).ajaxComplete(activateFlashNotice);
|
||||
jQuery(document).ajaxComplete(activateFlashError);
|
||||
@@ -90,22 +88,6 @@ export function setupServerResponse() {
|
||||
});
|
||||
}
|
||||
|
||||
function flashCloseHandler() {
|
||||
jQuery('body').on('click keydown touchend', '.close-handler,.op-toast--close', function (e) {
|
||||
if (e.type === 'click' || e.which === 13) {
|
||||
jQuery(this).parent('.errorExplanation, .op-toast')
|
||||
.not('.persistent-toggle--notification')
|
||||
.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function autoHideFlashMessage() {
|
||||
setTimeout(() => {
|
||||
jQuery('.op-toast.autohide-toaster').remove();
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function addClickEventToAllErrorMessages() {
|
||||
jQuery('a.afocus').each(function () {
|
||||
const target = jQuery(this);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { ApplicationController } from 'stimulus-use';
|
||||
|
||||
export const SUCCESS_AUTOHIDE_TIMEOUT = 5000;
|
||||
|
||||
export default class FlashController extends ApplicationController {
|
||||
static values = {
|
||||
autohide: Boolean,
|
||||
};
|
||||
|
||||
declare autohideValue:boolean;
|
||||
|
||||
static targets = [
|
||||
'item',
|
||||
];
|
||||
|
||||
declare readonly itemTargets:HTMLElement;
|
||||
|
||||
itemTargetConnected(element:HTMLElement) {
|
||||
const autohide = element.dataset.autohide === 'true';
|
||||
if (this.autohideValue && autohide) {
|
||||
setTimeout(() => element.remove(), SUCCESS_AUTOHIDE_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import PollForChangesController from './controllers/poll-for-changes.controller'
|
||||
import TableHighlightingController from './controllers/table-highlighting.controller';
|
||||
import OpShowWhenCheckedController from './controllers/show-when-checked.controller';
|
||||
import OpShowWhenValueSelectedController from './controllers/show-when-value-selected.controller';
|
||||
import FlashController from './controllers/flash.controller';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@@ -31,6 +32,7 @@ instance.register('menus--main', MainMenuController);
|
||||
instance.register('show-when-checked', OpShowWhenCheckedController);
|
||||
instance.register('disable-when-checked', OpDisableWhenCheckedController);
|
||||
instance.register('show-when-value-selected', OpShowWhenValueSelectedController);
|
||||
instance.register('flash', FlashController);
|
||||
instance.register('print', PrintController);
|
||||
instance.register('refresh-on-form-changes', RefreshOnFormChangesController);
|
||||
instance.register('async-dialog', AsyncDialogController);
|
||||
|
||||
@@ -17,21 +17,31 @@ See below for available arguments.
|
||||
## Render primer banner / flash from controllers
|
||||
|
||||
In many views in OpenProject, you will find `flash[:notice], flash[:alert], flash[:error]` messages.
|
||||
These are rendered using the previous `op-flash` styles, and are not yet primerized.
|
||||
All of these are now rendered with primer banners by default.
|
||||
|
||||
So if you find yourself in need to render a primerized flash. You can use this pattern instead:
|
||||
If you find the need to customize the rendering of the flash, you can also pass a hash to the flash:
|
||||
|
||||
```ruby
|
||||
flash[:op_primer_flash] = { message: "Successful update", scheme: :success, icon: :check }
|
||||
flash[:notice] = { message: "Successful update", icon: :check }
|
||||
```
|
||||
|
||||
Or for an error:
|
||||
|
||||
```ruby
|
||||
flash[:op_primer_flash] = { message: "Oh no! Something went wrong", scheme: :danger, icon: :alert }
|
||||
flash[:error] = { message: "Oh no! Something went wrong", icon: :alert }
|
||||
```
|
||||
|
||||
These are rendered in the layout through the `render_banner_messages` helper using the `OpPrimer::FlashComponent`.
|
||||
If you want to render multiple lines, `message` can also be an array that will be joined by breaklines for rendering:
|
||||
|
||||
```ruby
|
||||
flash[:error] = { message: ["Oh no! Something went wrong", "Some more details here"], icon: :alert }
|
||||
```
|
||||
|
||||
If you want to make the flash non-dismissable, you can pass `dismiss_scheme: :none`:
|
||||
|
||||
```ruby
|
||||
flash[:error] = { message: "Oh no!", icon: :alert, dismiss_scheme: :none }
|
||||
```
|
||||
|
||||
## Usage in turbo streams
|
||||
|
||||
|
||||
@@ -185,8 +185,7 @@ RSpec.describe "Backlogs in backlog view", :js,
|
||||
|
||||
click_button "Save"
|
||||
|
||||
backlogs_page
|
||||
.expect_and_dismiss_toaster(message: "Successful update.")
|
||||
expect_and_dismiss_flash(message: "Successful update.")
|
||||
|
||||
backlogs_page
|
||||
.expect_backlog(sprint)
|
||||
@@ -206,8 +205,7 @@ RSpec.describe "Backlogs in backlog view", :js,
|
||||
|
||||
click_button "Save"
|
||||
|
||||
backlogs_page
|
||||
.expect_and_dismiss_toaster(message: "Successful update.")
|
||||
expect_and_dismiss_flash(message: "Successful update.")
|
||||
|
||||
# Now works as a sprint instead of a backlog
|
||||
backlogs_page
|
||||
@@ -228,8 +226,7 @@ RSpec.describe "Backlogs in backlog view", :js,
|
||||
|
||||
click_button "Save"
|
||||
|
||||
backlogs_page
|
||||
.expect_and_dismiss_toaster(message: "Successful update.")
|
||||
expect_and_dismiss_flash(message: "Successful update.")
|
||||
|
||||
# the disabled backlog/sprint is no longer visible
|
||||
expect(page)
|
||||
@@ -250,8 +247,7 @@ RSpec.describe "Backlogs in backlog view", :js,
|
||||
|
||||
click_button "Save"
|
||||
|
||||
backlogs_page
|
||||
.expect_and_dismiss_toaster(message: "Successful update.")
|
||||
expect_and_dismiss_flash(message: "Successful update.")
|
||||
|
||||
# the disabled backlog/sprint is no longer visible
|
||||
expect(page)
|
||||
|
||||
@@ -57,11 +57,11 @@ RSpec.describe "authorization for BCF api", :js, with_config: { edition: "bim" }
|
||||
fill_in "application_redirect_uri", with: "not a url!"
|
||||
click_on "Create"
|
||||
|
||||
expect(page).to have_css(".errorExplanation", text: "Redirect URI must be an absolute URI.")
|
||||
expect(page).to have_text("Redirect URI must be an absolute URI.")
|
||||
fill_in "application_redirect_uri", with: "urn:ietf:wg:oauth:2.0:oob\nhttps://localhost/my/callback"
|
||||
click_on "Create"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful creation.")
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
expect(page).to have_css(".attributes-key-value--key",
|
||||
text: "Client ID")
|
||||
|
||||
@@ -103,7 +103,7 @@ RSpec.describe "Copy work packages through Rails view", :js, :with_cuprite, with
|
||||
|
||||
select budget.subject, from: "work_package_budget_id"
|
||||
click_on "Submit"
|
||||
wp_table.expect_and_dismiss_toaster message: "Successful update."
|
||||
expect_and_dismiss_flash message: "Successful update."
|
||||
|
||||
expect(work_package.reload.budget_id).to eq(budget.id)
|
||||
expect(work_package2.reload.budget_id).to eq(budget.id)
|
||||
|
||||
@@ -130,7 +130,7 @@ RSpec.describe "model management", :js, with_config: { edition: "bim" } do
|
||||
|
||||
it "I can't see any models and perform no actions" do
|
||||
expected = "[Error 403] You are not authorized to access this page."
|
||||
expect(page).to have_css(".op-toast.-error", text: expected)
|
||||
expect_flash(type: :error, message: expected)
|
||||
|
||||
index_page.add_model_allowed false
|
||||
end
|
||||
|
||||
@@ -45,6 +45,7 @@ RSpec.describe "model viewer", :js, with_config: { edition: "bim" } do
|
||||
uploader: user)
|
||||
end
|
||||
|
||||
let(:show_default_page) { Pages::IfcModels::ShowDefault.new(project) }
|
||||
let(:show_model_page) { Pages::IfcModels::Show.new(project, model.id) }
|
||||
let(:model_tree) { Components::XeokitModelTree.new }
|
||||
let(:card_view) { Pages::WorkPackageCards.new(project) }
|
||||
@@ -93,7 +94,7 @@ RSpec.describe "model viewer", :js, with_config: { edition: "bim" } do
|
||||
it "shows a warning that no IFC models exist yet" do
|
||||
login_as user
|
||||
visit defaults_bcf_project_ifc_models_path(project)
|
||||
expect(page).to have_css(".op-toast.-info", text: I18n.t("js.ifc_models.empty_warning"))
|
||||
show_default_page.expect_toast(type: :info, message: I18n.t("js.ifc_models.empty_warning"))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -134,7 +135,7 @@ RSpec.describe "model viewer", :js, with_config: { edition: "bim" } do
|
||||
|
||||
it "shows no viewer" do
|
||||
expected = "[Error 403] You are not authorized to access this page."
|
||||
expect(page).to have_css(".op-toast.-error", text: expected)
|
||||
expect_flash(type: :error, message: expected)
|
||||
|
||||
show_model_page.model_viewer_visible false
|
||||
show_model_page.model_viewer_shows_a_toolbar false
|
||||
|
||||
@@ -300,7 +300,7 @@ RSpec.describe "Board management spec", :js, with_ee: %i[board_view] do
|
||||
|
||||
it "does not allow viewing of boards" do
|
||||
visit project_work_package_board_path(project, board_view)
|
||||
expect(page).to have_css("#errorExplanation", text: I18n.t(:notice_not_authorized))
|
||||
expect_flash(type: :error, message: I18n.t(:notice_not_authorized))
|
||||
|
||||
board_index.expect_editable false
|
||||
end
|
||||
@@ -311,7 +311,7 @@ RSpec.describe "Board management spec", :js, with_ee: %i[board_view] do
|
||||
|
||||
it "does not allow viewing of boards" do
|
||||
board_index.visit!
|
||||
expect(page).to have_css("#errorExplanation", text: I18n.t(:notice_not_authorized))
|
||||
expect_flash(type: :error, message: I18n.t(:notice_not_authorized))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -195,8 +195,9 @@ RSpec.describe "Boards",
|
||||
it "renders a required attribute validation error" do
|
||||
expect(Boards::Grid.all).to be_empty
|
||||
|
||||
new_board_page.expect_toast message: "Project #{I18n.t('activerecord.errors.messages.blank')}",
|
||||
type: :error
|
||||
expect_flash message: "Project #{I18n.t('activerecord.errors.messages.blank')}",
|
||||
type: :error
|
||||
|
||||
new_board_page.expect_project_dropdown
|
||||
end
|
||||
end
|
||||
|
||||
@@ -72,7 +72,7 @@ module Pages
|
||||
new_board_page.set_board_type action
|
||||
new_board_page.click_on_submit
|
||||
|
||||
new_board_page.expect_and_dismiss_toaster
|
||||
expect_and_dismiss_flash(message: I18n.t(:notice_successful_create))
|
||||
|
||||
if expect_empty
|
||||
expect(page).to have_css(".boards-list--add-item-text", wait: 10)
|
||||
|
||||
@@ -284,7 +284,7 @@ module Pages
|
||||
click_dropdown_entry "Delete"
|
||||
|
||||
accept_alert_dialog!
|
||||
expect_and_dismiss_toaster message: I18n.t("js.notice_successful_delete")
|
||||
expect_and_dismiss_flash message: I18n.t("js.notice_successful_delete")
|
||||
end
|
||||
|
||||
def back_to_index
|
||||
|
||||
@@ -122,7 +122,7 @@ RSpec.describe "adding a new budget", :js do
|
||||
new_budget_page.add_labor_costs! "0,5", user_name: user.name, comment: "attendance", expected_costs: "12,50 EUR"
|
||||
|
||||
page.find('[data-test-selector="budgets-create-button"]').click
|
||||
expect(page).to have_content(I18n.t(:notice_successful_create, locale: :de))
|
||||
expect_and_dismiss_flash(message: I18n.t(:notice_successful_create, locale: :de))
|
||||
|
||||
expect(new_budget_page.unit_costs_at(1)).to have_content "175,00 EUR"
|
||||
expect(new_budget_page.unit_costs_at(2)).to have_content "50.025,00 EUR"
|
||||
|
||||
@@ -59,6 +59,8 @@ RSpec.describe "Upload attachment to budget", :js do
|
||||
|
||||
click_on "Create"
|
||||
|
||||
expect_and_dismiss_flash(message: "Successful creation.")
|
||||
|
||||
expect(page).to have_css("#content img", count: 1)
|
||||
expect(page).to have_content("Image uploaded on creation")
|
||||
attachments_list.expect_attached("image.png")
|
||||
@@ -96,6 +98,8 @@ RSpec.describe "Upload attachment to budget", :js do
|
||||
|
||||
click_on "Create"
|
||||
|
||||
expect_and_dismiss_flash(message: "Successful creation.")
|
||||
|
||||
attachments_list.expect_attached("image.png")
|
||||
|
||||
within ".toolbar-items" do
|
||||
|
||||
@@ -88,7 +88,7 @@ RSpec.describe "Copying a budget", :js do
|
||||
|
||||
click_button "Create"
|
||||
|
||||
budget_page.expect_toast message: "Successful creation."
|
||||
expect_flash message: "Successful creation."
|
||||
|
||||
expect(page)
|
||||
.to have_css(".author", text: current_user.name)
|
||||
|
||||
@@ -181,7 +181,7 @@ RSpec.describe "updating a budget", :js do
|
||||
|
||||
# Update first element
|
||||
budget_page.edit_planned_costs! material_budget_item.id, type: :material, costs: 123
|
||||
expect(budget_page).to have_content("Successful update")
|
||||
expect_and_dismiss_flash(message: "Successful update")
|
||||
expect(page).to have_css("tbody td.currency", text: "123.00 EUR")
|
||||
|
||||
click_on "Update"
|
||||
@@ -218,7 +218,7 @@ RSpec.describe "updating a budget", :js do
|
||||
|
||||
# Update first element
|
||||
budget_page.edit_planned_costs! material_budget_item.id, type: :material, costs: 123
|
||||
expect(budget_page).to have_content("Successful update")
|
||||
expect_and_dismiss_flash(message: "Successful update")
|
||||
expect(page).to have_css("tbody td.currency", text: "USD 123.00")
|
||||
|
||||
click_on "Update"
|
||||
@@ -258,7 +258,7 @@ RSpec.describe "updating a budget", :js do
|
||||
|
||||
# Update first element
|
||||
budget_page.edit_planned_costs! labor_budget_item.id, type: :labor, costs: 456
|
||||
expect(budget_page).to have_content("Successful update")
|
||||
expect_and_dismiss_flash(message: "Successful update")
|
||||
expect(page).to have_css("tbody td.currency", text: "456.00 EUR")
|
||||
|
||||
click_on "Update"
|
||||
@@ -295,7 +295,7 @@ RSpec.describe "updating a budget", :js do
|
||||
|
||||
# Update first element
|
||||
budget_page.edit_planned_costs! labor_budget_item.id, type: :labor, costs: 456
|
||||
expect(budget_page).to have_content("Successful update")
|
||||
expect_and_dismiss_flash(message: "Successful update")
|
||||
expect(page).to have_css("tbody td.currency", text: "USD 456.00")
|
||||
|
||||
click_on "Update"
|
||||
|
||||
@@ -99,7 +99,7 @@ RSpec.describe "Work Package cost fields", :js do
|
||||
click_on "Save"
|
||||
|
||||
# Expect correct costs
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_cost_logged_successfully))
|
||||
expect_flash(message: I18n.t(:notice_cost_logged_successfully))
|
||||
entry = CostEntry.last
|
||||
expect(entry.cost_type_id).to eq(cost_type2.id)
|
||||
expect(entry.units).to eq(2.0)
|
||||
@@ -136,7 +136,7 @@ RSpec.describe "Work Package cost fields", :js do
|
||||
click_on I18n.t(:button_save)
|
||||
|
||||
# Expect correct costs
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_cost_logged_successfully))
|
||||
expect_flash(message: I18n.t(:notice_cost_logged_successfully))
|
||||
entry = CostEntry.last
|
||||
expect(entry.cost_type_id).to eq(cost_type2.id)
|
||||
expect(entry.units).to eq(1.42)
|
||||
|
||||
@@ -77,7 +77,7 @@ RSpec.describe "Create cost entry without rate permissions", :js do
|
||||
click_on "Save"
|
||||
|
||||
# Expect correct costs
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_cost_logged_successfully))
|
||||
expect_flash(message: I18n.t(:notice_cost_logged_successfully))
|
||||
entry = CostEntry.last
|
||||
expect(entry.cost_type_id).to eq(cost_type.id)
|
||||
expect(entry.units).to eq(1.0)
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe "LDAP group sync administration spec", :js do
|
||||
check "synchronized_group_sync_users"
|
||||
|
||||
click_on "Create"
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_create))
|
||||
expect_flash(message: I18n.t(:notice_successful_create))
|
||||
expect(page).to have_css("td.dn", text: "cn=foo,ou=groups,dc=example,dc=com")
|
||||
expect(page).to have_css("td.ldap_auth_source", text: "ldap")
|
||||
expect(page).to have_css("td.group", text: "foo")
|
||||
@@ -69,7 +69,7 @@ RSpec.describe "LDAP group sync administration spec", :js do
|
||||
SeleniumHubWaiter.wait
|
||||
click_on "Delete"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_delete))
|
||||
expect_flash(message: I18n.t(:notice_successful_delete))
|
||||
expect(page).to have_css ".generic-table--empty-row"
|
||||
|
||||
expect(LdapGroups::Membership.where(id: memberships)).to be_empty
|
||||
|
||||
@@ -167,8 +167,7 @@ RSpec.describe MeetingsController do
|
||||
expect(response).to have_http_status :ok
|
||||
expect(response).to render_template :new
|
||||
expect(response.body)
|
||||
.to have_css "#errorExplanation li",
|
||||
text: "Date #{I18n.t('activerecord.errors.messages.not_an_iso_date')}"
|
||||
.to have_text("Date #{I18n.t('activerecord.errors.messages.not_an_iso_date')}")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -181,8 +180,7 @@ RSpec.describe MeetingsController do
|
||||
expect(response).to have_http_status :ok
|
||||
expect(response).to render_template :new
|
||||
expect(response.body)
|
||||
.to have_css "#errorExplanation li",
|
||||
text: "Start time #{I18n.t('activerecord.errors.messages.invalid_time_format')}"
|
||||
.to have_text("Start time #{I18n.t('activerecord.errors.messages.invalid_time_format')}")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -194,8 +192,7 @@ RSpec.describe MeetingsController do
|
||||
expect(response).to have_http_status :ok
|
||||
expect(response).to render_template :new
|
||||
expect(response.body)
|
||||
.to have_css "#errorExplanation li",
|
||||
text: "Project #{I18n.t('activerecord.errors.messages.blank')}"
|
||||
.to have_text("Project #{I18n.t('activerecord.errors.messages.blank')}")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -207,8 +204,7 @@ RSpec.describe MeetingsController do
|
||||
expect(response).to have_http_status :ok
|
||||
expect(response).to render_template :new
|
||||
expect(response.body)
|
||||
.to have_css "#errorExplanation li",
|
||||
text: "Project #{I18n.t('activerecord.errors.messages.blank')}"
|
||||
.to have_text("Project #{I18n.t('activerecord.errors.messages.blank')}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -97,7 +97,7 @@ RSpec.describe "Meetings new", :js, with_cuprite: false do
|
||||
|
||||
show_page = new_page.click_create
|
||||
|
||||
show_page.expect_toast(message: "Successful creation")
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
show_page.expect_invited(user, other_user)
|
||||
|
||||
@@ -143,8 +143,8 @@ RSpec.describe "Meetings new", :js, with_cuprite: false do
|
||||
it "renders a validation error" do
|
||||
new_page.click_create
|
||||
|
||||
new_page.expect_toast(message: "#{Project.model_name.human} #{I18n.t('activerecord.errors.messages.blank')}",
|
||||
type: :error)
|
||||
expect_flash(type: :error,
|
||||
message: "#{Project.model_name.human} #{I18n.t('activerecord.errors.messages.blank')}")
|
||||
|
||||
new_page.expect_project_dropdown
|
||||
end
|
||||
@@ -178,7 +178,7 @@ RSpec.describe "Meetings new", :js, with_cuprite: false do
|
||||
|
||||
show_page = new_page.click_create
|
||||
|
||||
show_page.expect_toast(message: "Successful creation")
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
# Not sure if that is then intended behaviour but that is what is currently programmed
|
||||
show_page.expect_invited(admin)
|
||||
@@ -194,8 +194,10 @@ RSpec.describe "Meetings new", :js, with_cuprite: false do
|
||||
it "renders a validation error" do
|
||||
new_page.click_create
|
||||
|
||||
new_page.expect_toast(message: "#{Project.model_name.human} #{I18n.t('activerecord.errors.messages.blank')}",
|
||||
type: :error)
|
||||
expect_flash(
|
||||
message: "#{Project.model_name.human} #{I18n.t('activerecord.errors.messages.blank')}",
|
||||
type: :error
|
||||
)
|
||||
new_page.expect_project_dropdown
|
||||
end
|
||||
end
|
||||
@@ -254,7 +256,7 @@ RSpec.describe "Meetings new", :js, with_cuprite: false do
|
||||
|
||||
show_page = new_page.click_create
|
||||
|
||||
show_page.expect_toast(message: "Successful creation")
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
show_page.expect_invited(user, other_user)
|
||||
|
||||
@@ -315,7 +317,7 @@ RSpec.describe "Meetings new", :js, with_cuprite: false do
|
||||
|
||||
show_page = new_page.click_create
|
||||
|
||||
show_page.expect_toast(message: "Successful creation")
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
# Not sure if that is then intended behaviour but that is what is currently programmed
|
||||
show_page.expect_invited(admin)
|
||||
@@ -342,9 +344,9 @@ RSpec.describe "Meetings new", :js, with_cuprite: false do
|
||||
new_page.set_title "Some title"
|
||||
new_page.set_type "Classic"
|
||||
|
||||
show_page = new_page.click_create
|
||||
new_page.click_create
|
||||
|
||||
show_page.expect_toast(message: "Successful creation")
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
meeting = Meeting.last
|
||||
|
||||
@@ -352,7 +354,7 @@ RSpec.describe "Meetings new", :js, with_cuprite: false do
|
||||
|
||||
field.submit_by_enter
|
||||
|
||||
show_page.expect_and_dismiss_toaster message: "Successful update"
|
||||
expect_flash(message: "Successful update")
|
||||
|
||||
meeting.reload
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ RSpec.describe "Meetings participants" do
|
||||
|
||||
edit_page.invite(viewer_user)
|
||||
show_page = edit_page.click_save
|
||||
show_page.expect_toast(message: "Successful update")
|
||||
expect_flash(message: "Successful update")
|
||||
|
||||
show_page.expect_invited(viewer_user)
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ RSpec.describe "Meetings", :js do
|
||||
|
||||
field.submit_by_enter
|
||||
|
||||
show_page.expect_and_dismiss_toaster message: "Successful update"
|
||||
expect_and_dismiss_flash(message: "Successful update")
|
||||
|
||||
meeting.reload
|
||||
|
||||
|
||||
@@ -355,6 +355,6 @@ RSpec.describe "history",
|
||||
visit history_meeting_path(meeting)
|
||||
|
||||
expected = "[Error 403] You are not authorized to access this page."
|
||||
expect(page).to have_css(".op-toast.-error", text: expected)
|
||||
expect_flash(type: :error, message: expected)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -26,11 +26,14 @@
|
||||
# See COPYRIGHT and LICENSE files for more details.
|
||||
#++
|
||||
|
||||
require "support/flash/expectations"
|
||||
|
||||
module Components
|
||||
class CostReportsBaseTable
|
||||
include Capybara::DSL
|
||||
include Capybara::RSpecMatchers
|
||||
include RSpec::Matchers
|
||||
include Flash::Expectations
|
||||
|
||||
attr_reader :time_logging_modal
|
||||
|
||||
@@ -78,7 +81,7 @@ module Components
|
||||
SeleniumHubWaiter.wait
|
||||
fill_in("cost_entry_units", with: new_value)
|
||||
click_button "Save"
|
||||
expect(page).to have_css(".op-toast.-success")
|
||||
expect_flash(message: "Successful update.")
|
||||
end
|
||||
|
||||
def delete_entry(row)
|
||||
|
||||
+1
-4
@@ -73,10 +73,7 @@ class Storages::Admin::AutomaticallyManagedProjectFoldersController < Applicatio
|
||||
service_result = call_update_service
|
||||
|
||||
if service_result.success?
|
||||
flash[:op_primer_flash] = {
|
||||
message: I18n.t(:"storages.notice_successful_storage_connection"),
|
||||
scheme: :success
|
||||
}
|
||||
flash[:notice] = I18n.t(:"storages.notice_successful_storage_connection")
|
||||
redirect_to edit_admin_settings_storage_path(@storage)
|
||||
else
|
||||
respond_with_ampf_form_turbo_stream_or_edit_html
|
||||
|
||||
@@ -125,7 +125,7 @@ class Storages::Admin::OAuthClientsController < ApplicationController
|
||||
end
|
||||
|
||||
def finish_setup
|
||||
flash[:op_primer_flash] = { message: I18n.t(:"storages.notice_successful_storage_connection"), scheme: :success }
|
||||
flash[:notice] = I18n.t(:"storages.notice_successful_storage_connection")
|
||||
|
||||
redirect_to edit_admin_settings_storage_path(@storage)
|
||||
end
|
||||
|
||||
@@ -191,9 +191,7 @@ class Storages::Admin::StoragesController < ApplicationController
|
||||
update_via_turbo_stream(component: Storages::Admin::SidePanel::HealthNotificationsComponent.new(storage: @storage))
|
||||
respond_with_turbo_streams
|
||||
else
|
||||
flash.now[:op_primer_flash] = {
|
||||
message: I18n.t("storages.health_email_notifications.error_could_not_be_saved"), scheme: :danger
|
||||
}
|
||||
flash.now[:error] = I18n.t("storages.health_email_notifications.error_could_not_be_saved")
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
@@ -209,11 +207,11 @@ class Storages::Admin::StoragesController < ApplicationController
|
||||
|
||||
# rubocop:disable Rails/ActionControllerFlashBeforeRender
|
||||
service_result.on_failure do
|
||||
flash[:op_primer_flash] = { message: join_flash_messages(service_result.errors.full_messages), scheme: :danger }
|
||||
flash[:error] = service_result.errors.full_messages
|
||||
end
|
||||
|
||||
service_result.on_success do
|
||||
flash[:op_primer_flash] = { message: I18n.t(:notice_successful_delete), scheme: :success }
|
||||
flash[:notice] = I18n.t(:notice_successful_delete)
|
||||
end
|
||||
# rubocop:enable Rails/ActionControllerFlashBeforeRender
|
||||
|
||||
@@ -265,7 +263,7 @@ class Storages::Admin::StoragesController < ApplicationController
|
||||
def ensure_valid_provider_type_selected
|
||||
short_provider_type = params[:provider]
|
||||
if short_provider_type.blank? || (@provider_type = ::Storages::Storage::PROVIDER_TYPE_SHORT_NAMES[short_provider_type]).blank?
|
||||
flash[:op_primer_flash] = { message: I18n.t("storages.error_invalid_provider_type"), scheme: :danger }
|
||||
flash[:error] = I18n.t("storages.error_invalid_provider_type")
|
||||
redirect_to admin_settings_storages_path
|
||||
end
|
||||
end
|
||||
|
||||
@@ -181,7 +181,7 @@ RSpec.describe "Admin Create a new file storage",
|
||||
|
||||
expect(page).to have_current_path(edit_admin_settings_storage_path(Storages::Storage.last))
|
||||
expect(page).to have_test_selector(
|
||||
"primer-banner-message-component",
|
||||
"op-primer-flash-message",
|
||||
text: "Storage connected successfully! Remember to activate the module and the specific " \
|
||||
"storage in the project settings of each desired project to use it."
|
||||
)
|
||||
@@ -318,7 +318,7 @@ RSpec.describe "Admin Create a new file storage",
|
||||
|
||||
expect(page).to have_current_path(edit_admin_settings_storage_path(Storages::Storage.last))
|
||||
wait_for { page }.to have_test_selector(
|
||||
"primer-banner-message-component",
|
||||
"op-primer-flash-message",
|
||||
text: "Storage connected successfully! Remember to activate the module and the specific " \
|
||||
"storage in the project settings of each desired project to use it."
|
||||
)
|
||||
|
||||
@@ -50,7 +50,7 @@ RSpec.describe "activating an invited account", :js,
|
||||
|
||||
activate!
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "Developer strategy generated the following one-time password:")
|
||||
expect_flash(message: "Developer strategy generated the following one-time password:")
|
||||
|
||||
SeleniumHubWaiter.wait
|
||||
fill_in I18n.t(:field_otp), with: sms_token
|
||||
@@ -63,7 +63,7 @@ RSpec.describe "activating an invited account", :js,
|
||||
it "handles faulty user input on two factor authentication" do
|
||||
activate!
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "Developer strategy generated the following one-time password:")
|
||||
expect_flash(message: "Developer strategy generated the following one-time password:")
|
||||
|
||||
fill_in I18n.t(:field_otp), with: "asdf" # faulty token
|
||||
click_button I18n.t(:button_login)
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ RSpec.describe "Admin 2FA management", :js, with_settings: {
|
||||
click_button I18n.t(:button_continue)
|
||||
|
||||
# Enter valid phone number
|
||||
expect(page).to have_css("#errorExplanation", text: "Phone number must be of format +XX XXXXXXXXX")
|
||||
expect_flash(type: :error, message: "Phone number must be of format +XX XXXXXXXXX")
|
||||
|
||||
SeleniumHubWaiter.wait
|
||||
fill_in "device_phone_number", with: "+49 123456789"
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ RSpec.describe "Login with 2FA backup code", :js, with_settings: {
|
||||
click_on "Submit"
|
||||
|
||||
# Expect failure
|
||||
expect(page).to have_css(".op-toast.-error", text: I18n.t("two_factor_authentication.error_invalid_backup_code"))
|
||||
expect_flash(type: :error, message: I18n.t("two_factor_authentication.error_invalid_backup_code"))
|
||||
expect(page).to have_current_path signin_path
|
||||
|
||||
# Try again!
|
||||
|
||||
@@ -36,7 +36,7 @@ RSpec.describe "Login with enforced 2FA", :js, with_settings: {
|
||||
first_login_step
|
||||
two_factor_step("whatever")
|
||||
|
||||
expect(page).to have_css(".op-toast.-error", text: I18n.t(:notice_account_otp_invalid))
|
||||
expect_flash(type: :error, message: I18n.t(:notice_account_otp_invalid))
|
||||
expect(page).to have_current_path signin_path
|
||||
end
|
||||
end
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe "Login with 2FA device", :js, with_settings: {
|
||||
first_login_step
|
||||
two_factor_step("whatever")
|
||||
|
||||
expect(page).to have_css(".op-toast.-error", text: I18n.t(:notice_account_otp_invalid))
|
||||
expect_flash(type: :error, message: I18n.t(:notice_account_otp_invalid))
|
||||
expect(page).to have_current_path signin_path
|
||||
end
|
||||
end
|
||||
|
||||
@@ -35,7 +35,7 @@ RSpec.describe "My Account 2FA configuration", :js, with_settings: {
|
||||
click_button I18n.t(:button_continue)
|
||||
|
||||
# Enter valid phone number
|
||||
expect(page).to have_css("#errorExplanation", text: "Phone number must be of format +XX XXXXXXXXX")
|
||||
expect_flash(type: :error, message: "Phone number must be of format +XX XXXXXXXXX")
|
||||
fill_in "device_phone_number", with: "+49 123456789"
|
||||
click_button I18n.t(:button_continue)
|
||||
|
||||
@@ -55,8 +55,8 @@ RSpec.describe "My Account 2FA configuration", :js, with_settings: {
|
||||
|
||||
expect(page).to have_css("h2", text: I18n.t("two_factor_authentication.devices.confirm_device"))
|
||||
expect(page).to have_css("input#otp")
|
||||
expect(page).to have_css(".op-toast.-error",
|
||||
text: I18n.t("two_factor_authentication.devices.registration_failed_token_invalid"))
|
||||
|
||||
expect_flash(type: :error, message: I18n.t("two_factor_authentication.devices.registration_failed_token_invalid"))
|
||||
|
||||
# Fill in correct token
|
||||
fill_in "otp", with: sms_token
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ RSpec.describe "Login with 2FA remember cookie", :js, with_settings: {
|
||||
visit my_2fa_devices_path
|
||||
|
||||
find(".two-factor-authentication--remove-remember-cookie-link").click
|
||||
expect(page).to have_css(".op-toast.-success")
|
||||
expect_flash(message: I18n.t("two_factor_authentication.remember.cookie_removed"))
|
||||
expect(page).to have_no_css(".two-factor-authentication--remove-remember-cookie-link")
|
||||
|
||||
# Log out and in again
|
||||
|
||||
@@ -35,8 +35,8 @@ end
|
||||
|
||||
RSpec.shared_examples "create enforced sms device" do
|
||||
it do
|
||||
expect(page).to have_css(".op-toast.-info",
|
||||
text: I18n.t("two_factor_authentication.forced_registration.required_to_add_device"))
|
||||
expect_flash(type: :info,
|
||||
message: I18n.t("two_factor_authentication.forced_registration.required_to_add_device"))
|
||||
|
||||
SeleniumHubWaiter.wait
|
||||
# Create SMS device
|
||||
@@ -46,7 +46,7 @@ RSpec.shared_examples "create enforced sms device" do
|
||||
click_on "Continue"
|
||||
|
||||
# Expect error on invalid phone
|
||||
expect(page).to have_css("#errorExplanation", text: "Phone number must be of format +XX XXXXXXXXX")
|
||||
expect_flash(type: :error, message: "Phone number must be of format +XX XXXXXXXXX")
|
||||
|
||||
SeleniumHubWaiter.wait
|
||||
fill_in "device_phone_number", with: "+49 123456789"
|
||||
@@ -63,7 +63,7 @@ RSpec.shared_examples "create enforced sms device" do
|
||||
# Log token for next access
|
||||
sms_token = nil
|
||||
allow_any_instance_of(OpenProject::TwoFactorAuthentication::TokenStrategy::Developer)
|
||||
.to receive(:create_mobile_otp).and_wrap_original do |m|
|
||||
.to receive(:create_mobile_otp).and_wrap_original do |m|
|
||||
sms_token = m.call
|
||||
end
|
||||
|
||||
@@ -71,8 +71,7 @@ RSpec.shared_examples "create enforced sms device" do
|
||||
|
||||
expect(page).to have_css("h2", text: I18n.t("two_factor_authentication.devices.confirm_device"))
|
||||
expect(page).to have_css("input#otp")
|
||||
expect(page).to have_css(".op-toast.-error",
|
||||
text: I18n.t("two_factor_authentication.devices.registration_failed_token_invalid"))
|
||||
expect_flash(type: :error, message: I18n.t("two_factor_authentication.devices.registration_failed_token_invalid"))
|
||||
|
||||
SeleniumHubWaiter.wait
|
||||
# Fill in wrong token
|
||||
|
||||
@@ -40,7 +40,7 @@ RSpec.describe "Manage webhooks through UI", :js do
|
||||
# 1st webhook created
|
||||
#
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_create))
|
||||
expect_flash(message: I18n.t(:notice_successful_create))
|
||||
expect(page).to have_css(".webhooks--outgoing-webhook-row .name", text: "My webhook")
|
||||
webhook = Webhooks::Webhook.last
|
||||
expect(webhook.event_names).to eq %w(work_package:created)
|
||||
@@ -65,7 +65,7 @@ RSpec.describe "Manage webhooks through UI", :js do
|
||||
find(".webhooks--selected-project-ids[value='#{project.id}']").set true
|
||||
|
||||
click_on "Save"
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_update))
|
||||
expect_flash(message: I18n.t(:notice_successful_update))
|
||||
expect(page).to have_css(".webhooks--outgoing-webhook-row .name", text: "My webhook")
|
||||
webhook = Webhooks::Webhook.last
|
||||
expect(webhook.event_names).to eq %w(work_package:updated)
|
||||
@@ -77,7 +77,7 @@ RSpec.describe "Manage webhooks through UI", :js do
|
||||
find(".webhooks--outgoing-webhook-row-#{webhook.id} .icon-delete").click
|
||||
page.driver.browser.switch_to.alert.accept
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_delete))
|
||||
expect_flash(message: I18n.t(:notice_successful_delete))
|
||||
expect(page).to have_css(".generic-table--empty-row")
|
||||
end
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ RSpec.describe NewsController do
|
||||
expect(assigns(:news)).not_to be_nil
|
||||
expect(assigns(:news)).to be_new_record
|
||||
|
||||
expect(response.body).to have_css("div.op-toast.-error", text: /1 error/)
|
||||
expect(response.body).to have_text /1 error/
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -52,7 +52,8 @@ RSpec.describe "Wiki Activity", :js, :with_cuprite do
|
||||
editor.set_markdown("First content")
|
||||
|
||||
click_button "Save"
|
||||
expect(page).to have_text("Successful creation")
|
||||
|
||||
expect_and_dismiss_flash(message: "Successful creation.")
|
||||
|
||||
# We mock letting some time pass by altering the timestamps
|
||||
Journal.last.update_columns(created_at: Time.now - 5.days, updated_at: Time.now - 5.days)
|
||||
|
||||
@@ -113,7 +113,7 @@ RSpec.describe "Attribute help texts", :js, :with_cuprite do
|
||||
click_button "Save"
|
||||
|
||||
# Handle errors
|
||||
expect(page).to have_css("#errorExplanation", text: "Help text can't be blank.")
|
||||
expect_flash(type: :error, message: "Help text can't be blank.")
|
||||
SeleniumHubWaiter.wait
|
||||
editor.set_markdown("New**help**text")
|
||||
click_button "Save"
|
||||
|
||||
@@ -60,9 +60,8 @@ RSpec.describe "Enterprise token", :js, :with_cuprite do
|
||||
submit_button.click
|
||||
|
||||
# Error output
|
||||
expect(page).to have_css(".errorExplanation",
|
||||
text: "Enterprise support token can't be read. " \
|
||||
"Are you sure it is a support token?")
|
||||
expect_flash(type: :error,
|
||||
message: "Enterprise support token can't be read. Are you sure it is a support token?")
|
||||
|
||||
within "span.errorSpan" do
|
||||
expect(page).to have_css("#enterprise_token_encoded_token")
|
||||
@@ -78,7 +77,7 @@ RSpec.describe "Enterprise token", :js, :with_cuprite do
|
||||
textarea.set "foobar"
|
||||
submit_button.click
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_update))
|
||||
expect_flash(message: I18n.t(:notice_successful_update))
|
||||
expect(page).to have_test_selector("op-enterprise--active-token")
|
||||
|
||||
expect(page.all(".attributes-key-value--key").map(&:text))
|
||||
@@ -101,7 +100,7 @@ RSpec.describe "Enterprise token", :js, :with_cuprite do
|
||||
|
||||
wait_for_reload
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_update))
|
||||
expect_flash(message: I18n.t(:notice_successful_update))
|
||||
|
||||
# Assume next request
|
||||
RequestStore.clear!
|
||||
@@ -115,7 +114,7 @@ RSpec.describe "Enterprise token", :js, :with_cuprite do
|
||||
|
||||
wait_for_reload
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_delete))
|
||||
expect_flash(message: I18n.t(:notice_successful_delete))
|
||||
|
||||
# Assume next request
|
||||
RequestStore.clear!
|
||||
|
||||
@@ -257,7 +257,7 @@ RSpec.describe "Enterprise trial management",
|
||||
|
||||
it "can confirm that trial regularly" do
|
||||
find_test_selector("op-ee-trial-waiting-resend-link", text: "Resend").click
|
||||
expect(page).to have_css(".op-toast.-success", text: "Email has been resent.", wait: 20)
|
||||
expect(page).to have_css(".op-toast", text: "Email has been resent.", wait: 20)
|
||||
|
||||
expect(page).to have_text "foo@foocorp.example"
|
||||
expect(page).to have_text "email sent - waiting for confirmation"
|
||||
@@ -276,7 +276,7 @@ RSpec.describe "Enterprise trial management",
|
||||
# advance to close
|
||||
click_on "Continue"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_and_dismiss_flash(message: "Successful update.")
|
||||
expect(page).to have_css(".attributes-key-value--value-container", text: "OpenProject Test")
|
||||
expect(page).to have_css(".attributes-key-value--value-container", text: "01/01/2020")
|
||||
expect(page).to have_css(".attributes-key-value--value-container", text: "01/02/2020")
|
||||
|
||||
@@ -49,20 +49,20 @@ RSpec.describe "OAuth applications management", :js, :with_cuprite do
|
||||
fill_in "application_redirect_uri", with: "not a url!"
|
||||
click_on "Create"
|
||||
|
||||
expect(page).to have_css(".errorExplanation", text: "Redirect URI must be an absolute URI.")
|
||||
expect_flash(type: :error, message: "Redirect URI must be an absolute URI.")
|
||||
|
||||
fill_in("application_redirect_uri", with: "")
|
||||
# Fill redirect_uri which does not provide a Secure Context
|
||||
fill_in "application_redirect_uri", with: "http://example.org"
|
||||
click_on "Create"
|
||||
|
||||
expect(page).to have_css(".errorExplanation", text: 'Redirect URI is not providing a "Secure Context"')
|
||||
expect_flash(type: :error, message: 'Redirect URI is not providing a "Secure Context"')
|
||||
|
||||
# Can create localhost without https (https://community.openproject.com/wp/34025)
|
||||
fill_in "application_redirect_uri", with: "urn:ietf:wg:oauth:2.0:oob\nhttp://localhost/my/callback"
|
||||
click_on "Create"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful creation.")
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
expect(page).to have_css(".attributes-key-value--key", text: "Client ID")
|
||||
expect(page).to have_css(".attributes-key-value--value", text: "urn:ietf:wg:oauth:2.0:oob\nhttp://localhost/my/callback")
|
||||
|
||||
@@ -51,7 +51,7 @@ RSpec.describe "Progress tracking admin page", :js, :with_cuprite do
|
||||
expect(page).to have_text(expected_warning_text)
|
||||
|
||||
click_on "Save"
|
||||
expect_and_dismiss_toaster(message: "Successful update.")
|
||||
expect_and_dismiss_flash(message: "Successful update.")
|
||||
expect(Setting.find_by(name: "work_package_done_ratio").value).to eq("status")
|
||||
|
||||
# now change from status-based to work-based
|
||||
@@ -65,7 +65,7 @@ RSpec.describe "Progress tracking admin page", :js, :with_cuprite do
|
||||
expect(page).to have_text(expected_warning_text)
|
||||
|
||||
click_on "Save"
|
||||
expect_and_dismiss_toaster(message: "Successful update.")
|
||||
expect_and_dismiss_flash(message: "Successful update.")
|
||||
expect(Setting.find_by(name: "work_package_done_ratio").value).to eq("field")
|
||||
end
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ RSpec.describe "Test mail notification", :js, :with_cuprite do
|
||||
click_link "Send a test email"
|
||||
|
||||
expected = "An error occurred while sending mail (#{error_message})"
|
||||
expect(page).to have_css(".op-toast.-error", text: expected)
|
||||
expect_flash(type: :error, message: expected)
|
||||
expect(page).to have_no_css(".op-toast.-error strong")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -101,7 +101,7 @@ RSpec.describe "Working Days", :js, :with_cuprite do
|
||||
dialog.confirm
|
||||
end
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.")
|
||||
expect_flash(message: "Successful update.")
|
||||
expect(page).to have_unchecked_field "Monday"
|
||||
expect(page).to have_unchecked_field "Friday"
|
||||
expect(page).to have_unchecked_field "Saturday"
|
||||
@@ -141,8 +141,7 @@ RSpec.describe "Working Days", :js, :with_cuprite do
|
||||
dialog.confirm
|
||||
end
|
||||
|
||||
expect(page).to have_css(".op-toast.-error",
|
||||
text: "At least one day of the week must be defined as a working day.")
|
||||
expect_flash(type: :error, message: "At least one day of the week must be defined as a working day.")
|
||||
# Restore the checkboxes to their valid state
|
||||
expect(page).to have_checked_field "Monday"
|
||||
expect(page).to have_checked_field "Tuesday"
|
||||
@@ -172,8 +171,8 @@ RSpec.describe "Working Days", :js, :with_cuprite do
|
||||
# Not executing the background jobs
|
||||
dialog.confirm
|
||||
|
||||
expect(page).to have_css(".op-toast.-error",
|
||||
text: "The previous changes to the working days configuration have not been applied yet.")
|
||||
expect_flash(type: :error,
|
||||
message: "The previous changes to the working days configuration have not been applied yet.")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -230,7 +229,7 @@ RSpec.describe "Working Days", :js, :with_cuprite do
|
||||
click_on "Apply changes"
|
||||
click_on "Save and reschedule"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.")
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
nwd1 = NonWorkingDay.find_by(name: "My holiday")
|
||||
expect(nwd1.date).to eq date1
|
||||
@@ -310,6 +309,6 @@ RSpec.describe "Working Days", :js, :with_cuprite do
|
||||
click_on "Apply changes"
|
||||
|
||||
# No dialog and saved successfully
|
||||
expect(page).to have_css(".op-toast.-success")
|
||||
expect_flash(message: "Successful update.")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -168,7 +168,7 @@ RSpec.describe "Authentication Stages" do
|
||||
find_by_id("toggle_consent_time").set(true)
|
||||
|
||||
click_on "Save"
|
||||
expect(page).to have_css(".op-toast.-success")
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
Setting.clear_cache
|
||||
expect(Setting.consent_time).to be_present
|
||||
@@ -215,7 +215,7 @@ RSpec.describe "Authentication Stages" do
|
||||
check "consent_check"
|
||||
click_on I18n.t(:button_create)
|
||||
|
||||
expect(page).to have_css(".op-toast.-success")
|
||||
expect_flash(message: I18n.t(:notice_account_registered_and_logged_in))
|
||||
expect_logged_in("/?first_time_user=true")
|
||||
end
|
||||
|
||||
@@ -256,7 +256,7 @@ RSpec.describe "Authentication Stages" do
|
||||
# Decline the consent
|
||||
click_on I18n.t(:button_decline)
|
||||
|
||||
expect(page).to have_css(".op-toast.-error", text: "foo@example.org")
|
||||
expect_flash(type: :error, message: "foo@example.org")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,14 +39,14 @@ RSpec.describe "Lost password" do
|
||||
fill_in "mail", with: "invalid mail"
|
||||
click_on "Submit"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_account_lost_email_sent))
|
||||
expect_flash(message: I18n.t(:notice_account_lost_email_sent))
|
||||
|
||||
perform_enqueued_jobs
|
||||
expect(ActionMailer::Base.deliveries.size).to be 0
|
||||
|
||||
fill_in "mail", with: user.mail
|
||||
click_on "Submit"
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_account_lost_email_sent))
|
||||
expect_flash(message: I18n.t(:notice_account_lost_email_sent))
|
||||
|
||||
perform_enqueued_jobs
|
||||
expect(ActionMailer::Base.deliveries.size).to be 1
|
||||
@@ -60,7 +60,7 @@ RSpec.describe "Lost password" do
|
||||
|
||||
click_button "Save"
|
||||
|
||||
expect(page).to have_css(".op-toast.-info", text: I18n.t(:notice_account_password_updated))
|
||||
expect_flash(type: :info, message: I18n.t(:notice_account_password_updated))
|
||||
|
||||
login_with user.login, new_password
|
||||
|
||||
@@ -79,7 +79,7 @@ RSpec.describe "Lost password" do
|
||||
fill_in "mail", with: user.mail
|
||||
click_on "Submit"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_account_lost_email_sent))
|
||||
expect_flash(message: I18n.t(:notice_account_lost_email_sent))
|
||||
|
||||
perform_enqueued_jobs
|
||||
expect(ActionMailer::Base.deliveries.size).to be 1
|
||||
@@ -99,7 +99,7 @@ RSpec.describe "Lost password" do
|
||||
fill_in "mail", with: user.mail
|
||||
click_on "Submit"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_account_lost_email_sent))
|
||||
expect_flash(message: I18n.t(:notice_account_lost_email_sent))
|
||||
|
||||
perform_enqueued_jobs
|
||||
expect(ActionMailer::Base.deliveries.size).to be 1
|
||||
|
||||
@@ -38,7 +38,7 @@ RSpec.describe "Reordering custom options of a list custom field", :js do
|
||||
|
||||
click_link "Reorder values alphabetically"
|
||||
cf_page.accept_alert_dialog!
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_update))
|
||||
expect_flash(message: I18n.t(:notice_successful_update))
|
||||
expect(custom_field.custom_options.order(:position).pluck(:value))
|
||||
.to eq get_possible_values_reordered(200)
|
||||
end
|
||||
|
||||
@@ -60,7 +60,7 @@ RSpec.describe "Tabs navigation and content switching on the admin/design page"
|
||||
it "selects a color theme and redirect to the interface tab" do
|
||||
select("OpenProject Gray", from: "theme")
|
||||
find("[data-test-selector='color-theme-button']").click
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_update))
|
||||
expect_flash(message: I18n.t(:notice_successful_update))
|
||||
expect(page).to have_current_path custom_style_path(tab: "interface")
|
||||
end
|
||||
|
||||
@@ -78,7 +78,7 @@ RSpec.describe "Tabs navigation and content switching on the admin/design page"
|
||||
# select a color theme and redirect to the branding tab
|
||||
select("OpenProject Navy Blue", from: "theme")
|
||||
find("[data-test-selector='color-theme-button']").click
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_update))
|
||||
expect_flash(message: I18n.t(:notice_successful_update))
|
||||
expect(page).to have_current_path custom_style_path(tab: "branding")
|
||||
|
||||
# remove the logo and redirect to the branding tab
|
||||
@@ -94,7 +94,7 @@ RSpec.describe "Tabs navigation and content switching on the admin/design page"
|
||||
# select a color theme and redirect to the PDF export styles tab
|
||||
select("OpenProject (default)", from: "theme")
|
||||
find("[data-test-selector='color-theme-button']").click
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_update))
|
||||
expect_flash(message: I18n.t(:notice_successful_update))
|
||||
expect(page).to have_current_path custom_style_path(tab: "pdf_export_styles")
|
||||
|
||||
# change export cover text color and redirect to the PDF export styles tab
|
||||
|
||||
@@ -45,7 +45,7 @@ RSpec.describe "group memberships through groups page", :js, :with_cuprite do
|
||||
|
||||
groups_page.delete_group! "Bob's Team"
|
||||
|
||||
expect(page).to have_css(".op-toast.-info", text: I18n.t(:notice_deletion_scheduled))
|
||||
expect_flash(type: :info, message: I18n.t(:notice_deletion_scheduled))
|
||||
expect(groups_page).to have_group "Bob's Team"
|
||||
|
||||
perform_enqueued_jobs
|
||||
|
||||
@@ -71,7 +71,7 @@ RSpec.describe "Homescreen", "index", :with_cuprite do
|
||||
welcome_text_editor.click_and_type_slowly("Hello! ")
|
||||
|
||||
general_settings_page.press_save_button
|
||||
general_settings_page.expect_and_dismiss_toaster
|
||||
expect_and_dismiss_flash(message: "Successful update.")
|
||||
|
||||
visit root_url
|
||||
expect(page)
|
||||
|
||||
@@ -52,7 +52,7 @@ RSpec.describe "CRUD LDAP connections", :js, :with_cuprite do
|
||||
|
||||
click_on "Create"
|
||||
|
||||
ldap_page.expect_and_dismiss_toaster message: "Successful creation."
|
||||
expect_and_dismiss_flash message: "Successful creation."
|
||||
expect(page).to have_css("td.name", text: "My LDAP connection")
|
||||
expect(page).to have_css("td.host", text: "localhost")
|
||||
|
||||
@@ -71,7 +71,7 @@ RSpec.describe "CRUD LDAP connections", :js, :with_cuprite do
|
||||
accept_prompt { click_on "Delete" }
|
||||
end
|
||||
|
||||
ldap_page.expect_and_dismiss_toaster message: "Successful deletion."
|
||||
expect_and_dismiss_flash message: "Successful deletion."
|
||||
|
||||
expect(page).to have_no_text "My LDAP connection"
|
||||
expect(page).to have_text "Admin connection"
|
||||
@@ -88,7 +88,7 @@ RSpec.describe "CRUD LDAP connections", :js, :with_cuprite do
|
||||
fill_in "ldap_auth_source_name", with: "Updated Admin connection"
|
||||
click_on "Save"
|
||||
|
||||
ldap_page.expect_and_dismiss_toaster message: "Successful update."
|
||||
expect_flash(message: "Successful update.")
|
||||
expect(page).to have_css("td.name", text: "Updated Admin connection")
|
||||
end
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ RSpec.describe "members pagination", :js do
|
||||
members_page.visit!
|
||||
SeleniumHubWaiter.wait
|
||||
members_page.remove_user! "Alice Alison"
|
||||
members_page.expect_and_dismiss_toaster
|
||||
expect_and_dismiss_flash message: "Removed Alice Alison from project"
|
||||
expect(members_page).to have_user "Bob Bobbit"
|
||||
|
||||
SeleniumHubWaiter.wait
|
||||
|
||||
@@ -101,7 +101,7 @@ RSpec.describe "OAuth authorization code flow", :js do
|
||||
page.driver.browser.switch_to.alert.accept
|
||||
|
||||
# Should be back on access_token path
|
||||
expect(page).to have_css(".op-toast.-success")
|
||||
expect_flash(message: "Revocation of application Cool API app! successful.")
|
||||
expect(page).to have_no_css("[id^=oauth-application-grant]")
|
||||
|
||||
expect(page).to have_current_path /\/my\/access_token/
|
||||
|
||||
@@ -40,7 +40,7 @@ RSpec.describe "create placeholder users", :selenium do
|
||||
|
||||
new_placeholder_user_page.submit!
|
||||
|
||||
expect(page).to have_css(".op-toast", text: "Successful creation.")
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
new_placeholder_user = PlaceholderUser.order(Arel.sql("id DESC")).first
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ RSpec.describe "delete placeholder user", :js do
|
||||
expect(page).to have_css(".danger-zone--verification button:not([disabled])")
|
||||
click_on "Delete"
|
||||
|
||||
expect(page).to have_css(".op-toast.-info", text: I18n.t(:notice_deletion_scheduled))
|
||||
expect_flash(type: :info, message: I18n.t(:notice_deletion_scheduled))
|
||||
|
||||
# The user is still there
|
||||
placeholder_user.reload
|
||||
|
||||
@@ -41,7 +41,7 @@ RSpec.describe "edit placeholder users", :js do
|
||||
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.")
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
placeholder_user.reload
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ RSpec.shared_examples "principal membership management flows" do
|
||||
principal_page.expect_project(project.name)
|
||||
principal_page.edit_roles!(member, %w())
|
||||
|
||||
expect(page).to have_css(".op-toast.-error", text: "Roles need to be assigned.")
|
||||
expect_flash(type: :error, message: "Roles need to be assigned.")
|
||||
|
||||
# Remove the user from the project
|
||||
principal_page.remove_from_project!(project.name)
|
||||
|
||||
@@ -53,7 +53,7 @@ RSpec.describe "Projects#destroy", :js, :with_cuprite do
|
||||
expect(danger_zone).not_to be_disabled
|
||||
danger_zone.danger_button.click
|
||||
|
||||
expect(page).to have_css ".op-toast.-success", text: I18n.t("projects.delete.scheduled")
|
||||
expect_flash message: I18n.t("projects.delete.scheduled")
|
||||
expect(project.reload).to eq(project)
|
||||
|
||||
perform_enqueued_jobs
|
||||
|
||||
@@ -65,11 +65,10 @@ RSpec.describe "Projects module administration" do
|
||||
check "Calendar"
|
||||
click_button "Save"
|
||||
|
||||
expect(page)
|
||||
.to have_css ".op-toast.-error",
|
||||
text: I18n.t(:"activerecord.errors.models.project.attributes.enabled_modules.dependency_missing",
|
||||
dependency: "Work packages",
|
||||
module: "Calendars")
|
||||
expect_flash(type: :error, message:
|
||||
I18n.t(:"activerecord.errors.models.project.attributes.enabled_modules.dependency_missing",
|
||||
dependency: "Work packages",
|
||||
module: "Calendars"))
|
||||
|
||||
expect(page).to have_no_xpath(project_work_packages_menu_link_selector)
|
||||
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ RSpec.describe "Edit project custom fields on project overview page", :js do
|
||||
member_with_project_attributes_edit_permissions.reload
|
||||
dialog.submit
|
||||
|
||||
expect(page).to have_css("#errorExplanation", text: I18n.t(:notice_not_authorized))
|
||||
expect_flash(type: :error, message: I18n.t(:notice_not_authorized))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -274,9 +274,9 @@ RSpec.describe "Projects index page", :js, :with_cuprite, with_settings: { login
|
||||
|
||||
error_text = "Orders ><script src='/foobar js'></script> is not set to one of the allowed values. and does not exist."
|
||||
error_html = "Orders ><script src='/foobar js'></script> is not set to one of the allowed values. and does not exist."
|
||||
expect(page).to have_css(".op-toast.-error", text: error_text)
|
||||
expect_flash(type: :error, message: error_text)
|
||||
|
||||
error_container = page.find(".op-toast.-error")
|
||||
error_container = find_flash_element(type: :error)
|
||||
expect(error_container["innerHTML"]).to include error_html
|
||||
end
|
||||
end
|
||||
|
||||
@@ -115,7 +115,7 @@ RSpec.describe "Projects index page", :js, :with_cuprite, with_settings: { login
|
||||
# Save the page
|
||||
scroll_to_and_click(find(".button", text: "Save"))
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.")
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
RequestStore.clear!
|
||||
query = JSON.parse Setting.project_gantt_query
|
||||
|
||||
@@ -44,6 +44,7 @@ RSpec.describe "Project templates", :js, :with_cuprite,
|
||||
|
||||
# Make a template
|
||||
find(".button", text: "Set as template").click
|
||||
expect_and_dismiss_flash(message: "Successful update.")
|
||||
|
||||
expect(page).to have_css(".button", text: "Remove from templates")
|
||||
project.reload
|
||||
|
||||
@@ -149,8 +149,7 @@ RSpec.describe "Create repository", :js, :selenium do
|
||||
|
||||
click_button(I18n.t(:button_create))
|
||||
|
||||
expect(page).to have_css("div.op-toast.-success",
|
||||
text: I18n.t("repositories.create_successful"))
|
||||
expect_flash(message: I18n.t("repositories.create_successful"))
|
||||
expect(page).to have_css("a.icon-delete", text: I18n.t(:button_delete))
|
||||
end
|
||||
end
|
||||
@@ -162,8 +161,7 @@ RSpec.describe "Create repository", :js, :selenium do
|
||||
|
||||
click_button(I18n.t(:button_create))
|
||||
|
||||
expect(page).to have_css("div.op-toast.-success",
|
||||
text: I18n.t("repositories.create_successful"))
|
||||
expect_flash(message: I18n.t("repositories.create_successful"))
|
||||
expect(page).to have_css('button[type="submit"]', text: I18n.t(:button_save))
|
||||
expect(page).to have_css("a.icon-remove", text: I18n.t(:button_remove))
|
||||
end
|
||||
|
||||
@@ -193,8 +193,7 @@ RSpec.describe "Repository Settings", :js do
|
||||
|
||||
click_button(I18n.t(:button_save))
|
||||
expect(page).to have_css('[name="repository[login]"][value="foobar"]')
|
||||
expect(page).to have_css(".op-toast",
|
||||
text: I18n.t("repositories.update_settings_successful"))
|
||||
expect_flash(message: I18n.t("repositories.update_settings_successful"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -55,8 +55,7 @@ RSpec.describe "Role creation", :js, :with_cuprite do
|
||||
|
||||
click_button "Create"
|
||||
|
||||
expect(page)
|
||||
.to have_css(".errorExplanation", text: "Name has already been taken")
|
||||
expect_flash(type: :error, message: "Name has already been taken")
|
||||
|
||||
fill_in "Name", with: "New role name"
|
||||
|
||||
@@ -65,17 +64,15 @@ RSpec.describe "Role creation", :js, :with_cuprite do
|
||||
|
||||
click_button "Create"
|
||||
|
||||
expect(page)
|
||||
.to have_css(".errorExplanation",
|
||||
text: "Permissions need to also include 'View members' as 'Manage members' is selected.")
|
||||
expect_flash(type: :error,
|
||||
message: "Permissions need to also include 'View members' as 'Manage members' is selected.")
|
||||
|
||||
check "View members"
|
||||
select existing_role.name, from: "Copy workflow from"
|
||||
|
||||
click_button "Create"
|
||||
|
||||
expect(page)
|
||||
.to have_css(".-success", text: "Successful creation.")
|
||||
expect_and_dismiss_flash(message: "Successful creation.")
|
||||
|
||||
expect(page)
|
||||
.to have_current_path(roles_path)
|
||||
|
||||
@@ -52,8 +52,7 @@ RSpec.describe "Types", :js, :with_cuprite do
|
||||
|
||||
click_button "Create"
|
||||
|
||||
expect(page)
|
||||
.to have_css(".errorExplanation", text: "Name has already been taken.")
|
||||
expect_flash(type: :error, message: "Name has already been taken.")
|
||||
|
||||
# Values are retained
|
||||
expect(page)
|
||||
@@ -123,9 +122,7 @@ RSpec.describe "Types", :js, :with_cuprite do
|
||||
end
|
||||
|
||||
it "renders an error message with links to the archived project in the projects list" do
|
||||
within ".op-toast.-error" do
|
||||
expect(page).to have_link(project.name)
|
||||
end
|
||||
expect_flash type: :error, message: project.name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -93,7 +93,7 @@ RSpec.describe "form query configuration", :js, :with_cuprite do
|
||||
it "can save an empty query group" do
|
||||
form.add_query_group("Empty test", :children)
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash(message: "Successful update.")
|
||||
type_bug.reload
|
||||
|
||||
query_group = type_bug.attribute_groups.detect { |x| x.is_a?(Type::QueryGroup) }
|
||||
@@ -105,7 +105,7 @@ RSpec.describe "form query configuration", :js, :with_cuprite do
|
||||
form.add_query_group("Subtasks", :children)
|
||||
# Save changed query
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
# Visit wp_table
|
||||
wp_table.visit!
|
||||
@@ -131,7 +131,7 @@ RSpec.describe "form query configuration", :js, :with_cuprite do
|
||||
form.add_query_group("Subtasks", :children)
|
||||
# Save changed query
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
# Visit new wp page
|
||||
visit new_project_work_packages_path(project)
|
||||
@@ -156,7 +156,7 @@ RSpec.describe "form query configuration", :js, :with_cuprite do
|
||||
filters.save
|
||||
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash message: "Successful update."
|
||||
|
||||
archived.update_attribute(:active, false)
|
||||
|
||||
@@ -184,7 +184,7 @@ RSpec.describe "form query configuration", :js, :with_cuprite do
|
||||
|
||||
# Save changed query
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
type_bug.reload
|
||||
query = type_bug.attribute_groups.detect { |x| x.key == "Columns Test" }
|
||||
@@ -206,7 +206,7 @@ RSpec.describe "form query configuration", :js, :with_cuprite do
|
||||
|
||||
# Save changed query
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
type_bug.reload
|
||||
query = type_bug.attribute_groups.detect { |x| x.key == "Columns Test" }
|
||||
@@ -253,7 +253,7 @@ RSpec.describe "form query configuration", :js, :with_cuprite do
|
||||
filters.save
|
||||
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
# Visit work package with that type
|
||||
wp_page.visit!
|
||||
|
||||
@@ -91,7 +91,7 @@ RSpec.describe "form configuration", :js do
|
||||
|
||||
# Save configuration
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
form.expect_empty
|
||||
|
||||
@@ -171,7 +171,7 @@ RSpec.describe "form configuration", :js do
|
||||
|
||||
# Save configuration
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
# Expect configuration to be correct now
|
||||
form.expect_no_attribute("assignee", "Cool Stuff")
|
||||
@@ -269,7 +269,7 @@ RSpec.describe "form configuration", :js do
|
||||
form.expect_attribute(key: cf_identifier)
|
||||
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash(message: "Successful update.")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -299,7 +299,7 @@ RSpec.describe "form configuration", :js do
|
||||
form.expect_attribute(key: cf_identifier)
|
||||
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash(message: "Successful update.")
|
||||
end
|
||||
|
||||
context "if inactive in project" do
|
||||
|
||||
@@ -60,7 +60,7 @@ RSpec.describe "Reset form configuration", :js do
|
||||
form.expect_attribute(key: cf_identifier)
|
||||
|
||||
form.save_changes
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.", wait: 10)
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
SeleniumHubWaiter.wait
|
||||
form.reset_button.click
|
||||
|
||||
@@ -45,7 +45,7 @@ RSpec.describe "create users", :with_cuprite do
|
||||
|
||||
shared_examples_for "successful user creation" do |redirect_to_edit_page: true|
|
||||
it "creates the user" do
|
||||
expect(page).to have_css(".op-toast", text: "Successful creation.")
|
||||
expect_flash(message: "Successful creation.")
|
||||
|
||||
new_user = User.order(Arel.sql("id DESC")).first
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ RSpec.describe "edit users", :js, :with_cuprite do
|
||||
|
||||
click_button "Save"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful update.")
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
user.reload
|
||||
|
||||
@@ -140,7 +140,7 @@ RSpec.describe "edit users", :js, :with_cuprite do
|
||||
|
||||
click_on "Send invitation"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "An invitation has been sent to foo@example.com")
|
||||
expect_flash(message: "An invitation has been sent to foo@example.com")
|
||||
end
|
||||
|
||||
it "can not edit attributes of an admin user" do
|
||||
|
||||
@@ -60,7 +60,7 @@ RSpec.describe "random password generation", :js, :with_cuprite do
|
||||
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_css(".op-toast", text: I18n.t(:notice_successful_update))
|
||||
expect_flash(message: "Successful update.")
|
||||
expect(password).to be_present
|
||||
|
||||
# Logout
|
||||
@@ -90,7 +90,7 @@ RSpec.describe "random password generation", :js, :with_cuprite do
|
||||
expect(Sessions::UserSession.for_user(user.id).count).to be >= 1
|
||||
|
||||
click_on "Save"
|
||||
expect(page).to have_css(".op-toast.-info", text: I18n.t(:notice_account_password_updated))
|
||||
expect_flash(type: :info, message: I18n.t(:notice_account_password_updated))
|
||||
|
||||
# The old session is removed
|
||||
expect(Sessions::UserSession.find_by(session_id: "other")).to be_nil
|
||||
@@ -126,7 +126,7 @@ RSpec.describe "random password generation", :js, :with_cuprite do
|
||||
find_by_id("settings_password_min_adhered_rules").set 3
|
||||
|
||||
scroll_to_and_click(find(".button", text: "Save"))
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_update))
|
||||
expect_flash(message: "Successful update.")
|
||||
|
||||
Setting.clear_cache
|
||||
|
||||
@@ -144,19 +144,19 @@ RSpec.describe "random password generation", :js, :with_cuprite do
|
||||
fill_in "user_password", with: "adminADMIN"
|
||||
fill_in "user_password_confirmation", with: "adminADMIN"
|
||||
scroll_to_and_click(find(".button", text: "Save"))
|
||||
expect(page).to have_css(".errorExplanation", text: "Password Must contain characters of the following classes")
|
||||
expect_flash(type: :error, message: "Password Must contain characters of the following classes")
|
||||
|
||||
# 2 of 3 classes
|
||||
fill_in "user_password", with: "adminADMIN123"
|
||||
fill_in "user_password_confirmation", with: "adminADMIN123"
|
||||
scroll_to_and_click(find(".button", text: "Save"))
|
||||
expect(page).to have_css(".errorExplanation", text: "Password Must contain characters of the following classes")
|
||||
expect_flash(type: :error, message: "Password Must contain characters of the following classes")
|
||||
|
||||
# All classes
|
||||
fill_in "user_password", with: "adminADMIN!"
|
||||
fill_in "user_password_confirmation", with: "adminADMIN!"
|
||||
scroll_to_and_click(find(".button", text: "Save"))
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_update))
|
||||
expect_flash(message: I18n.t(:notice_successful_update))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ RSpec.describe "version delete", :js, :with_cuprite do
|
||||
end
|
||||
end
|
||||
|
||||
expect(page).to have_css(".op-toast.-error", text: I18n.t(:error_can_not_delete_in_use_archived_undisclosed))
|
||||
expect_flash(type: :error, message: I18n.t(:error_can_not_delete_in_use_archived_undisclosed))
|
||||
expect(page).to have_no_css("a", text: "Archived child")
|
||||
|
||||
user.update!(admin: true)
|
||||
@@ -67,7 +67,7 @@ RSpec.describe "version delete", :js, :with_cuprite do
|
||||
end
|
||||
end
|
||||
|
||||
expect(page).to have_css(".op-toast.-error", text: "There are also work packages in archived projects.")
|
||||
expect_flash(type: :error, message: "There are also work packages in archived projects.")
|
||||
expect(page).to have_css("a", text: "Archived child")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -82,6 +82,7 @@ RSpec.describe "wiki pages", :js, with_settings: { journal_aggregation_time_minu
|
||||
find(".ck-content").base.send_keys(content_first_version)
|
||||
click_button "Save"
|
||||
|
||||
expect_and_dismiss_flash(message: "Successful creation.")
|
||||
expect(page).to have_css(".title-container", text: "New page")
|
||||
expect(page).to have_css(".wiki-content", text: content_first_version)
|
||||
|
||||
|
||||
@@ -56,14 +56,11 @@ RSpec.describe "Upload attachment to wiki page", :js do
|
||||
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_text("Successful creation")
|
||||
expect_and_dismiss_flash(message: "Successful creation")
|
||||
expect(page).to have_css("#content img", count: 1)
|
||||
expect(page).to have_content("Image uploaded the first time")
|
||||
attachments_list.expect_attached("image.png")
|
||||
|
||||
# required sleep otherwise clicking on the Edit button doesn't do anything
|
||||
SeleniumHubWaiter.wait
|
||||
|
||||
within ".toolbar-items" do
|
||||
click_on "Edit"
|
||||
end
|
||||
@@ -116,7 +113,7 @@ RSpec.describe "Upload attachment to wiki page", :js do
|
||||
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_text("Successful creation")
|
||||
expect_and_dismiss_flash(message: "Successful creation")
|
||||
attachments_list.expect_attached("image.png")
|
||||
|
||||
# required sleep otherwise clicking on the Edit button doesn't do anything
|
||||
|
||||
@@ -41,6 +41,6 @@ RSpec.describe "Editing a new wiki page", :js do
|
||||
expect(page).to have_field "page_title", with: "Foobar"
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: "Successful creation.", wait: 10)
|
||||
expect_flash(message: "Successful creation.", wait: 10)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -201,35 +201,17 @@ RSpec.describe "Copy work packages through Rails view", :js, :with_cuprite do
|
||||
it "fails, informing of the reasons" do
|
||||
click_on "Copy and follow"
|
||||
|
||||
expect(page)
|
||||
.to have_css(
|
||||
".op-toast.-error",
|
||||
text: I18n.t("work_packages.bulk.none_could_be_saved", total: 3)
|
||||
)
|
||||
|
||||
expect(page)
|
||||
.to have_css(
|
||||
".op-toast.-error",
|
||||
text: I18n.t("work_packages.bulk.selected_because_descendants", total: 3, selected: 2)
|
||||
)
|
||||
|
||||
expect(page)
|
||||
.to have_css(
|
||||
".op-toast.-error",
|
||||
text: "#{work_package.id}: Type #{I18n.t('activerecord.errors.messages.inclusion')}"
|
||||
)
|
||||
|
||||
expect(page)
|
||||
.to have_css(
|
||||
".op-toast.-error",
|
||||
text: "#{work_package2.id}: Type #{I18n.t('activerecord.errors.messages.inclusion')}"
|
||||
)
|
||||
|
||||
expect(page)
|
||||
.to have_css(
|
||||
".op-toast.-error",
|
||||
text: "#{child.id} (descendant of selected): Type #{I18n.t('activerecord.errors.messages.inclusion')}"
|
||||
)
|
||||
expect_flash(type: :error, message: I18n.t("work_packages.bulk.none_could_be_saved", total: 3))
|
||||
expect_flash(type: :error,
|
||||
message: I18n.t(
|
||||
"work_packages.bulk.selected_because_descendants", total: 3, selected: 2
|
||||
))
|
||||
expect_flash(type: :error,
|
||||
message: "#{work_package.id}: Type #{I18n.t('activerecord.errors.messages.inclusion')}")
|
||||
expect_flash(type: :error,
|
||||
message: "#{work_package2.id}: Type #{I18n.t('activerecord.errors.messages.inclusion')}")
|
||||
expect_flash(type: :error, message:
|
||||
"#{child.id} (descendant of selected): Type #{I18n.t('activerecord.errors.messages.inclusion')}")
|
||||
end
|
||||
|
||||
context "when the limit to move in the frontend is 0",
|
||||
@@ -316,9 +298,7 @@ RSpec.describe "Copy work packages through Rails view", :js, :with_cuprite do
|
||||
|
||||
click_on "Copy and follow"
|
||||
|
||||
expect(page)
|
||||
.to have_css(".op-toast.-success",
|
||||
text: I18n.t(:notice_successful_create))
|
||||
expect_flash(message: I18n.t(:notice_successful_create))
|
||||
|
||||
wp_page = Pages::FullWorkPackage.new(WorkPackage.last)
|
||||
|
||||
|
||||
@@ -140,10 +140,7 @@ RSpec.describe "Moving a work package through Rails view", :js do
|
||||
click_on "Move and follow"
|
||||
wait_for_reload
|
||||
|
||||
expect(page)
|
||||
.to have_css(".op-toast.-error",
|
||||
text: I18n.t(:"work_packages.bulk.none_could_be_saved",
|
||||
total: 1))
|
||||
expect_flash type: :error, message: I18n.t(:"work_packages.bulk.none_could_be_saved", total: 1)
|
||||
|
||||
# Should NOT have moved
|
||||
child_wp.reload
|
||||
@@ -170,10 +167,7 @@ RSpec.describe "Moving a work package through Rails view", :js do
|
||||
click_on "Move and follow"
|
||||
end
|
||||
|
||||
expect(page)
|
||||
.to have_css(".op-toast.-error",
|
||||
text: I18n.t(:"work_packages.bulk.none_could_be_saved",
|
||||
total: 1))
|
||||
expect_flash type: :error, message: I18n.t(:"work_packages.bulk.none_could_be_saved", total: 1)
|
||||
child_wp.reload
|
||||
work_package.reload
|
||||
expect(work_package.project_id).to eq(project.id)
|
||||
@@ -215,23 +209,16 @@ RSpec.describe "Moving a work package through Rails view", :js do
|
||||
end
|
||||
|
||||
it "displays an error message explaining which work package could not be moved and why" do
|
||||
expect(page)
|
||||
.to have_css(".op-toast.-error",
|
||||
text: I18n.t("work_packages.bulk.could_not_be_saved"),
|
||||
wait: 10)
|
||||
expect_flash(type: :error,
|
||||
message: I18n.t("work_packages.bulk.could_not_be_saved"))
|
||||
expect_flash(type: :error,
|
||||
message: "#{work_package2.id}: Project #{I18n.t('activerecord.errors.messages.error_readonly')}")
|
||||
|
||||
expect(page)
|
||||
.to have_css(
|
||||
".op-toast.-error",
|
||||
text: "#{work_package2.id}: Project #{I18n.t('activerecord.errors.messages.error_readonly')}"
|
||||
)
|
||||
|
||||
expect(page)
|
||||
.to have_css(".op-toast.-error",
|
||||
text: I18n.t("work_packages.bulk.x_out_of_y_could_be_saved",
|
||||
failing: 1,
|
||||
total: 2,
|
||||
success: 1))
|
||||
expect_flash(type: :error, message:
|
||||
I18n.t("work_packages.bulk.x_out_of_y_could_be_saved",
|
||||
failing: 1,
|
||||
total: 2,
|
||||
success: 1))
|
||||
|
||||
expect(work_package.reload.project_id).to eq(project2.id)
|
||||
expect(work_package2.reload.project_id).to eq(project.id)
|
||||
|
||||
@@ -111,27 +111,17 @@ RSpec.describe "Bulk update work packages through Rails view", :js, :with_cuprit
|
||||
fill_in "Parent", with: "-1"
|
||||
click_on "Submit"
|
||||
|
||||
expect(page)
|
||||
.to have_css(
|
||||
".op-toast.-error",
|
||||
text: I18n.t("work_packages.bulk.none_could_be_saved", total: 2)
|
||||
)
|
||||
expect_flash(type: :error, message: I18n.t("work_packages.bulk.none_could_be_saved", total: 2))
|
||||
expect_flash(type: :error,
|
||||
message: "#{work_package.id}: Parent #{I18n.t('activerecord.errors.messages.does_not_exist')}")
|
||||
|
||||
expect(page)
|
||||
.to have_css(
|
||||
".op-toast.-error",
|
||||
text: "#{work_package.id}: Parent #{I18n.t('activerecord.errors.messages.does_not_exist')}"
|
||||
)
|
||||
|
||||
expect(page)
|
||||
.to have_css(
|
||||
".op-toast.-error",
|
||||
text: <<~MSG.squish
|
||||
#{work_package2.id}:
|
||||
Parent #{I18n.t('activerecord.errors.messages.does_not_exist')}
|
||||
Status #{I18n.t('activerecord.errors.models.work_package.attributes.status_id.status_transition_invalid')}
|
||||
MSG
|
||||
)
|
||||
expect_flash(type: :error, message:
|
||||
<<~MSG.squish
|
||||
#{work_package2.id}:
|
||||
Parent #{I18n.t('activerecord.errors.messages.does_not_exist')}
|
||||
Status #{I18n.t('activerecord.errors.models.work_package.attributes.status_id.status_transition_invalid')}
|
||||
MSG
|
||||
)
|
||||
|
||||
# Should not update the status
|
||||
work_package2.reload
|
||||
@@ -153,21 +143,16 @@ RSpec.describe "Bulk update work packages through Rails view", :js, :with_cuprit
|
||||
fill_in custom_field.name, with: "Custom field text"
|
||||
click_on "Submit"
|
||||
|
||||
expect(page)
|
||||
.to have_css(
|
||||
".op-toast.-error",
|
||||
text: I18n.t("work_packages.bulk.x_out_of_y_could_be_saved", total: 2, failing: 1, success: 1)
|
||||
)
|
||||
expect_flash(type: :error, message:
|
||||
I18n.t("work_packages.bulk.x_out_of_y_could_be_saved", total: 2, failing: 1, success: 1))
|
||||
|
||||
expect(page)
|
||||
.to have_css(
|
||||
".op-toast.-error",
|
||||
text: <<~MSG.squish
|
||||
#{work_package2.id}:
|
||||
#{custom_field.name} #{I18n.t('activerecord.errors.messages.error_readonly')}
|
||||
#{I18n.t('activerecord.errors.models.work_package.readonly_status')}
|
||||
MSG
|
||||
)
|
||||
expect_flash(type: :error, message:
|
||||
<<~MSG.squish
|
||||
#{work_package2.id}:
|
||||
#{custom_field.name} #{I18n.t('activerecord.errors.messages.error_readonly')}
|
||||
#{I18n.t('activerecord.errors.models.work_package.readonly_status')}
|
||||
MSG
|
||||
)
|
||||
|
||||
# Should update 1 work package custom field only
|
||||
work_package.reload
|
||||
@@ -189,7 +174,7 @@ RSpec.describe "Bulk update work packages through Rails view", :js, :with_cuprit
|
||||
fill_in custom_field.name, with: "Custom field text"
|
||||
click_on "Submit"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success", text: I18n.t(:notice_successful_update))
|
||||
expect_and_dismiss_flash(message: I18n.t(:notice_successful_update))
|
||||
|
||||
# Should update 2 work package custom fields
|
||||
work_package.reload
|
||||
|
||||
@@ -186,7 +186,7 @@ RSpec.describe "Work display", :js do
|
||||
visit admin_settings_working_days_and_hours_path
|
||||
select "Days and hours", from: "Duration format"
|
||||
click_on "Apply changes"
|
||||
expect_and_dismiss_toaster(message: "Successful update.")
|
||||
expect_and_dismiss_flash(message: "Successful update.")
|
||||
|
||||
wp_table.visit_query query
|
||||
|
||||
|
||||
@@ -148,11 +148,11 @@ RSpec.describe "Work package navigation", :js, :selenium do
|
||||
it "loading an unknown work package ID" do
|
||||
visit "/work_packages/999999999"
|
||||
|
||||
page404 = Pages::Page.new
|
||||
page404.expect_toast type: :error, message: I18n.t(:notice_file_not_found)
|
||||
expect_flash type: :error, message: I18n.t(:notice_file_not_found)
|
||||
|
||||
visit "/projects/#{project.identifier}/work_packages/999999999"
|
||||
page404.expect_and_dismiss_toaster type: :error, message: I18n.t("api_v3.errors.not_found.work_package")
|
||||
global_work_packages = Pages::WorkPackagesTable.new
|
||||
global_work_packages.expect_toast type: :error, message: I18n.t("api_v3.errors.not_found.work_package")
|
||||
end
|
||||
|
||||
# Regression #29994
|
||||
|
||||
@@ -50,7 +50,8 @@ RSpec.describe "Wysiwyg autosave spec",
|
||||
editor.click_and_type_slowly "Initial version"
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success")
|
||||
expect_and_dismiss_flash(message: "Successful creation.")
|
||||
|
||||
within("#content") do
|
||||
expect(page).to have_text "Initial version"
|
||||
end
|
||||
@@ -69,7 +70,7 @@ RSpec.describe "Wysiwyg autosave spec",
|
||||
# Save wiki page
|
||||
click_on "Save"
|
||||
|
||||
expect(page).to have_css(".op-toast.-success")
|
||||
expect_flash(message: "Successful update.")
|
||||
within("#content") do
|
||||
expect(page).to have_text "This should be saved"
|
||||
end
|
||||
@@ -79,6 +80,8 @@ RSpec.describe "Wysiwyg autosave spec",
|
||||
keys = page.evaluate_script "Object.keys(localStorage)"
|
||||
expect(keys).to include "op_ckeditor_rev_/api/v3/wiki_pages/#{wiki_page.id}_page[text]"
|
||||
|
||||
expect_and_dismiss_flash(message: "Successful update.")
|
||||
|
||||
# Edit again
|
||||
click_on "Edit"
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user