diff --git a/Gemfile b/Gemfile index 13b5523fa..2f2a23916 100644 --- a/Gemfile +++ b/Gemfile @@ -75,6 +75,7 @@ gem 'validate_url' # Background job processing gem 'sidekiq', '< 6' +gem 'sidekiq-cron', '~> 1.1' # Misc support gems gem 'rails-settings-cached', '~> 0.7.2' diff --git a/Gemfile.lock b/Gemfile.lock index 67f5d223a..8cee5b29a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -141,6 +141,8 @@ GEM errbase (0.1.1) erubi (1.8.0) erubis (2.7.0) + et-orbi (1.2.1) + tzinfo excon (0.64.0) execjs (2.7.0) factory_bot (5.0.2) @@ -157,6 +159,9 @@ GEM font-awesome-rails (4.7.0.5) railties (>= 3.2, < 6.1) formatador (0.2.5) + fugit (1.2.1) + et-orbi (~> 1.1, >= 1.1.8) + raabro (~> 1.1) globalid (0.4.2) activesupport (>= 4.2.0) groupdate (4.1.1) @@ -274,6 +279,7 @@ GEM method_source (~> 0.9.0) public_suffix (3.0.3) puma (3.12.1) + raabro (1.1.6) rack (2.0.7) rack-protection (2.0.5) rack @@ -377,6 +383,9 @@ GEM rack (>= 1.5.0) rack-protection (>= 1.5.0) redis (>= 3.3.5, < 5) + sidekiq-cron (1.1.0) + fugit (~> 1.1) + sidekiq (>= 4.2.1) simple_form (4.1.0) actionpack (>= 5.0) activemodel (>= 5.0) @@ -496,6 +505,7 @@ DEPENDENCIES shoulda (~> 3.5) shoulda-matchers (~> 2.0) sidekiq (< 6) + sidekiq-cron (~> 1.1) simple_form simple_spark simplecov diff --git a/app/assets/javascripts/manage/lib/setupDataTables.js b/app/assets/javascripts/manage/lib/setupDataTables.js index 5781633f7..77f43a776 100644 --- a/app/assets/javascripts/manage/lib/setupDataTables.js +++ b/app/assets/javascripts/manage/lib/setupDataTables.js @@ -39,6 +39,7 @@ var setupDataTables = function() { { orderable: true, data: "email" }, { orderable: true, data: "role" }, { orderable: true, data: "active" }, + { orderable: true, data: "receive_weekly_report" }, { orderable: true, data: "created_at" } ] }); diff --git a/app/controllers/manage/admins_controller.rb b/app/controllers/manage/admins_controller.rb index c854ff729..be37a03de 100644 --- a/app/controllers/manage/admins_controller.rb +++ b/app/controllers/manage/admins_controller.rb @@ -46,7 +46,7 @@ def destroy def user_params params.require(:user).permit( - :email, :password, :password_confirmation, :remember_me, :role, :is_active + :email, :password, :password_confirmation, :remember_me, :role, :is_active, :receive_weekly_report ) end diff --git a/app/controllers/manage/messages_controller.rb b/app/controllers/manage/messages_controller.rb index 909eac07e..33380188c 100644 --- a/app/controllers/manage/messages_controller.rb +++ b/app/controllers/manage/messages_controller.rb @@ -59,14 +59,14 @@ def deliver end def preview - email = Mailer.bulk_message_email(@message.id, current_user.id, nil, true) + email = UserMailer.bulk_message_email(@message.id, current_user.id, nil, true) render html: email.body.raw_source.html_safe end def live_preview body = params[:body] || "" message = Message.new(body: body) - email = Mailer.bulk_message_email(nil, current_user.id, message, true) + email = UserMailer.bulk_message_email(nil, current_user.id, message, true) render html: email.body.raw_source.html_safe end @@ -88,7 +88,7 @@ def template def template_preview body = File.read("app/views/manage/messages/_template_example.html.md") message = Message.new(body: body) - email = Mailer.bulk_message_email(nil, current_user.id, message, true) + email = UserMailer.bulk_message_email(nil, current_user.id, message, true) render html: email.body.raw_source.html_safe end diff --git a/app/datatables/admin_datatable.rb b/app/datatables/admin_datatable.rb index e21fad413..f31a7d6d5 100644 --- a/app/datatables/admin_datatable.rb +++ b/app/datatables/admin_datatable.rb @@ -7,6 +7,7 @@ def view_columns email: { source: "User.email" }, role: { source: "User.role", searchable: false }, active: { source: "User.is_active", searchable: false }, + receive_weekly_report: { source: "User.receive_weekly_report", searchable: false }, created_at: { source: "User.created_at", searchable: false }, } end @@ -20,6 +21,7 @@ def data email: link_to(bold(record.email), manage_admin_path(record)), role: record.role.titleize, active: record.is_active ? 'Active'.html_safe : 'Inactive'.html_safe, + receive_weekly_report: record.receive_weekly_report ? 'Yes'.html_safe : 'No'.html_safe, created_at: display_datetime(record.created_at), } end diff --git a/app/jobs/admin_weekly_report_job.rb b/app/jobs/admin_weekly_report_job.rb new file mode 100644 index 000000000..5c3f7b0c5 --- /dev/null +++ b/app/jobs/admin_weekly_report_job.rb @@ -0,0 +1,11 @@ +class AdminWeeklyReportJob < ApplicationJob + queue_as :default + + def perform + # Queue all eligible users and let the is_active (or other) logic determine if they should really receive it + users = User.where(receive_weekly_report: true) + users.each do |user| + AdminMailer.weekly_report(user.id).deliver_later + end + end +end diff --git a/app/jobs/bulk_message_job.rb b/app/jobs/bulk_message_job.rb index c6479f0f6..2989e6564 100644 --- a/app/jobs/bulk_message_job.rb +++ b/app/jobs/bulk_message_job.rb @@ -9,7 +9,7 @@ def perform(message) recipients = self.class.build_recipients(message.recipients) recipients.each do |recipient| - Mailer.bulk_message_email(message.id, recipient).deliver_later + UserMailer.bulk_message_email(message.id, recipient).deliver_later end message.update_attribute(:delivered_at, Time.now) diff --git a/app/mailers/admin_mailer.rb b/app/mailers/admin_mailer.rb new file mode 100644 index 000000000..2fd2d8bb6 --- /dev/null +++ b/app/mailers/admin_mailer.rb @@ -0,0 +1,53 @@ +class AdminMailer < ApplicationMailer + include Roadie::Rails::Automatic + add_template_helper(HackathonManagerHelper) + + layout "admin_mailer" + + def weekly_report(user_id) + # Don't send emails more than 7 days after event starts + stop_date = Date.parse(HackathonConfig["event_start_date"]) + 7.days + return if Date.today > stop_date + + @user = User.find_by_id(user_id) + + return unless @user.safe_receive_weekly_report + + @period_start = 7.days.ago.at_beginning_of_day + @period_end = 1.day.ago.at_end_of_day + @period = @period_start..@period_end + + @applications = report_metric(Questionnaire, :created_at) + @rsvp_confirmed = report_metric(Questionnaire.where(acc_status: "rsvp_confirmed"), :acc_status_date) + @rsvp_denied = report_metric(Questionnaire.where(acc_status: "rsvp_denied"), :acc_status_date) + + @bus_metrics = BusList.all.map do |bus_list| + { + name: bus_list.name, + total: bus_list.passengers.count, + } + end + + @messages_sent = Message.bulk.where(delivered_at: @period).count + + @new_admissions_metrics = [@applications, @rsvp_confirmed, @rsvp_denied].any? { |x| x[:new].positive? } + @new_communication_metrics = @messages_sent.positive? + + # Don't send email if no new activity + return if !@new_admissions_metrics && !@new_bus_list_metrics && !@new_communication_metrics + + mail( + to: pretty_email(@user.full_name, @user.email), + subject: "Your Weekly Report", + ) + end + + private + + def report_metric(query_base, new_query_field) + { + new: query_base.where(new_query_field => @period).count, + total: query_base.count, + } + end +end diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index e9d2de534..0758f85ae 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -1,4 +1,10 @@ class ApplicationMailer < ActionMailer::Base - default from: -> { HackathonConfig['email_from'] } - layout 'mailer' + default from: -> { HackathonConfig["email_from"] } + layout "user_mailer" + + def pretty_email(name, email) + return email if name.blank? + + "\"#{name}\" <#{email}>" + end end diff --git a/app/mailers/mail_preview.rb b/app/mailers/mail_preview.rb index 294168071..d29bda648 100644 --- a/app/mailers/mail_preview.rb +++ b/app/mailers/mail_preview.rb @@ -2,7 +2,11 @@ class MailPreview < ActionMailer::Preview def bulk_message_email message = Message.first - Mailer.bulk_message_email(message, User.first.id) + UserMailer.bulk_message_email(message, User.first.id) + end + + def admin_weekly_report + AdminMailer.weekly_report(User.first.id) end end end diff --git a/app/mailers/mailer.rb b/app/mailers/user_mailer.rb similarity index 62% rename from app/mailers/mailer.rb rename to app/mailers/user_mailer.rb index 4514b30d4..c13612be3 100644 --- a/app/mailers/mailer.rb +++ b/app/mailers/user_mailer.rb @@ -1,40 +1,30 @@ -class Mailer < ApplicationMailer +class UserMailer < ApplicationMailer include Roadie::Rails::Automatic add_template_helper(HackathonManagerHelper) - default from: -> { HackathonConfig['email_from'] } - def bulk_message_email(message_id, user_id, message = nil, use_examples = false) - @message = message || Message.find_by_id(message_id) - @user = User.find_by_id(user_id) + @message = message || Message.find_by_id(message_id) + @user = User.find_by_id(user_id) @use_examples = use_examples return if @user.blank? || @message.blank? mail( to: pretty_email(@user.full_name, @user.email), - subject: @message.subject + subject: @message.subject, ) end def incomplete_reminder_email(user_id) @user = User.find_by_id(user_id) - return if @user.blank? || @user.admin? || @user.questionnaire || Time.now.to_date > Date.parse(HackathonConfig['last_day_to_apply']) + return if @user.blank? || @user.admin? || @user.questionnaire || Time.now.to_date > Date.parse(HackathonConfig["last_day_to_apply"]) Message.queue_for_trigger("user.24hr_incomplete_application", @user.id) end rescue_from SparkPostRails::DeliveryException do |e| error_codes_to_not_retry = [ - "1902" # Generation rejection + "1902", # Generation rejection ] raise e unless e.blank? || error_codes_to_not_retry.include?(e.service_code) end - - private - - def pretty_email(name, email) - return email if name.blank? - - "\"#{name}\" <#{email}>" - end end diff --git a/app/models/message.rb b/app/models/message.rb index f8b1f7586..cf6fcd1c3 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -171,7 +171,7 @@ def self.for_trigger(trigger) end def self.queue_for_trigger(trigger, user_id) - for_trigger(trigger).map { |message| Mailer.bulk_message_email(message.id, user_id).deliver_later } + for_trigger(trigger).map { |message| UserMailer.bulk_message_email(message.id, user_id).deliver_later } end def self.bulk diff --git a/app/models/user.rb b/app/models/user.rb index 39b018875..7667d98cd 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -32,7 +32,7 @@ def send_devise_notification(notification, *args) def queue_reminder_email return if reminder_sent_at - Mailer.incomplete_reminder_email(id).deliver_later(wait: 1.day) + UserMailer.incomplete_reminder_email(id).deliver_later(wait: 1.day) update_attribute(:reminder_sent_at, Time.now) end @@ -40,6 +40,11 @@ def email=(value) super value.try(:downcase) end + def safe_receive_weekly_report + return false unless is_active + receive_weekly_report + end + def first_name return "" if questionnaire.blank? questionnaire.first_name diff --git a/app/views/admin_mailer/weekly_report.haml b/app/views/admin_mailer/weekly_report.haml new file mode 100644 index 000000000..c5f6bb453 --- /dev/null +++ b/app/views/admin_mailer/weekly_report.haml @@ -0,0 +1,50 @@ +%h1 Your Weekly Report + +%p + For the week of + %strong + = @period_start.strftime("%A, %B %-d") + – + = @period_end.strftime("%A, %B %-d") + +%h2 Admissions + +- if @new_admissions_metrics + %p + 📥  + %strong= @applications[:new] + new applications (#{@applications[:total]} total) + + %p + ✅  + %strong= @rsvp_confirmed[:new] + new RSVP confirmations (#{@rsvp_confirmed[:total]} total) + + %p + ❌  + %strong= @rsvp_denied[:new] + new RSVP denials (#{@rsvp_denied[:total]} total) +- else + %p + %em No change from last week + +%h2 Transportation + +- @bus_metrics.each do |bus_metric| + %p + %u= bus_metric[:name] + %br + 🚌  + %strong= bus_metric[:total] + total passengers + +%h2 Communication + +- if @new_communication_metrics + %p + ✉️  + %strong= @messages_sent + new bulk emails sent out +- else + %p + %em No new bulk emails sent diff --git a/app/views/layouts/admin_mailer.html.erb b/app/views/layouts/admin_mailer.html.erb new file mode 100644 index 000000000..6c7f22dfa --- /dev/null +++ b/app/views/layouts/admin_mailer.html.erb @@ -0,0 +1,341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/user_mailer.html.erb similarity index 100% rename from app/views/layouts/mailer.html.erb rename to app/views/layouts/user_mailer.html.erb diff --git a/app/views/mailer/bulk_message_email.html.erb b/app/views/mailer/bulk_message_email.html.erb deleted file mode 100644 index 0bc64b42b..000000000 --- a/app/views/mailer/bulk_message_email.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= render partial: "mailer/bulk_templates/#{@message.template}" %> diff --git a/app/views/manage/admins/_form.html.haml b/app/views/manage/admins/_form.html.haml index c1ce8c536..6baa82497 100644 --- a/app/views/manage/admins/_form.html.haml +++ b/app/views/manage/admins/_form.html.haml @@ -13,6 +13,7 @@ = f.input :email, input_html: { "data-validate" => "presence" }, required: true = f.input :role, collection: User.roles.to_a.collect{|c| [c[0].titleize, c[0]]}, include_blank: false = f.input :is_active, collection: [['Active', true], ['Inactive', false]], as: :radio_buttons + = f.input :receive_weekly_report, collection: [['Yes', true], ['No', false]], as: :radio_buttons .center = f.button :submit, value: ( @user.new_record? ? 'Create' : 'Save' ), class: 'btn-primary' diff --git a/app/views/manage/admins/index.html.haml b/app/views/manage/admins/index.html.haml index f05befd76..25487b23c 100644 --- a/app/views/manage/admins/index.html.haml +++ b/app/views/manage/admins/index.html.haml @@ -9,5 +9,6 @@ %th Email %th Role %th Login access + %th Weekly report %th Registered on %tbody diff --git a/app/views/manage/admins/show.html.haml b/app/views/manage/admins/show.html.haml index c519781cc..df6a6794e 100644 --- a/app/views/manage/admins/show.html.haml +++ b/app/views/manage/admins/show.html.haml @@ -19,6 +19,18 @@ - else %span.badge.badge-danger Inactive + %p + %b Receive weekly report: + - if @user.receive_weekly_report + %span.badge.badge-success Yes + - if !@user.is_active + %br + %small + %span.fa.fa-info-circle.icon-space-r-half + Will not receive while user is inactive + - else + %span.badge.badge-secondary No + %p %b Registered: = display_datetime(@user.created_at) diff --git a/app/views/user_mailer/bulk_message_email.html.erb b/app/views/user_mailer/bulk_message_email.html.erb new file mode 100644 index 000000000..0e271e552 --- /dev/null +++ b/app/views/user_mailer/bulk_message_email.html.erb @@ -0,0 +1 @@ +<%= render partial: "user_mailer/bulk_templates/#{@message.template}" %> diff --git a/app/views/mailer/bulk_templates/_default.html.erb b/app/views/user_mailer/bulk_templates/_default.html.erb similarity index 100% rename from app/views/mailer/bulk_templates/_default.html.erb rename to app/views/user_mailer/bulk_templates/_default.html.erb diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 1016c0aca..5295a105b 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -263,6 +263,6 @@ # Devise Rails.application.config.to_prepare do - Devise::Mailer.layout "mailer" + Devise::Mailer.layout "user_mailer" end end diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index a94fa19c6..cfd91b1cc 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -7,3 +7,8 @@ config.redis = { url: ENV["REDIS_URL"] } end end + +schedule_file = "config/schedule.yml" +if File.exist?(schedule_file) && Sidekiq.server? + Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file) +end diff --git a/config/locales/en.yml b/config/locales/en.yml index 156d09baf..58d42d539 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -45,6 +45,7 @@ en: user: role: Limited access prevents the admin from adding, modifying, or deleting any records; modifications through the check-in process are allowed. Event tracking limits to only event tracking. is_active: Deactivating a user will prevent them from logging in. Their access will be immediately revoked from the admin and application pages. + receive_weekly_report: A weekly email report on admissions, bus lists, and messages. Only sent when there are weekly updates up until 7 days past the event. Disabled for inactive admins. message: type: Bulk emails are sent once, manually. Automated emails are sent upon a desired trigger/event. name: A friendly name to recognize this email. Applicants won't see this. @@ -52,8 +53,8 @@ en: hackathon_config: registration_is_open: Specify that registration is open. This does not block registration; it only changes messaging around it. event_is_over: Specify that the event is over - last_day_to_apply: "Last date to apply to your hackathon (format: YYYY-MM-DD)" - event_start_date: "Start date of your hackathon (format: YYYY-MM-DD)" + last_day_to_apply: 'Last date to apply to your hackathon (format: YYYY-MM-DD)' + event_start_date: 'Start date of your hackathon (format: YYYY-MM-DD)' auto_late_waitlist: Automatically set application status to "late waitlist" for new applications name: Your hackathon's name diff --git a/config/routes.rb b/config/routes.rb index 7991f4023..85c0b9f62 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,17 +1,18 @@ # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html Rails.application.routes.draw do - require 'sidekiq/web' + require "sidekiq/web" + require "sidekiq/cron/web" devise_for :users, controllers: { registrations: "users/registrations", omniauth_callbacks: "users/omniauth_callbacks" } use_doorkeeper - mount MailPreview => 'mail_view' if Rails.env.development? + mount MailPreview => "mail_view" if Rails.env.development? - root to: 'questionnaires#show' + root to: "questionnaires#show" authenticate :user, ->(u) { u.admin? } do - mount Sidekiq::Web => '/sidekiq' + mount Sidekiq::Web => "/sidekiq" mount Blazer::Engine, at: "blazer" end diff --git a/config/schedule.yml b/config/schedule.yml new file mode 100644 index 000000000..7035ecc3f --- /dev/null +++ b/config/schedule.yml @@ -0,0 +1,3 @@ +admin_weekly_report: + cron: '0 8 * * MON' + class: 'AdminWeeklyReportJob' diff --git a/db/migrate/20190527163723_add_receive_weekly_report_to_users.rb b/db/migrate/20190527163723_add_receive_weekly_report_to_users.rb new file mode 100644 index 000000000..a4c666e3e --- /dev/null +++ b/db/migrate/20190527163723_add_receive_weekly_report_to_users.rb @@ -0,0 +1,5 @@ +class AddReceiveWeeklyReportToUsers < ActiveRecord::Migration[5.2] + def change + add_column :users, :receive_weekly_report, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 5e34327e1..7e1f6475f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_05_22_210338) do +ActiveRecord::Schema.define(version: 2019_05_27_163723) do create_table "active_storage_attachments", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| t.string "name", null: false @@ -38,9 +38,7 @@ t.integer "query_id" t.text "statement" t.string "data_source" - t.timestamp "created_at" - t.index ["query_id"], name: "index_blazer_audits_on_query_id" - t.index ["user_id"], name: "index_blazer_audits_on_user_id" + t.datetime "created_at" end create_table "blazer_checks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| @@ -51,11 +49,9 @@ t.text "emails" t.string "check_type" t.text "message" - t.timestamp "last_run_at" + t.datetime "last_run_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.index ["creator_id"], name: "index_blazer_checks_on_creator_id" - t.index ["query_id"], name: "index_blazer_checks_on_query_id" end create_table "blazer_dashboard_queries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| @@ -64,8 +60,6 @@ t.integer "position" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.index ["dashboard_id"], name: "index_blazer_dashboard_queries_on_dashboard_id" - t.index ["query_id"], name: "index_blazer_dashboard_queries_on_query_id" end create_table "blazer_dashboards", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| @@ -73,7 +67,6 @@ t.text "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.index ["creator_id"], name: "index_blazer_dashboards_on_creator_id" end create_table "blazer_queries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| @@ -84,7 +77,6 @@ t.string "data_source" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.index ["creator_id"], name: "index_blazer_queries_on_creator_id" end create_table "bus_lists", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| @@ -115,9 +107,9 @@ t.string "subject" t.string "recipients" t.text "body" - t.timestamp "queued_at" - t.timestamp "started_at" - t.timestamp "delivered_at" + t.datetime "queued_at" + t.datetime "started_at" + t.datetime "delivered_at" t.datetime "created_at" t.datetime "updated_at" t.string "template", default: "default" @@ -275,6 +267,7 @@ t.datetime "reminder_sent_at" t.integer "role", default: 0 t.boolean "is_active", default: true + t.boolean "receive_weekly_report", default: false t.index ["email"], name: "index_users_on_email", unique: true t.index ["provider"], name: "index_users_on_provider" t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true diff --git a/test/controllers/admin_mailer_test.rb b/test/controllers/admin_mailer_test.rb new file mode 100644 index 000000000..565b63158 --- /dev/null +++ b/test/controllers/admin_mailer_test.rb @@ -0,0 +1,44 @@ +require "test_helper" + +class AdminMailerTest < ActionMailer::TestCase + context "weekly_report" do + setup do + @user = create(:user, email: "test@example.com", receive_weekly_report: true) + # Setup initial data to trigger regular report + HackathonConfig["event_start_date"] = Date.today.to_s + @questionnaire = create(:questionnaire, created_at: 5.days.ago) + end + + should "deliver weekly email report" do + email = AdminMailer.weekly_report(@user.id).deliver_now + + assert_equal ["test@example.com"], email.to + assert_equal "Your Weekly Report", email.subject + assert_match /new application/, email.encoded + end + + should "not send when more than 7 days after event started" do + HackathonConfig["event_start_date"] = 10.days.ago.to_s + email = AdminMailer.weekly_report(@user.id).deliver_now + assert_nil email + end + + should "not send if admin is inactive" do + @user.update_attribute(:is_active, false) + email = AdminMailer.weekly_report(@user.id).deliver_now + assert_nil email + end + + should "not send if admin isn't receiving weekly reports" do + @user.update_attribute(:receive_weekly_report, false) + email = AdminMailer.weekly_report(@user.id).deliver_now + assert_nil email + end + + should "not send if there hasn't been new activity" do + @questionnaire.update_attribute(:created_at, Date.today) + email = AdminMailer.weekly_report(@user.id).deliver_now + assert_nil email + end + end +end diff --git a/test/controllers/mailer_test.rb b/test/controllers/user_mailer_test.rb similarity index 81% rename from test/controllers/mailer_test.rb rename to test/controllers/user_mailer_test.rb index b92ca462f..5b9d237e4 100644 --- a/test/controllers/mailer_test.rb +++ b/test/controllers/user_mailer_test.rb @@ -1,6 +1,6 @@ require "test_helper" -class MailerTest < ActionMailer::TestCase +class UserMailerTest < ActionMailer::TestCase context "upon trigger of a bulk message" do setup do @message = create(:message, subject: "Example Subject", body: "Hello World!") @@ -8,7 +8,7 @@ class MailerTest < ActionMailer::TestCase end should "deliver bulk messages" do - email = Mailer.bulk_message_email(@message.id, @user.id).deliver_now + email = UserMailer.bulk_message_email(@message.id, @user.id).deliver_now assert_equal ["test@example.com"], email.to assert_equal "Example Subject", email.subject @@ -24,7 +24,7 @@ class MailerTest < ActionMailer::TestCase should "queue reminder bulk message" do assert_difference "enqueued_jobs.size", 1 do - Mailer.incomplete_reminder_email(@user.id).deliver_later + UserMailer.incomplete_reminder_email(@user.id).deliver_later end end end @@ -37,7 +37,7 @@ class MailerTest < ActionMailer::TestCase end should "use customized email_from" do - email = Mailer.bulk_message_email(@message.id, @user.id).deliver_now + email = UserMailer.bulk_message_email(@message.id, @user.id).deliver_now assert_equal ["test@custom.example.com"], email.from end diff --git a/test/factories/users.rb b/test/factories/users.rb index 8aa3a7d23..6188b9991 100644 --- a/test/factories/users.rb +++ b/test/factories/users.rb @@ -6,6 +6,7 @@ password { "password" } role { :user } is_active { true } + receive_weekly_report { false } factory :admin do sequence :email do |n| diff --git a/test/jobs/admin_weekly_report_job_test.rb b/test/jobs/admin_weekly_report_job_test.rb new file mode 100644 index 000000000..c8b6007ba --- /dev/null +++ b/test/jobs/admin_weekly_report_job_test.rb @@ -0,0 +1,12 @@ +require "test_helper" + +class AdminWeeklyReportJobTest < ActiveJob::TestCase + should "queue a mailer per recipient" do + create_list(:user, 3, receive_weekly_report: true) + create_list(:user, 2, receive_weekly_report: false) + assert_difference "enqueued_jobs.size", 3 do + worker = AdminWeeklyReportJob.new + worker.perform + end + end +end diff --git a/test/models/message_template_test.rb b/test/models/message_template_test.rb index 9e1da7db1..e60b42ac5 100644 --- a/test/models/message_template_test.rb +++ b/test/models/message_template_test.rb @@ -14,6 +14,8 @@ class MessageTemplateTest < ActiveSupport::TestCase end should "refresh stored instance when calling #load_singleton" do + # Fresh load + instance expiration + MessageTemplate.load_singleton # Mutate the in-memory instance MessageTemplate.instance.html = "foo" assert_equal "foo", MessageTemplate.instance.html @@ -23,6 +25,8 @@ class MessageTemplateTest < ActiveSupport::TestCase end should "refresh singleton after instance has aged" do + # Fresh load + instance expiration + MessageTemplate.load_singleton # Mutate the in-memory instance MessageTemplate.instance.html = "foo" assert_equal "foo", MessageTemplate.instance.html diff --git a/test/models/user_test.rb b/test/models/user_test.rb index 3fa816384..e53b3c53b 100644 --- a/test/models/user_test.rb +++ b/test/models/user_test.rb @@ -104,4 +104,13 @@ class UserTest < ActiveSupport::TestCase create(:user) end end + + context "safe_receive_weekly_report" do + should "return false if user is inactive" do + user = build(:user, is_active: true, receive_weekly_report: true) + assert_equal true, user.safe_receive_weekly_report + user.is_active = false + assert_equal false, user.safe_receive_weekly_report + end + end end diff --git a/vendor/cache/et-orbi-1.2.1.gem b/vendor/cache/et-orbi-1.2.1.gem new file mode 100644 index 000000000..5b1d00ffa Binary files /dev/null and b/vendor/cache/et-orbi-1.2.1.gem differ diff --git a/vendor/cache/fugit-1.2.1.gem b/vendor/cache/fugit-1.2.1.gem new file mode 100644 index 000000000..942ca3ee6 Binary files /dev/null and b/vendor/cache/fugit-1.2.1.gem differ diff --git a/vendor/cache/raabro-1.1.6.gem b/vendor/cache/raabro-1.1.6.gem new file mode 100644 index 000000000..2b57a7be8 Binary files /dev/null and b/vendor/cache/raabro-1.1.6.gem differ diff --git a/vendor/cache/sidekiq-cron-1.1.0.gem b/vendor/cache/sidekiq-cron-1.1.0.gem new file mode 100644 index 000000000..cee69dbb1 Binary files /dev/null and b/vendor/cache/sidekiq-cron-1.1.0.gem differ