Remove notified events

pull/9685/head
Oliver Günther 3 years ago
parent 26014cda50
commit 612572190a
No known key found for this signature in database
GPG Key ID: 88872239EB414F99
  1. 2
      app/controllers/admin/settings/notifications_settings_controller.rb
  2. 11
      app/helpers/settings_helper.rb
  3. 2
      app/services/notifications/create_from_model_service/comment_strategy.rb
  4. 2
      app/services/notifications/create_from_model_service/message_strategy.rb
  5. 2
      app/services/notifications/create_from_model_service/news_strategy.rb
  6. 2
      app/services/notifications/create_from_model_service/wiki_content_strategy.rb
  7. 8
      app/services/notifications/mail_service/comment_strategy.rb
  8. 8
      app/services/notifications/mail_service/message_strategy.rb
  9. 8
      app/services/notifications/mail_service/news_strategy.rb
  10. 6
      app/services/notifications/mail_service/wiki_content_strategy.rb
  11. 22
      app/views/admin/settings/notifications_settings/show.html.erb
  12. 2
      app/views/wiki/show.html.erb
  13. 10
      app/workers/mails/member_job.rb
  14. 1
      config/locales/en.yml
  15. 10
      config/settings.yml
  16. 1
      frontend/src/app/features/user-preferences/reminder-settings/page/reminder-settings-page.component.ts
  17. 2
      frontend/src/app/features/user-preferences/reminder-settings/reminder-time/reminder-settings-daily-time.component.ts
  18. 54
      lib/open_project/notifiable.rb
  19. 2
      modules/documents/app/controllers/documents_controller.rb
  20. 2
      modules/documents/app/services/notifications/create_from_model_service/document_strategy.rb
  21. 8
      modules/documents/app/services/notifications/mail_service/document_strategy.rb
  22. 1
      modules/documents/lib/open_project/documents/engine.rb
  23. 41
      modules/documents/lib/open_project/documents/patches/notifiable_patch.rb
  24. 1
      modules/documents/spec/controllers/documents_controller_spec.rb
  25. 1
      modules/documents/spec/features/attachment_upload_spec.rb
  26. 4
      modules/documents/spec/lib/open_project/markdown_formatting_spec.rb
  27. 39
      modules/documents/spec/lib/open_project/notifiable_spec.rb
  28. 13
      modules/documents/spec/services/notifications/mail_service_spec.rb
  29. 4
      modules/meeting/spec/lib/open_project/markdown_formatting_spec.rb
  30. 40
      spec/helpers/settings_helper_spec.rb
  31. 42
      spec/lib/open_project/notifiable_spec.rb
  32. 1
      spec/models/mail_handler_spec.rb
  33. 3
      spec/models/news_spec.rb
  34. 128
      spec/models/setting_spec.rb
  35. 5
      spec/models/wiki_content_spec.rb
  36. 55
      spec/services/notifications/mail_service_spec.rb
  37. 36
      spec/workers/mails/shared/member_job.rb
  38. 4
      spec_legacy/unit/mail_handler_spec.rb

@ -35,8 +35,6 @@ module Admin::Settings
end
def show
@notifiables = OpenProject::Notifiable.all
respond_to :html
end

@ -186,17 +186,6 @@ module SettingsHelper
setting_label(setting, options) + wrap_field_outer(options, &block)
end
# Renders a notification field for an OpenProject::Notifiable option
def notification_field(notifiable, options = {})
content_tag(:label, class: 'form--label-with-check-box') do
styled_check_box_tag('settings[notified_events][]',
notifiable.name,
Setting.notified_events.include?(notifiable.name),
options.merge(id: nil)) +
l_or_humanize(notifiable.name, prefix: 'label_')
end
end
private
def wrap_field_outer(options, &block)

@ -50,7 +50,7 @@ module Notifications::CreateFromModelService::CommentStrategy
end
def self.subscribed_users(comment)
User.notified_globally notification_reason(comment)
User.notified_globally subscribed_notification_reason(comment)
end
def self.subscribed_notification_reason(_comment)

@ -50,7 +50,7 @@ module Notifications::CreateFromModelService::MessageStrategy
end
def self.subscribed_users(journal)
User.notified_globally notification_reason(journal)
User.notified_globally subscribed_notification_reason(journal)
end
def self.subscribed_notification_reason(_journal)

@ -51,7 +51,7 @@ module Notifications::CreateFromModelService::NewsStrategy
def self.subscribed_users(journal)
if journal.initial?
User.notified_globally notification_reason(journal)
User.notified_globally subscribed_notification_reason(journal)
else
# No notification on updating a news
User.none

@ -50,7 +50,7 @@ module Notifications::CreateFromModelService::WikiContentStrategy
end
def self.subscribed_users(journal)
User.notified_globally notification_reason(journal)
User.notified_globally subscribed_notification_reason(journal)
end
def self.subscribed_notification_reason(journal)

@ -29,8 +29,6 @@
module Notifications::MailService::CommentStrategy
class << self
def send_mail(notification)
return if notification_disabled?
UserMailer
.news_comment_added(
notification.recipient,
@ -39,11 +37,5 @@ module Notifications::MailService::CommentStrategy
)
.deliver_later
end
private
def notification_disabled?
Setting.notified_events.exclude?('news_comment_added')
end
end
end

@ -29,8 +29,6 @@
module Notifications::MailService::MessageStrategy
class << self
def send_mail(notification)
return if notification_disabled?
UserMailer
.message_posted(
notification.recipient,
@ -39,11 +37,5 @@ module Notifications::MailService::MessageStrategy
)
.deliver_later
end
private
def notification_disabled?
Setting.notified_events.exclude?('message_posted')
end
end
end

@ -29,7 +29,7 @@
module Notifications::MailService::NewsStrategy
class << self
def send_mail(notification)
return if notification_disabled? || !notification.journal.initial?
return unless notification.journal.initial?
UserMailer
.news_added(
@ -39,11 +39,5 @@ module Notifications::MailService::NewsStrategy
)
.deliver_later
end
private
def notification_disabled?
Setting.notified_events.exclude?('news_added')
end
end
end

@ -31,8 +31,6 @@ module Notifications::MailService::WikiContentStrategy
def send_mail(notification)
method = mailer_method(notification)
return if notification_disabled?(method.to_s)
UserMailer
.send(method,
notification.recipient,
@ -50,9 +48,5 @@ module Notifications::MailService::WikiContentStrategy
:wiki_content_updated
end
end
def notification_disabled?(name)
Setting.notified_events.exclude?(name)
end
end
end

@ -50,27 +50,5 @@ See COPYRIGHT and LICENSE files for more details.
</span>
</div>
<fieldset id="notified_events" class="form--fieldset">
<legend class="form--fieldset-legend">
<%= t(:text_select_notifications) %>
</legend>
<div class="form--toolbar">
<span class="form--toolbar-item">
(<%= check_all_links 'notified_events' %>)
</span>
</div>
<%= hidden_field_tag 'settings[notified_events][]', '' %>
<div class="form--field">
<div class="form--field-container -vertical">
<% @notifiables.each do |notifiable| %>
<%= notification_field notifiable %>
<% end %>
</div>
<span class="form--field-instructions -no-margin">
<%= t(:'settings.notifications.events_explanation') %>
</span>
</div>
</fieldset>
<%= styled_button_tag t(:button_save), class: '-highlight -with-icon icon-checkmark' %>
<% end %>

@ -65,11 +65,9 @@ See COPYRIGHT and LICENSE files for more details.
<% end %>
</li>
<% end %>
<% if Setting.notified_events.include?("wiki_content_added") or Setting.notified_events.include?("wiki_content_updated") %>
<li class="toolbar-item hidden-for-mobile">
<%= watcher_link(@page, User.current) %>
</li>
<% end %>
<% if @content.version != @page.content.version %>
<li class="toolbar-item hidden-for-mobile">
<%= link_to(t(:label_history), {action: 'history', id: @page}, class: 'button icon-wiki') %>

@ -54,24 +54,18 @@ class Mails::MemberJob < ApplicationJob
end
def send_updated_global(current_user, member, member_message)
return if sending_disabled?(:updated, member_message)
MemberMailer
.updated_global(current_user, member, member_message)
.deliver_now
end
def send_added_project(current_user, member, member_message)
return if sending_disabled?(:added, member_message)
MemberMailer
.added_project(current_user, member, member_message)
.deliver_now
end
def send_updated_project(current_user, member, member_message)
return if sending_disabled?(:updated, member_message)
MemberMailer
.updated_project(current_user, member, member_message)
.deliver_now
@ -84,8 +78,4 @@ class Mails::MemberJob < ApplicationJob
.includes(:project, :principal, :roles, :member_roles)
.each(&block)
end
def sending_disabled?(setting, message)
message.blank? && !Setting.notified_events.include?("membership_#{setting}")
end
end

@ -2665,7 +2665,6 @@ en:
text_regexp_info: "eg. ^[A-Z0-9]+$"
text_regexp_multiline: 'The regex is applied in a multi-line mode. e.g., ^---\s+'
text_repository_usernames_mapping: "Select or update the OpenProject user mapped to each username found in the repository log.\nUsers with the same OpenProject and repository username or email are automatically mapped."
text_select_notifications: "Select actions for which notifications should be sent."
text_status_changed_by_changeset: "Applied in changeset %{value}."
text_table_difference_description: "In this table the single %{entries} are shown. You can view the difference between any two entries by first selecting the according checkboxes in the table. When clicking on the button below the table the differences are shown."
text_time_logged_by_changeset: "Applied in changeset %{value}."

@ -233,16 +233,6 @@ user_format:
cross_project_work_package_relations:
default: 1
format: boolean
notified_events:
serialized: true
default:
- news_added
- news_comment_added
- message_posted
- wiki_content_added
- wiki_content_updated
- membership_added
- membership_updated
mail_handler_body_delimiters:
default: ''
mail_handler_ignore_filenames:

@ -24,7 +24,6 @@ import {
} from 'core-app/features/user-preferences/reminder-settings/email-alerts/email-alerts-settings.component';
import { UntilDestroyedMixin } from 'core-app/shared/helpers/angular/until-destroyed.mixin';
import {
distinctUntilChanged,
filter,
withLatestFrom,
} from 'rxjs/operators';

@ -93,6 +93,7 @@ export class ReminderSettingsDailyTimeComponent implements OnInit {
.get('times') as FormArray)
.valueChanges
.pipe(
startWith(() => this.form.get('times')?.value as FormArray),
map(() => {
const timesArray = this.form.get('times') as FormArray;
const activeTimes = timesArray.controls.map((c) => c.value as string);
@ -191,6 +192,7 @@ export class ReminderSettingsDailyTimeComponent implements OnInit {
);
}
// eslint-disable-next-line class-methods-use-this
isDisabled(time:string, activeTimes:string[]):boolean {
return activeTimes.length === 0 || (activeTimes.length === 1 && activeTimes[0] === time);
}

@ -1,54 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 OpenProject
NOTIFIABLE = [
%w(news_added),
%w(news_comment_added),
%w(message_posted),
%w(wiki_content_added),
%w(wiki_content_updated),
%w(membership_added),
%w(membership_updated)
].freeze
Notifiable = Struct.new(:name) do
def to_s
name
end
# TODO: Plugin API for adding a new notification?
def self.all
OpenProject::NOTIFIABLE.map do |event_strings|
Notifiable.new(*event_strings)
end
end
end
end

@ -108,7 +108,7 @@ class DocumentsController < ApplicationController
model: @document,
args: document_params
if call.success? && Setting.notified_events.include?('document_added')
if call.success?
added = call.result
.attachments
.reject { |a| current_attachments.include?(a.id) }

@ -50,7 +50,7 @@ module Notifications::CreateFromModelService::DocumentStrategy
end
def self.subscribed_users(journal)
User.notified_globally notification_reason(journal)
User.notified_globally subscribed_notification_reason(journal)
end
def self.subscribed_notification_reason(_journal)

@ -29,7 +29,7 @@
module Notifications::MailService::DocumentStrategy
class << self
def send_mail(notification)
return if notification_disabled? || !notification.journal.initial?
return unless notification.journal.initial?
DocumentsMailer
.document_added(
@ -38,11 +38,5 @@ module Notifications::MailService::DocumentStrategy
)
.deliver_later
end
private
def notification_disabled?
Setting.notified_events.exclude?('document_added')
end
end
end

@ -56,7 +56,6 @@ module OpenProject::Documents
activity_provider :documents, class_name: 'Activities::DocumentActivityProvider', default: false
patches %i[CustomFieldsHelper Project]
patch_with_namespace :OpenProject, :Notifiable
add_api_path :documents do
"#{root}/documents"

@ -1,41 +0,0 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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 OpenProject::Documents::Patches::NotifiablePatch
def self.included(base)
class << base
prepend ClassMethods
end
end
module ClassMethods
def all
super + [::OpenProject::Notifiable.new('document_added')]
end
end
end

@ -105,7 +105,6 @@ describe DocumentsController do
before do
ActionMailer::Base.deliveries.clear
allow(Setting).to receive(:notified_events).and_return(Setting.notified_events.dup << 'document_added')
end
it "should create a new document with valid arguments" do

@ -33,7 +33,6 @@ describe 'Upload attachment to documents',
js: true,
with_settings: {
journal_aggregation_time_minutes: 0,
notified_events: %w(document_added)
} do
let!(:user) do
FactoryBot.create :user,

@ -29,9 +29,7 @@
require 'spec_helper'
describe OpenProject::TextFormatting,
'Document links',
# Speeds up the spec by avoiding event mailers to be procssed
with_settings: { notified_events: [] } do
'Document links' do
include ActionView::Helpers::UrlHelper # soft-dependency
include ActionView::Context
include OpenProject::StaticRouting::UrlHelpers

@ -1,39 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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.
#++
require 'spec_helper'
describe OpenProject::Notifiable do
describe '#all' do
it 'includes document_added' do
expect(described_class.all.map(&:name))
.to include('document_added')
end
end
end

@ -76,8 +76,6 @@ describe Notifications::MailService, type: :model do
before do
mail
allow(Setting).to receive(:notified_events).and_return(notification_setting)
end
it 'sends a mail' do
@ -92,17 +90,6 @@ describe Notifications::MailService, type: :model do
.to have_received(:deliver_later)
end
context 'with the event being disabled' do
let(:notification_setting) { %w(wiki_content_updated) }
it 'sends no mail' do
call
expect(DocumentsMailer)
.not_to have_received(:document_added)
end
end
context 'with the notification read in app already' do
let(:read_ian) { true }

@ -29,9 +29,7 @@
require 'spec_helper'
describe OpenProject::TextFormatting,
'Meeting links',
# Speeds up the spec by avoiding event mailers to be procssed
with_settings: { notified_events: [] } do
'Meeting links' do
include ActionView::Helpers::UrlHelper # soft-dependency
include ActionView::Context
include OpenProject::StaticRouting::UrlHelpers

@ -262,44 +262,4 @@ important text</textarea>
it_behaves_like 'labelled'
it_behaves_like 'not wrapped in container'
end
describe '#notification_field' do
before do
allow(Setting).to receive(:notified_events).and_return(%w(interesting_stuff))
end
subject(:output) do
helper.notification_field(notifiable, options)
end
context 'when setting includes option' do
let(:notifiable) { OpenStruct.new(name: 'interesting_stuff') }
it 'should have a label' do
expect(output).to have_selector 'label.form--label-with-check-box', count: 1
end
it_behaves_like 'wrapped in container', 'check-box-container'
it 'should output element' do
expect(output).to have_selector 'input[type="checkbox"].form--check-box'
expect(output).to have_checked_field 'Interesting stuff'
end
end
context 'when setting does not include option' do
let(:notifiable) { OpenStruct.new(name: 'boring_stuff') }
it 'should have a label' do
expect(output).to have_selector 'label.form--label-with-check-box', count: 1
end
it_behaves_like 'wrapped in container', 'check-box-container'
it 'should output element' do
expect(output).to have_selector 'input[type="checkbox"].form--check-box'
expect(output).to have_unchecked_field 'Boring stuff'
end
end
end
end

@ -1,42 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 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.
#++
require 'spec_helper'
describe OpenProject::Notifiable do
describe '#all' do
it 'matches expected list' do
%w(news_added news_comment_added message_posted wiki_content_added
wiki_content_updated membership_added membership_updated).each do |expected|
expect(described_class.all.map(&:name))
.to include(expected)
end
end
end
end

@ -35,7 +35,6 @@ describe MailHandler, type: :model do
let(:priority_low) { FactoryBot.create(:priority_low, is_default: true) }
before do
allow(Setting).to receive(:notified_events).and_return(OpenProject::Notifiable.all.map(&:name))
# we need both of these run first so the anonymous user is created and
# there is a default work package priority to save any work packages
priority_low

@ -109,8 +109,7 @@ describe News, type: :model do
end
end
describe '#save',
with_settings: { notified_events: %w(news_added) } do
describe '#save' do
it 'sends email notifications when created' do
FactoryBot.create(:user,
member_in_project: project,

@ -31,18 +31,22 @@
require 'spec_helper'
describe Setting, type: :model do
after do
described_class.destroy_all
end
# OpenProject specific defaults that are set in settings.yml
describe "OpenProject's default settings" do
it 'has OpenProject as application title' do
expect(Setting.app_title).to eq 'OpenProject'
expect(described_class.app_title).to eq 'OpenProject'
end
it 'allows users to register themselves' do
expect(Setting.self_registration?).to be_truthy
expect(described_class).to be_self_registration
end
it 'allows anonymous users to access public information' do
expect(Setting.login_required?).to be_falsey
expect(described_class).to be_login_required
end
end
@ -50,65 +54,65 @@ describe Setting, type: :model do
describe 'changing a setting' do
context "setting doesn't exist in the database" do
before do
Setting.host_name = 'some name'
described_class.host_name = 'some name'
end
it 'sets the setting' do
expect(Setting.host_name).to eq 'some name'
after do
described_class.find_by(name: 'host_name').destroy
end
it 'stores the setting' do
expect(Setting.find_by(name: 'host_name').value).to eq 'some name'
it 'sets the setting' do
expect(described_class.host_name).to eq 'some name'
end
after do
Setting.find_by(name: 'host_name').destroy
it 'stores the setting' do
expect(described_class.find_by(name: 'host_name').value).to eq 'some name'
end
end
context 'setting already exist in the database' do
before do
Setting.host_name = 'some name'
Setting.host_name = 'some other name'
described_class.host_name = 'some name'
described_class.host_name = 'some other name'
end
it 'sets the setting' do
expect(Setting.host_name).to eq 'some other name'
expect(described_class.host_name).to eq 'some other name'
end
it 'stores the setting' do
expect(Setting.find_by(name: 'host_name').value).to eq 'some other name'
expect(described_class.find_by(name: 'host_name').value).to eq 'some other name'
end
after do
Setting.find_by(name: 'host_name').destroy
described_class.find_by(name: 'host_name').destroy
end
end
end
describe ".installation_uuid" do
after do
Setting.find_by(name: "installation_uuid")&.destroy
described_class.find_by(name: "installation_uuid")&.destroy
end
it "returns unknown if the settings table isn't available yet" do
allow(Setting)
.to receive(:settings_table_exists_yet?)
.and_return(false)
expect(Setting.installation_uuid).to eq("unknown")
expect(described_class.installation_uuid).to eq("unknown")
end
context "with settings table ready" do
it "resets the value if blank" do
Setting.create!(name: "installation_uuid", value: "")
expect(Setting.installation_uuid).not_to be_blank
described_class.create!(name: "installation_uuid", value: "")
expect(described_class.installation_uuid).not_to be_blank
end
it "returns the existing value if any" do
# can't use with_settings since Setting.installation_uuid has a custom implementation
# can't use with_settings since described_class.installation_uuid has a custom implementation
allow(Setting).to receive(:installation_uuid).and_return "abcd1234"
expect(Setting.installation_uuid).to eq("abcd1234")
expect(described_class.installation_uuid).to eq("abcd1234")
end
context "with no existing value" do
@ -118,16 +122,16 @@ describe Setting, type: :model do
end
it "returns 'test' as the UUID" do
expect(Setting.installation_uuid).to eq("test")
expect(described_class.installation_uuid).to eq("test")
end
end
it "returns a random UUID" do
expect(Rails.env).to receive(:test?).and_return(false)
installation_uuid = Setting.installation_uuid
installation_uuid = described_class.installation_uuid
expect(installation_uuid).not_to eq("test")
expect(installation_uuid.size).to eq(36)
expect(Setting.installation_uuid).to eq(installation_uuid)
expect(described_class.installation_uuid).to eq(installation_uuid)
end
end
end
@ -136,18 +140,18 @@ describe Setting, type: :model do
# Check that when reading certain setting values that they get overwritten if needed.
describe "filter saved settings" do
before do
Setting.work_package_list_default_highlighting_mode = "inline"
described_class.work_package_list_default_highlighting_mode = "inline"
end
describe "with EE token", with_ee: [:conditional_highlighting] do
it "returns the value for 'work_package_list_default_highlighting_mode' without changing it" do
expect(Setting.work_package_list_default_highlighting_mode).to eq("inline")
expect(described_class.work_package_list_default_highlighting_mode).to eq("inline")
end
end
describe "without EE" do
it "return 'none' as 'work_package_list_default_highlighting_mode'" do
expect(Setting.work_package_list_default_highlighting_mode).to eq("none")
expect(described_class.work_package_list_default_highlighting_mode).to eq("none")
end
end
end
@ -155,22 +159,22 @@ describe Setting, type: :model do
# tests the serialization feature to store complex data types like arrays in settings
describe 'serialized settings' do
before do
# note: notified_events is marked as serialized in settings.yml (no type-based automagic here)
Setting.notified_events = ['some_event']
# note: default_projects_modules is marked as serialized in settings.yml (no type-based automagic here)
described_class.default_projects_modules = ['some_input']
end
it 'serializes arrays' do
expect(Setting.notified_events).to eq ['some_event']
expect(Setting.find_by(name: 'notified_events').value).to eq ['some_event']
expect(described_class.default_projects_modules).to eq ['some_input']
expect(described_class.find_by(name: 'default_projects_modules').value).to eq ['some_input']
end
after do
Setting.find_by(name: 'notified_events').destroy
described_class.find_by(name: 'default_projects_modules').destroy
end
end
describe 'caching' do
let(:cache_key) { Setting.send :cache_key }
let(:cache_key) { described_class.send :cache_key }
before do
RequestStore.clear!
@ -196,9 +200,9 @@ describe Setting, type: :model do
expect(Rails.cache.read(cache_key)).to be_nil
# Falls back to default values, but hitting cache
value = Setting.app_title
expect(Setting.app_title).to eq 'OpenProject'
expect(value).to eq(Setting.app_title)
value = described_class.app_title
expect(described_class.app_title).to eq 'OpenProject'
expect(value).to eq(described_class.app_title)
# Settings are empty by default
expect(RequestStore.read(:cached_settings)).to eq({})
@ -206,16 +210,16 @@ describe Setting, type: :model do
end
it 'clears the cache when writing a setting' do
expect(Setting.app_title).to eq 'OpenProject'
expect(described_class.app_title).to eq 'OpenProject'
expect(RequestStore.read(:cached_settings)).to eq({})
new_title = 'OpenProject with changed title'
Setting.app_title = new_title
described_class.app_title = new_title
expect(RequestStore.read(:cached_settings)).to be_nil
expect(Rails.cache.read(cache_key)).to be_nil
expect(Setting.app_title).to eq(new_title)
expect(Setting.count).to eq(1)
expect(described_class.app_title).to eq(new_title)
expect(described_class.count).to eq(1)
expect(RequestStore.read(:cached_settings)).to eq('app_title' => new_title)
end
end
@ -231,17 +235,17 @@ describe Setting, type: :model do
it 'returns the value from the deeper cache' do
expect(RequestStore.read(:cached_settings)).to be_nil
expect(Setting.available_languages).to eq(%w(en de))
expect(described_class.available_languages).to eq(%w(en de))
expect(RequestStore.read(:cached_settings)).to eq(cached_hash)
end
it 'expires the cache when writing a setting' do
Setting.available_languages = %w(en)
described_class.available_languages = %w(en)
expect(RequestStore.read(:cached_settings)).to be_nil
# Creates a new cache key
new_cache_key = Setting.send(:cache_key)
new_cache_key = described_class.send(:cache_key)
new_hash = { 'available_languages' => "---\n- en\n" }
expect(new_cache_key).not_to be eq(cache_key)
@ -250,7 +254,7 @@ describe Setting, type: :model do
expect(Rails.cache.read(cache_key)).to be_nil
expect(Rails.cache.read(new_cache_key)).to be_nil
expect(Setting.available_languages).to eq(%w(en))
expect(described_class.available_languages).to eq(%w(en))
expect(Rails.cache.read(new_cache_key)).to eq(new_hash)
expect(RequestStore.read(:cached_settings)).to eq(new_hash)
end
@ -267,59 +271,55 @@ describe Setting, type: :model do
# registers the dummy callback
before do
Setting.register_callback(:notified_events, &callback)
described_class.register_callback(:default_projects_modules, &callback)
end
it 'calls a callback when a setting is set' do
Setting.notified_events = [:some_event]
described_class.default_projects_modules = [:some_value]
expect(collector).not_to be_empty
end
it 'calls no callback on invalid setting' do
allow_any_instance_of(Setting).to receive(:valid?).and_return(false)
Setting.notified_events = 'invalid'
described_class.default_projects_modules = 'invalid'
expect(collector).to be_empty
end
it 'calls multiple callbacks when a setting is set' do
Setting.register_callback(:notified_events, &callback)
Setting.notified_events = [:some_event]
described_class.register_callback(:default_projects_modules, &callback)
described_class.default_projects_modules = [:some_value]
expect(collector.size).to eq 2
end
it 'calls callbacks every time a setting is set' do
Setting.notified_events = [:some_event]
Setting.notified_events = [:some_event]
described_class.default_projects_modules = [:some_value]
described_class.default_projects_modules = [:some_value]
expect(collector.size).to eq 2
end
it 'calls only the callbacks belonging to the changed setting' do
Setting.register_callback(:host_name, &callback)
Setting.notified_events = [:some_event]
described_class.register_callback(:host_name, &callback)
described_class.default_projects_modules = [:some_value]
expect(collector.size).to eq 1
end
it 'attaches to the right setting by passing a string' do
Setting.register_callback('app_title', &callback)
Setting.app_title = 'some title'
described_class.register_callback('app_title', &callback)
described_class.app_title = 'some title'
expect(collector).not_to be_empty
end
it 'passes the new setting value to the callback' do
Setting.notified_events = [:some_event]
expect(collector).to include [:some_event]
described_class.default_projects_modules = [:some_value]
expect(collector).to include [:some_value]
end
it 'optionally passes the old setting value to the callback as the second argument' do
Setting.host_name = 'some name' # set old value
described_class.host_name = 'some name' # set old value
cb = lambda { |args| collector << args[:old_value] }
Setting.register_callback(:host_name, &cb)
Setting.host_name = 'some other name'
described_class.register_callback(:host_name, &cb)
described_class.host_name = 'some other name'
expect(collector).to include 'some name'
end
after do
Setting.destroy_all
end
end
end

@ -63,8 +63,7 @@ describe WikiContent, type: :model do
describe '#save (create)' do
let(:content) { FactoryBot.build(:wiki_content, page: page) }
it 'sends mails to the wiki`s watchers and project all watchers',
with_settings: { notified_events: ['wiki_content_added'] } do
it 'sends mails to the wiki`s watchers and project all watchers' do
wiki_watcher
project_watcher
@ -80,7 +79,7 @@ describe WikiContent, type: :model do
describe '#save (update)' do
it 'sends mails to the watchers, the wiki`s watchers and project all watchers',
with_settings: { notified_events: ['wiki_content_updated'], journal_aggregation_time_minutes: 0 } do
with_settings: { journal_aggregation_time_minutes: 0 } do
page_watcher
wiki_watcher
project_watcher

@ -79,8 +79,6 @@ describe Notifications::MailService, type: :model do
before do
mail
allow(Setting).to receive(:notified_events).and_return(notification_setting)
end
context 'with the notification being for an initial journal' do
@ -100,18 +98,6 @@ describe Notifications::MailService, type: :model do
end
end
context 'with the notification being for an initial journal but the event is disabled' do
let(:journal_initial) { true }
let(:notification_setting) { %w(wiki_content_updated) }
it 'sends no mail' do
call
expect(UserMailer)
.not_to have_received(:wiki_content_added)
end
end
context 'with the notification being for an update journal' do
let(:journal_initial) { false }
@ -129,18 +115,6 @@ describe Notifications::MailService, type: :model do
end
end
context 'with the notification being for an update journal but the event is disabled' do
let(:journal_initial) { false }
let(:notification_setting) { %w(wiki_content_added) }
it 'sends no mail' do
call
expect(UserMailer)
.not_to have_received(:wiki_content_updated)
end
end
context 'with the notification read in app already' do
let(:read_ian) { true }
@ -170,7 +144,6 @@ describe Notifications::MailService, type: :model do
recipient: recipient,
actor: actor)
end
let(:notification_setting) { %w(news_added) }
let(:mail) do
mail = instance_double(ActionMailer::MessageDelivery)
@ -187,8 +160,6 @@ describe Notifications::MailService, type: :model do
before do
mail
allow(Setting).to receive(:notified_events).and_return(notification_setting)
end
context 'with the notification being for an initial journal' do
@ -208,18 +179,6 @@ describe Notifications::MailService, type: :model do
end
end
context 'with the notification being for an initial journal but the event is disabled' do
let(:journal_initial) { true }
let(:notification_setting) { %w() }
it 'sends no mail' do
call
expect(UserMailer)
.not_to have_received(:news_added)
end
end
# This case should not happen as no notification is created in this case that would
# trigger the NotificationJob. But as this might change, this test case is in place.
context 'with the notification being for an update journal' do
@ -248,7 +207,6 @@ describe Notifications::MailService, type: :model do
actor: actor,
read_ian: read_ian)
end
let(:notification_setting) { %w(message_posted) }
let(:mail) do
mail = instance_double(ActionMailer::MessageDelivery)
@ -264,8 +222,6 @@ describe Notifications::MailService, type: :model do
before do
mail
allow(Setting).to receive(:notified_events).and_return(notification_setting)
end
it 'sends a mail' do
@ -281,17 +237,6 @@ describe Notifications::MailService, type: :model do
.to have_received(:deliver_later)
end
context 'with the event being disabled' do
let(:notification_setting) { %w(wiki_content_updated) }
it 'sends no mail' do
call
expect(UserMailer)
.not_to have_received(:message_posted)
end
end
context 'with the notification read in app already' do
let(:read_ian) { true }

@ -115,23 +115,7 @@ shared_examples 'member job' do
context 'with a global membership' do
let(:project) { nil }
context 'with sending enabled', with_settings: { notified_events: ['membership_updated'] } do
it 'sends mail' do
run_job
expect(MemberMailer)
.to have_received(:updated_global)
.with(current_user, member, message)
end
end
context 'with sending disabled and no message', with_settings: { notified_events: [] } do
let(:message) { '' }
it_behaves_like 'sends no mail'
end
context 'with sending disabled and a message', with_settings: { notified_events: [] } do
context 'with sending enabled' do
it 'sends mail' do
run_job
@ -143,23 +127,7 @@ shared_examples 'member job' do
end
context 'with a user membership' do
context 'with sending enabled', with_settings: { notified_events: %w[membership_updated membership_added] } do
it 'sends mail' do
run_job
expect(MemberMailer)
.to have_received(user_project_mail_method)
.with(current_user, member, message)
end
end
context 'with sending disabled and no message', with_settings: { notified_events: [] } do
let(:message) { '' }
it_behaves_like 'sends no mail'
end
context 'with sending disabled and a message', with_settings: { notified_events: [] } do
context 'with sending enabled' do
it 'sends mail' do
run_job

@ -34,10 +34,6 @@ describe MailHandler, type: :model do
FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
before do
allow(Setting).to receive(:notified_events).and_return(OpenProject::Notifiable.all.map(&:name))
end
it 'should add work package with attributes override' do
issue = submit_email('ticket_with_attributes.eml', allow_override: 'type,category,priority')
assert issue.is_a?(WorkPackage)

Loading…
Cancel
Save