From bef15a0f91ee82815bc1a79e2608201fcd83c2ca Mon Sep 17 00:00:00 2001 From: Felipe Artur <felipefac@gmail.com> Date: Tue, 14 Jun 2016 10:17:00 -0300 Subject: [PATCH] Refactor custom notifications controller code and add specs --- CHANGELOG | 2 +- .../notification_settings_controller.rb | 19 ++++---------- app/models/notification_setting.rb | 13 ++++++++-- app/services/notification_service.rb | 3 ++- .../projects/_custom_notifications.html.haml | 4 +-- .../notification_settings_controller_spec.rb | 19 ++++++++++++++ spec/models/notification_setting_spec.rb | 25 +++++++++++++++++++ 7 files changed, 65 insertions(+), 20 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1c73e385bd6..3dfb88f212a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -45,7 +45,7 @@ v 8.9.0 (unreleased) - Remove 'main language' feature - Pipelines can be canceled only when there are running builds - Use downcased path to container repository as this is expected path by Docker - - Custom notification level for projects + - Customized notification settings for projects - Projects pending deletion will render a 404 page - Measure queue duration between gitlab-workhorse and Rails - Make Omniauth providers specs to not modify global configuration diff --git a/app/controllers/projects/notification_settings_controller.rb b/app/controllers/projects/notification_settings_controller.rb index 13b38501ae4..05fe5accc65 100644 --- a/app/controllers/projects/notification_settings_controller.rb +++ b/app/controllers/projects/notification_settings_controller.rb @@ -3,28 +3,19 @@ class Projects::NotificationSettingsController < Projects::ApplicationController def update @notification_setting = current_user.notification_settings_for(project) - - if params[:custom_events].nil? - saved = @notification_setting.update_attributes(notification_setting_params) - else - events = params[:events] || {} - - NotificationSetting::EMAIL_EVENTS.each do |event| - @notification_setting.events[event] = events[event] - end - - saved = @notification_setting.save - end + saved = @notification_setting.update_attributes(notification_setting_params) render json: { html: view_to_html_string("projects/buttons/_notifications", locals: { project: @project, notification_setting: @notification_setting }), - saved: saved, + saved: saved } end private def notification_setting_params - params.require(:notification_setting).permit(:level) + allowed_fields = NotificationSetting::EMAIL_EVENTS.dup + allowed_fields << :level + params.require(:notification_setting).permit(allowed_fields) end end diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb index f41b011c0ae..43acb4c5a7b 100644 --- a/app/models/notification_setting.rb +++ b/app/models/notification_setting.rb @@ -31,6 +31,7 @@ class NotificationSetting < ActiveRecord::Base store :events, accessors: EMAIL_EVENTS, coder: JSON before_save :set_events + before_save :events_to_boolean def self.find_or_create_for(source) setting = find_or_initialize_by(source: source) @@ -42,12 +43,20 @@ class NotificationSetting < ActiveRecord::Base setting end - # Set all event attributes to false when level is not custom or being initialized + # Set all event attributes to false when level is not custom or being initialized for UX reasons def set_events - return if self.custom? || self.persisted? + return if custom? || persisted? EMAIL_EVENTS.each do |event| events[event] = false end end + + # Validates store accessors values as boolean + # It is a text field so it does not cast correct boolean values in JSON + def events_to_boolean + EMAIL_EVENTS.each do |event| + events[event] = ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(events[event]) + end + end end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 841912b72c5..369bc874843 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -524,7 +524,8 @@ class NotificationService end end - # Builds key to be used if user has custom notification setting + # Build event key to search on custom notification level + # Check NotificationSetting::EMAIL_EVENTS def build_custom_key(action, object) "#{action}_#{object.class.name.underscore}".to_sym end diff --git a/app/views/shared/projects/_custom_notifications.html.haml b/app/views/shared/projects/_custom_notifications.html.haml index 8569c523ef4..4e446fe2d10 100644 --- a/app/views/shared/projects/_custom_notifications.html.haml +++ b/app/views/shared/projects/_custom_notifications.html.haml @@ -9,7 +9,6 @@ .modal-body .container-fluid = form_for @notification_setting, url: namespace_project_notification_setting_path(@project.namespace.becomes(Namespace), @project), method: :patch, html: { class: "custom-notifications-form" } do |f| - = hidden_field_tag "custom_events", "true" = f.hidden_field :level .row .col-lg-3 @@ -21,7 +20,8 @@ .form-group .checkbox{ class: ("prepend-top-0" if index == 0) } %label{ for: "events_#{event}" } - = check_box_tag "events[#{event}]", true, @notification_setting.events[event], id: "events_#{event}", class: "js-custom-notification-event" + = check_box("notification_setting", event, {id: "events_#{event}", class: "js-custom-notification-event"}) + %strong = event.to_s.humanize = icon("spinner spin", class: "custom-notification-event-loading") diff --git a/spec/controllers/projects/notification_settings_controller_spec.rb b/spec/controllers/projects/notification_settings_controller_spec.rb index c5d17d97ec9..a726f70a64a 100644 --- a/spec/controllers/projects/notification_settings_controller_spec.rb +++ b/spec/controllers/projects/notification_settings_controller_spec.rb @@ -33,6 +33,25 @@ describe Projects::NotificationSettingsController do expect(response.status).to eq 200 end + + context 'and setting custom notification setting' do + let(:custom_events) do + events = {} + + NotificationSetting::EMAIL_EVENTS.each do |event| + events[event] = "true" + end + end + + it 'returns success' do + put :update, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + notification_setting: { level: :participating, events: custom_events } + + expect(response.status).to eq 200 + end + end end context 'not authorized' do diff --git a/spec/models/notification_setting_spec.rb b/spec/models/notification_setting_spec.rb index 4e24e89b008..df336a6effe 100644 --- a/spec/models/notification_setting_spec.rb +++ b/spec/models/notification_setting_spec.rb @@ -12,5 +12,30 @@ RSpec.describe NotificationSetting, type: :model do it { is_expected.to validate_presence_of(:user) } it { is_expected.to validate_presence_of(:level) } it { is_expected.to validate_uniqueness_of(:user_id).scoped_to([:source_id, :source_type]).with_message(/already exists in source/) } + + context "events" do + let(:user) { create(:user) } + let(:notification_setting) { NotificationSetting.new(source_id: 1, source_type: 'Project', user_id: user.id) } + + before do + notification_setting.level = "custom" + notification_setting.new_note = "true" + notification_setting.new_issue = 1 + notification_setting.close_issue = "1" + notification_setting.merge_merge_request = "t" + notification_setting.close_merge_request = "nil" + notification_setting.reopen_merge_request = "false" + notification_setting.save + end + + it "parses boolean before saving" do + expect(notification_setting.new_note).to eq(true) + expect(notification_setting.new_issue).to eq(true) + expect(notification_setting.close_issue).to eq(true) + expect(notification_setting.merge_merge_request).to eq(true) + expect(notification_setting.close_merge_request).to eq(false) + expect(notification_setting.reopen_merge_request).to eq(false) + end + end end end -- 2.30.9