From 2926f6be123161f877d9153f01cf3bf00f19b6b4 Mon Sep 17 00:00:00 2001 From: rhymes Date: Thu, 2 Apr 2020 15:14:10 +0200 Subject: [PATCH] [deploy] Strengthen badge achievement code and fix badge email (#7000) * Add badges and badge achievements to seeds * Strengthen BadgeAchievement code and fix mailer bug * Add indentation --- app/mailers/application_mailer.rb | 1 + app/models/badge_achievement.rb | 23 ++++-- .../notify_mailer/new_badge_email.html.erb | 24 +++--- .../notify_mailer/new_badge_email.text.erb | 8 +- db/seeds.rb | 26 +++++-- spec/mailers/notify_mailer_spec.rb | 78 ++++++++++++++++--- 6 files changed, 123 insertions(+), 37 deletions(-) diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 17b32409a..b9f17a5f9 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -1,5 +1,6 @@ class ApplicationMailer < ActionMailer::Base layout "mailer" + helper ApplicationHelper default( from: -> { "DEV Community <#{SiteConfig.default_site_email}>" }, diff --git a/app/models/badge_achievement.rb b/app/models/badge_achievement.rb index 36a84d129..daabb4657 100644 --- a/app/models/badge_achievement.rb +++ b/app/models/badge_achievement.rb @@ -1,4 +1,7 @@ class BadgeAchievement < ApplicationRecord + CONTEXT_MESSAGE_ALLOWED_TAGS = %w[strong em i b u a code].freeze + CONTEXT_MESSAGE_ALLOWED_ATTRIBUTES = %w[href name].freeze + belongs_to :user belongs_to :badge belongs_to :rewarder, class_name: "User", optional: true @@ -7,30 +10,34 @@ class BadgeAchievement < ApplicationRecord validates :badge_id, uniqueness: { scope: :user_id } + after_create :award_credits after_create_commit :notify_recipient after_create_commit :send_email_notification - after_create :award_credits before_validation :render_rewarding_context_message_html + private + def render_rewarding_context_message_html - return if rewarding_context_message_markdown.blank? + return unless rewarding_context_message_markdown parsed_markdown = MarkdownParser.new(rewarding_context_message_markdown) html = parsed_markdown.finalize - final_html = ActionController::Base.helpers.sanitize html, - tags: %w[strong em i b u a code], - attributes: %w[href name] + final_html = ActionController::Base.helpers.sanitize( + html, + tags: CONTEXT_MESSAGE_ALLOWED_TAGS, + attributes: CONTEXT_MESSAGE_ALLOWED_ATTRIBUTES, + ) + self.rewarding_context_message = final_html end - private - def notify_recipient Notification.send_new_badge_achievement_notification(self) end def send_email_notification - return unless user.class.name == "User" && user.email.present? && user.email_badge_notifications + return unless user.is_a?(User) + return unless user.email && user.email_badge_notifications BadgeAchievements::SendEmailNotificationWorker.perform_async(id) end diff --git a/app/views/mailers/notify_mailer/new_badge_email.html.erb b/app/views/mailers/notify_mailer/new_badge_email.html.erb index f8285278f..e4ec57b61 100644 --- a/app/views/mailers/notify_mailer/new_badge_email.html.erb +++ b/app/views/mailers/notify_mailer/new_badge_email.html.erb @@ -8,23 +8,29 @@

<%= @badge.description %>

+ + <% if @badge_achievement.rewarding_context_message %> +

+ + <%= @badge_achievement.rewarding_context_message.html_safe %> + +

+
+ <% end %> +

- - <%= @badge_achievement.rewarding_context_message.html_safe %> - -

-
-

- " style="font-weight:bold;color:white;background:#4e57ef;padding: 5px 10px;border-radius:3px;text-decoration:none"> + Check out your profile


- You also get 5 new credits to use for community listings
+ You also get 5 new credits to use for community listings
if you have anything you'd like to promote. 🎉

- More information about listings + ">More information about listings

diff --git a/app/views/mailers/notify_mailer/new_badge_email.text.erb b/app/views/mailers/notify_mailer/new_badge_email.text.erb index 606f0dc69..5685532c8 100644 --- a/app/views/mailers/notify_mailer/new_badge_email.text.erb +++ b/app/views/mailers/notify_mailer/new_badge_email.text.erb @@ -4,10 +4,10 @@ Congratulations, <%= @user.name %>! You got the <%= @badge.title %> badge! Be su <%= strip_tags @badge_achievement.rewarding_context_message %> -https://dev.to/<%= @user.username %> +<%= user_url(@user) %> -You also get 5 new credits to use for community listings if you have anything you'd like to promote: https://dev.to/listings +You also get 5 new credits to use for community listings if you have anything you'd like to promote: <%= classified_listings_url %> -To manage your credits: visit: https://dev.to/credits +To manage your credits: visit: <%= credits_url %> -For more information about listings, visit: https://dev.to/about-listings +For more information about listings, visit: <%= app_url("/about-listings") %> diff --git a/db/seeds.rb b/db/seeds.rb index b321ad678..0c7c1d287 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -93,6 +93,8 @@ Organization.find_each do |organization| end end +users_in_random_order = User.order(Arel.sql("RANDOM()")) + ############################################################################## counter += 1 @@ -324,11 +326,21 @@ HtmlVariant.create!( counter += 1 Rails.logger.info "#{counter}. Creating Badges" -Badge.create!( - title: Faker::Lorem.word, - description: Faker::Lorem.sentence, - badge_image: File.open(Rails.root.join("app/assets/images/#{rand(1..40)}.png")), -) +5.times do + Badge.create!( + title: "#{Faker::Lorem.word} #{rand(100)}", + description: Faker::Lorem.sentence, + badge_image: File.open(Rails.root.join("app/assets/images/#{rand(1..40)}.png")), + ) +end + +users_in_random_order.limit(10).each do |user| + user.badge_achievements.create!( + badge: Badge.order(Arel.sql("RANDOM()")).limit(1).take, + rewarding_context_message_markdown: Faker::Markdown.random, + ) +end + ############################################################################## @@ -375,8 +387,8 @@ end counter += 1 Rails.logger.info "#{counter}. Creating Classified Listings" -users = User.order(Arel.sql("RANDOM()")).to_a -users.each { |user| Credit.add_to(user, rand(100)) } +users_in_random_order.each { |user| Credit.add_to(user, rand(100)) } +users = users_in_random_order.to_a listings_categories = ClassifiedListing.categories_available.keys listings_categories.each_with_index do |category, index| diff --git a/spec/mailers/notify_mailer_spec.rb b/spec/mailers/notify_mailer_spec.rb index a8c81d03c..66b5e470c 100644 --- a/spec/mailers/notify_mailer_spec.rb +++ b/spec/mailers/notify_mailer_spec.rb @@ -152,9 +152,9 @@ RSpec.describe NotifyMailer, type: :mailer do def create_badge_achievement(user, badge, rewarder) BadgeAchievement.create( - user_id: user.id, - badge_id: badge.id, - rewarder_id: rewarder.id, + user: user, + badge: badge, + rewarder: rewarder, rewarding_context_message_markdown: "Hello [Yoho](/hey)", ) end @@ -172,14 +172,74 @@ RSpec.describe NotifyMailer, type: :mailer do expect(email.to).to eq([user.email]) end - it "includes the tracking pixel" do - expect(email.html_part.body).to include("open.gif") + context "when rendering the HTML email" do + it "includes the tracking pixel" do + expect(email.html_part.body).to include("open.gif") + end + + it "includes UTM params" do + expect(email.html_part.body).to include(CGI.escape("utm_medium=email")) + expect(email.html_part.body).to include(CGI.escape("utm_source=notify_mailer")) + expect(email.html_part.body).to include(CGI.escape("utm_campaign=new_badge_email")) + end + + it "includes the user URL" do + expect(email.html_part.body).to include(CGI.escape(URL.user(user))) + end + + it "includes the listings URL" do + expect(email.html_part.body).to include( + CGI.escape( + Rails.application.routes.url_helpers.classified_listings_url, + ), + ) + end + + it "includes the about listings URL" do + expect(email.html_part.body).to include( + CGI.escape(URL.url("/about-listings")), + ) + end + + it "includes the rewarding_context_message in the email" do + expect(email.html_part.body).to include("Hello