Split BadgeRewarder into multiple services (#11902)
This commit is contained in:
parent
01f7dbd24f
commit
63cf95d811
32 changed files with 616 additions and 421 deletions
|
|
@ -1,151 +0,0 @@
|
|||
module BadgeRewarder
|
||||
YEARS = { 1 => "one", 2 => "two", 3 => "three", 4 => "four", 5 => "five", 6 => "six", 7 => "seven" }.freeze
|
||||
REPOSITORIES = [
|
||||
"forem/forem",
|
||||
"forem/forem-browser-extension",
|
||||
"thepracticaldev/DEV-Android",
|
||||
"thepracticaldev/DEV-ios",
|
||||
].freeze
|
||||
|
||||
LONGEST_STREAK_WEEKS = 16
|
||||
LONGEST_STREAK_MESSAGE = "16 weeks! You've achieved the longest writing " \
|
||||
"streak possible. This makes you eligible for special quests in the future. Keep up the amazing contributions to" \
|
||||
" our community!".freeze
|
||||
|
||||
MINIMUM_QUALITY = -25
|
||||
|
||||
def self.award_yearly_club_badges
|
||||
total_years = Time.current.year - SiteConfig.community_copyright_start_year.to_i
|
||||
(1..total_years).each do |i|
|
||||
message = "Happy #{SiteConfig.community_name} birthday! " \
|
||||
"Can you believe it's been #{i} #{'year'.pluralize(i)} already?!"
|
||||
badge = Badge.find_by(slug: "#{YEARS[i]}-year-club")
|
||||
next unless badge
|
||||
|
||||
User.registered.where("created_at < ? AND created_at > ?", i.year.ago, i.year.ago - 2.days).find_each do |user|
|
||||
achievement = BadgeAchievement.create(
|
||||
user_id: user.id,
|
||||
badge_id: badge.id,
|
||||
rewarding_context_message_markdown: message,
|
||||
)
|
||||
user.save if achievement.valid?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.award_beloved_comment_badges(comment_count = 24)
|
||||
badge_id = Badge.find_by(slug: "beloved-comment")&.id
|
||||
return unless badge_id
|
||||
|
||||
Comment.includes(:user).where("public_reactions_count > ?", comment_count).find_each do |comment|
|
||||
message = "You're famous! [This is the comment](#{URL.comment(comment)}) for which you are being recognized. 😄"
|
||||
achievement = BadgeAchievement.create(
|
||||
user_id: comment.user_id,
|
||||
badge_id: badge_id,
|
||||
rewarding_context_message_markdown: message,
|
||||
)
|
||||
comment.user.save if achievement.valid?
|
||||
end
|
||||
end
|
||||
|
||||
def self.award_top_seven_badges(usernames, message_markdown = "Congrats!!!")
|
||||
award_badges(usernames, "top-7", message_markdown)
|
||||
end
|
||||
|
||||
def self.award_fab_five_badges(usernames, message_markdown = "Congrats!!!")
|
||||
award_badges(usernames, "fab-5", message_markdown)
|
||||
end
|
||||
|
||||
def self.award_contributor_badges(usernames, message_markdown = "Thank you so much for your contributions!")
|
||||
award_badges(usernames, "dev-contributor", message_markdown)
|
||||
end
|
||||
|
||||
def self.award_tag_badges
|
||||
Tag.where.not(badge_id: nil).find_each do |tag|
|
||||
past_winner_user_ids = BadgeAchievement.where(badge_id: tag.badge_id).pluck(:user_id)
|
||||
winning_article = Article.where("score > 100")
|
||||
.published
|
||||
.where.not(user_id: past_winner_user_ids)
|
||||
.order(score: :desc)
|
||||
.where("published_at > ?", 7.5.days.ago) # More than seven days, to have some wiggle room.
|
||||
.cached_tagged_with(tag).first
|
||||
if winning_article
|
||||
award_badges(
|
||||
[winning_article.user.username],
|
||||
tag.badge.slug,
|
||||
"Congratulations on posting the most beloved [##{tag.name}](#{URL.tag(tag)}) post " \
|
||||
"from the past seven days! " \
|
||||
"Your winning post was [#{winning_article.title}](#{URL.article(winning_article)}). " \
|
||||
"(You can only win once per badge-eligible tag)",
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.award_contributor_badges_from_github(since = 1.day.ago, msg = "Thank you so much for your contributions!")
|
||||
badge = Badge.find_by(slug: "dev-contributor")
|
||||
return unless badge
|
||||
|
||||
REPOSITORIES.each do |repo|
|
||||
commits = Github::OauthClient.new.commits(repo, since: since.utc.iso8601)
|
||||
|
||||
authors_uids = commits.map { |commit| commit.author.id }
|
||||
Identity.github.where(uid: authors_uids).find_each do |i|
|
||||
BadgeAchievement.where(user_id: i.user_id, badge_id: badge.id).first_or_create(
|
||||
rewarding_context_message_markdown: msg,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.award_four_week_streak_badge
|
||||
award_streak_badge(4)
|
||||
end
|
||||
|
||||
def self.award_eight_week_streak_badge
|
||||
award_streak_badge(8)
|
||||
end
|
||||
|
||||
def self.award_sixteen_week_streak_badge
|
||||
award_streak_badge(16)
|
||||
end
|
||||
|
||||
def self.award_streak_badge(num_weeks)
|
||||
# No credit for super low quality
|
||||
article_user_ids = Article.published
|
||||
.where("published_at > ? AND score > ?", 1.week.ago, MINIMUM_QUALITY)
|
||||
.pluck(:user_id)
|
||||
message = if num_weeks == LONGEST_STREAK_WEEKS
|
||||
LONGEST_STREAK_MESSAGE
|
||||
else
|
||||
"Congrats on achieving this streak! Consistent writing is hard. " \
|
||||
"The next streak badge you can get is the #{num_weeks * 2} Week Badge. 😉"
|
||||
end
|
||||
users = User.where(id: article_user_ids).where("articles_count >= ?", num_weeks)
|
||||
usernames = []
|
||||
users.find_each do |user|
|
||||
count = 0
|
||||
num_weeks.times do |i|
|
||||
num = i + 1
|
||||
count += 1 if user.articles.published.where("published_at > ? AND published_at < ?", num.weeks.ago,
|
||||
(num - 1).weeks.ago).any?
|
||||
end
|
||||
usernames << user.username if count >= num_weeks
|
||||
end
|
||||
award_badges(usernames, "#{num_weeks}-week-streak", message)
|
||||
end
|
||||
|
||||
def self.award_badges(usernames, slug, message_markdown)
|
||||
badge_id = Badge.find_by(slug: slug)&.id
|
||||
return unless badge_id
|
||||
|
||||
User.registered.where(username: usernames).find_each do |user|
|
||||
BadgeAchievement.create(
|
||||
user_id: user.id,
|
||||
badge_id: badge_id,
|
||||
rewarding_context_message_markdown: message_markdown,
|
||||
)
|
||||
user.save
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -18,6 +18,10 @@ class Badge < ApplicationRecord
|
|||
"/badge/#{slug}"
|
||||
end
|
||||
|
||||
def self.id_for_slug(slug)
|
||||
select(:id).find_by(slug: slug)&.id
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_slug
|
||||
|
|
|
|||
15
app/services/badges/award.rb
Normal file
15
app/services/badges/award.rb
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
module Badges
|
||||
class Award
|
||||
def self.call(user_relation, slug, message_markdown)
|
||||
return unless (badge_id = Badge.id_for_slug(slug))
|
||||
|
||||
user_relation.find_each do |user|
|
||||
achievement = user.badge_achievements.create(
|
||||
badge_id: badge_id,
|
||||
rewarding_context_message_markdown: message_markdown,
|
||||
)
|
||||
user.touch if achievement.persisted?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
38
app/services/badges/award_beloved_comment.rb
Normal file
38
app/services/badges/award_beloved_comment.rb
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
module Badges
|
||||
class AwardBelovedComment
|
||||
BADGE_SLUG = "beloved-comment".freeze
|
||||
|
||||
MESSAGE_TEMPLATE =
|
||||
"You're famous! " \
|
||||
"[This is the comment](%<comment>s) for which you're being recognized. 😄".freeze
|
||||
|
||||
def self.call(comment_count = 25)
|
||||
new(comment_count).call
|
||||
end
|
||||
|
||||
def initialize(comment_count)
|
||||
@comment_count = comment_count
|
||||
end
|
||||
|
||||
def call
|
||||
return unless (badge_id = Badge.id_for_slug(BADGE_SLUG))
|
||||
|
||||
Comment.includes(:user).where(public_reactions_count: comment_count..).find_each do |comment|
|
||||
achievement = BadgeAchievement.create(
|
||||
user_id: comment.user_id,
|
||||
badge_id: badge_id,
|
||||
rewarding_context_message_markdown: generate_message(comment),
|
||||
)
|
||||
comment.user.touch if achievement.valid?
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :comment_count
|
||||
|
||||
def generate_message(comment)
|
||||
format(MESSAGE_TEMPLATE, comment: URL.comment(comment))
|
||||
end
|
||||
end
|
||||
end
|
||||
13
app/services/badges/award_contributor.rb
Normal file
13
app/services/badges/award_contributor.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
module Badges
|
||||
class AwardContributor
|
||||
BADGE_SLUG = "dev-contributor".freeze
|
||||
|
||||
def self.call(usernames, message_markdown = "Thank you so much for your contributions!")
|
||||
::Badges::Award.call(
|
||||
User.where(username: usernames),
|
||||
BADGE_SLUG,
|
||||
message_markdown,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
27
app/services/badges/award_contributor_from_github.rb
Normal file
27
app/services/badges/award_contributor_from_github.rb
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
module Badges
|
||||
class AwardContributorFromGithub
|
||||
BADGE_SLUG = "dev-contributor".freeze
|
||||
|
||||
REPOSITORIES = [
|
||||
"forem/forem",
|
||||
"forem/forem-browser-extension",
|
||||
"forem/DEV-Android",
|
||||
"forem/DEV-ios",
|
||||
].freeze
|
||||
|
||||
def self.call(since = 1.day.ago, msg = "Thank you so much for your contributions!")
|
||||
return unless (badge_id = Badge.id_for_slug(BADGE_SLUG))
|
||||
|
||||
REPOSITORIES.each do |repo|
|
||||
commits = Github::OauthClient.new.commits(repo, since: since.utc.iso8601)
|
||||
|
||||
authors_uids = commits.map { |commit| commit.author.id }
|
||||
Identity.github.where(uid: authors_uids).find_each do |i|
|
||||
BadgeAchievement
|
||||
.where(user_id: i.user_id, badge_id: badge_id)
|
||||
.first_or_create(rewarding_context_message_markdown: msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
7
app/services/badges/award_eight_week_streak.rb
Normal file
7
app/services/badges/award_eight_week_streak.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
module Badges
|
||||
class AwardEightWeekStreak
|
||||
def self.call
|
||||
::Badges::AwardStreak.call(weeks: 8)
|
||||
end
|
||||
end
|
||||
end
|
||||
14
app/services/badges/award_fab_five.rb
Normal file
14
app/services/badges/award_fab_five.rb
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
module Badges
|
||||
class AwardFabFive
|
||||
BADGE_SLUG = "fab-5".freeze
|
||||
DEFAULT_MESSAGE = "Congrats!!!".freeze
|
||||
|
||||
def self.call(usernames, message_markdown = DEFAULT_MESSAGE)
|
||||
::Badges::Award.call(
|
||||
User.where(username: usernames),
|
||||
BADGE_SLUG,
|
||||
message_markdown,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
7
app/services/badges/award_four_week_streak.rb
Normal file
7
app/services/badges/award_four_week_streak.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
module Badges
|
||||
class AwardFourWeekStreak
|
||||
def self.call
|
||||
::Badges::AwardStreak.call(weeks: 4)
|
||||
end
|
||||
end
|
||||
end
|
||||
7
app/services/badges/award_sixteen_week_streak.rb
Normal file
7
app/services/badges/award_sixteen_week_streak.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
module Badges
|
||||
class AwardSixteenWeekStreak
|
||||
def self.call
|
||||
::Badges::AwardStreak.call(weeks: 16)
|
||||
end
|
||||
end
|
||||
end
|
||||
61
app/services/badges/award_streak.rb
Normal file
61
app/services/badges/award_streak.rb
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
module Badges
|
||||
class AwardStreak
|
||||
LONGEST_STREAK_WEEKS = 16
|
||||
LONGEST_STREAK_MESSAGE = "16 weeks! You've achieved the longest writing " \
|
||||
"streak possible. This makes you eligible for special quests in the future. " \
|
||||
"Keep up the amazing contributions to our community!".freeze
|
||||
|
||||
MINIMUM_QUALITY = -25
|
||||
|
||||
MESSAGE_TEMPLATE =
|
||||
"Congrats on achieving this streak! Consistent writing is hard. " \
|
||||
"The next streak badge you can get is the %<weeks>d Week Badge. 😉".freeze
|
||||
|
||||
def self.call(weeks:)
|
||||
new(weeks: weeks).call
|
||||
end
|
||||
|
||||
def initialize(weeks:)
|
||||
@weeks = weeks
|
||||
end
|
||||
|
||||
def call
|
||||
badge_slug = "#{weeks}-week-streak"
|
||||
return unless (badge_id = Badge.id_for_slug(badge_slug))
|
||||
|
||||
users = User.where(id: article_user_ids).where("articles_count >= ?", weeks)
|
||||
|
||||
users.find_each do |user|
|
||||
count = weeks.times.count { |i| published_x_weeks_ago?(user, i + 1) }
|
||||
next unless count >= weeks
|
||||
|
||||
user.badge_achievements.create(
|
||||
badge_id: badge_id,
|
||||
rewarding_context_message_markdown: generate_message,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :weeks
|
||||
|
||||
# No credit for super low quality
|
||||
def article_user_ids
|
||||
Article.published
|
||||
.where("published_at > ? AND score > ?", 1.week.ago, MINIMUM_QUALITY)
|
||||
.pluck(:user_id)
|
||||
end
|
||||
|
||||
def published_x_weeks_ago?(user, num)
|
||||
user.articles.published
|
||||
.where("published_at > ? AND published_at < ?", num.weeks.ago, (num - 1).weeks.ago).any?
|
||||
end
|
||||
|
||||
def generate_message
|
||||
return LONGEST_STREAK_MESSAGE if weeks == LONGEST_STREAK_WEEKS
|
||||
|
||||
format(MESSAGE_TEMPLATE, weeks: weeks * 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
45
app/services/badges/award_tag.rb
Normal file
45
app/services/badges/award_tag.rb
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
module Badges
|
||||
class AwardTag
|
||||
MESSAGE_TEMPLATE =
|
||||
"Congratulations on posting the most beloved [#%<tag_name>s](%<tag_url>s) post " \
|
||||
"from the past seven days! " \
|
||||
"Your winning post was [%<article_title>s](%<article_url>s). " \
|
||||
"(You can only win once per badge-eligible tag)".freeze
|
||||
|
||||
def self.call
|
||||
new.call
|
||||
end
|
||||
|
||||
def call
|
||||
Tag.where.not(badge_id: nil).find_each do |tag|
|
||||
past_winner_user_ids = BadgeAchievement.where(badge_id: tag.badge_id).pluck(:user_id)
|
||||
winning_article = Article.where("score > 100")
|
||||
.published
|
||||
.where.not(user_id: past_winner_user_ids)
|
||||
.order(score: :desc)
|
||||
.where("published_at > ?", 7.5.days.ago) # More than seven days, to have some wiggle room.
|
||||
.cached_tagged_with(tag).first
|
||||
next unless winning_article
|
||||
|
||||
user = winning_article.user
|
||||
achievement = user.badge_achievements.create(
|
||||
badge_id: tag.badge_id,
|
||||
rewarding_context_message_markdown: generate_message(tag, winning_article),
|
||||
)
|
||||
user.touch if achievement.persisted?
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_message(tag, winning_article)
|
||||
format(
|
||||
MESSAGE_TEMPLATE,
|
||||
tag_name: tag.name,
|
||||
tag_url: URL.tag(tag),
|
||||
article_title: winning_article.title,
|
||||
article_url: URL.article(winning_article),
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
14
app/services/badges/award_top_seven.rb
Normal file
14
app/services/badges/award_top_seven.rb
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
module Badges
|
||||
class AwardTopSeven
|
||||
BADGE_SLUG = "top-7".freeze
|
||||
DEFAULT_MESSAGE = "Congrats!!!".freeze
|
||||
|
||||
def self.call(usernames, message_markdown = DEFAULT_MESSAGE)
|
||||
::Badges::Award.call(
|
||||
User.where(username: usernames),
|
||||
BADGE_SLUG,
|
||||
message_markdown,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
38
app/services/badges/award_yearly_club.rb
Normal file
38
app/services/badges/award_yearly_club.rb
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
module Badges
|
||||
class AwardYearlyClub
|
||||
YEARS = {
|
||||
1 => "one",
|
||||
2 => "two",
|
||||
3 => "three",
|
||||
4 => "four",
|
||||
5 => "five",
|
||||
6 => "six",
|
||||
7 => "seven"
|
||||
}.freeze
|
||||
|
||||
MESSAGE_TEMPLATE =
|
||||
"Happy #{SiteConfig.community_name} birthday! " \
|
||||
"Can you believe it's been %<years>d %<noun>s already?!".freeze
|
||||
|
||||
def self.call
|
||||
new.call
|
||||
end
|
||||
|
||||
def call
|
||||
total_years = Time.current.year - SiteConfig.community_copyright_start_year.to_i
|
||||
(1..total_years).each do |i|
|
||||
::Badges::Award.call(
|
||||
User.registered.where(created_at: i.year.ago - 2.days...i.year.ago),
|
||||
"#{YEARS[i]}-year-club",
|
||||
generate_message(i),
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_message(years)
|
||||
format(MESSAGE_TEMPLATE, years: years, noun: "year".pluralize(years))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,10 +5,14 @@ module BadgeAchievements
|
|||
sidekiq_options queue: :high_priority, retry: 10
|
||||
|
||||
def perform(usernames, badge_slug, message)
|
||||
if BadgeRewarder.respond_to?(badge_slug)
|
||||
BadgeRewarder.public_send(badge_slug)
|
||||
if (award_class = "Badges::#{badge_slug.classify}".safe_constantize)
|
||||
award_class.call
|
||||
else
|
||||
BadgeRewarder.award_badges(usernames, badge_slug, message)
|
||||
Badges::Award.call(
|
||||
User.where(username: usernames),
|
||||
badge_slug,
|
||||
message,
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,49 +21,49 @@ award_yearly_club_badges:
|
|||
class: "BadgeAchievements::BadgeAwardWorker"
|
||||
args:
|
||||
- ""
|
||||
- award_yearly_club_badges
|
||||
- award_yearly_club
|
||||
- ""
|
||||
award_beloved_comment_badges:
|
||||
cron: "5 */12 * * *" # 5 min past every 12th hour UTC
|
||||
class: "BadgeAchievements::BadgeAwardWorker"
|
||||
args:
|
||||
- ""
|
||||
- award_beloved_comment_badges
|
||||
- award_beloved_comment
|
||||
- ""
|
||||
award_four_week_streak_badge:
|
||||
cron: "10 */12 * * *" # 10 min past every 12th hour UTC
|
||||
class: "BadgeAchievements::BadgeAwardWorker"
|
||||
args:
|
||||
- ""
|
||||
- award_four_week_streak_badge
|
||||
- award_four_week_streak
|
||||
- ""
|
||||
award_eight_week_streak_badge:
|
||||
cron: "15 */12 * * *" # 15 min past every 12th hour UTC
|
||||
class: "BadgeAchievements::BadgeAwardWorker"
|
||||
args:
|
||||
- ""
|
||||
- award_eight_week_streak_badge
|
||||
- award_eight_week_streak
|
||||
- ""
|
||||
award_sixteen_week_streak_badge:
|
||||
cron: "20 */12 * * *" # 20 min past every 12th hour UTC
|
||||
class: "BadgeAchievements::BadgeAwardWorker"
|
||||
args:
|
||||
- ""
|
||||
- award_sixteen_week_streak_badge
|
||||
- award_sixteen_week_streak
|
||||
- ""
|
||||
award_weekly_tag_badges:
|
||||
cron: "0 11 * * 4" # 11 am UTC every Thursday
|
||||
class: "BadgeAchievements::BadgeAwardWorker"
|
||||
args:
|
||||
- ""
|
||||
- award_tag_badges
|
||||
- award_tag
|
||||
- ""
|
||||
award_contributor_badges_from_github:
|
||||
cron: "20 * * * *" # every hour, 20 min after the hour
|
||||
class: "BadgeAchievements::BadgeAwardWorker"
|
||||
args:
|
||||
- ""
|
||||
- award_contributor_badges_from_github
|
||||
- award_contributor_from_github
|
||||
- ""
|
||||
remove_old_html_variant_data:
|
||||
cron: "10 * * * *" # every hour, 10 min after the hour
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
task :award_top_seven_badges, [:arg1] => :environment do |_t, args|
|
||||
usernames = args[:arg1].split
|
||||
puts "Awarding top-7 badges to #{usernames}"
|
||||
BadgeRewarder.award_top_seven_badges(usernames)
|
||||
Badges::AwardTopSeven.call(usernames)
|
||||
puts "Done!"
|
||||
end
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ end
|
|||
task :award_contributor_badges, [:arg1] => :environment do |_t, args|
|
||||
usernames = args[:arg1].split
|
||||
puts "Awarding dev-contributor badges to #{usernames}"
|
||||
BadgeRewarder.award_contributor_badges(usernames)
|
||||
Badges::AwardContributor.call(usernames)
|
||||
puts "Done!"
|
||||
end
|
||||
|
||||
|
|
@ -18,6 +18,6 @@ end
|
|||
task :award_fab_five_badges, [:arg1] => :environment do |_t, args|
|
||||
usernames = args[:arg1].split
|
||||
puts "Awarding fab 5 badges to #{usernames}"
|
||||
BadgeRewarder.award_fab_five_badges(usernames)
|
||||
Badges::AwardFabFive.call(usernames)
|
||||
puts "Done!"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,249 +0,0 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe BadgeRewarder, type: :labor do
|
||||
describe "::award_yearly_club_badges" do
|
||||
before do
|
||||
stub_const("#{described_class}::YEARS", BadgeRewarder::YEARS.slice(1, 2, 3))
|
||||
allow(ApplicationConfig).to receive(:[])
|
||||
allow(SiteConfig).to receive(:community_copyright_start_year).and_return(3.years.ago.year)
|
||||
create(:badge, title: "one-year-club")
|
||||
create(:badge, title: "two-year-club")
|
||||
create(:badge, title: "three-year-club")
|
||||
create(:badge, title: "heysddssdhey")
|
||||
end
|
||||
|
||||
it "rewards birthday badge to birthday folks who registered a year ago" do
|
||||
user = create(:user, created_at: 366.days.ago)
|
||||
newer_user = create(:user, created_at: 6.days.ago)
|
||||
older_user = create(:user, created_at: 390.days.ago)
|
||||
described_class.award_yearly_club_badges
|
||||
expect(user.badge_achievements.size).to eq(1)
|
||||
expect(newer_user.badge_achievements.size).to eq(0)
|
||||
expect(older_user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
|
||||
it "rewards 2-year birthday badge to birthday folks who registered 2 years ago" do
|
||||
user = create(:user, created_at: 731.days.ago)
|
||||
newer_user = create(:user, created_at: 6.days.ago)
|
||||
older_user = create(:user, created_at: 800.days.ago)
|
||||
described_class.award_yearly_club_badges
|
||||
expect(user.badge_achievements.size).to eq(1)
|
||||
expect(newer_user.badge_achievements.size).to eq(0)
|
||||
expect(older_user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
|
||||
it "rewards 3-year birthday badge to birthday folks who registered 3 years ago" do
|
||||
user = create(:user, created_at: 1096.days.ago)
|
||||
newer_user = create(:user, created_at: 6.days.ago)
|
||||
older_user = create(:user, created_at: 1200.days.ago)
|
||||
described_class.award_yearly_club_badges
|
||||
expect(user.badge_achievements.size).to eq(1)
|
||||
expect(newer_user.badge_achievements.size).to eq(0)
|
||||
expect(older_user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
describe "::award_beloved_comments" do
|
||||
it "rewards beloved comment to folks who have a qualifying comment" do
|
||||
create(:badge, title: "Beloved comment", slug: "beloved-comment")
|
||||
comment = create(:comment, commentable: create(:article))
|
||||
comment.update(public_reactions_count: 30)
|
||||
described_class.award_beloved_comment_badges
|
||||
expect(BadgeAchievement.count).to eq(1)
|
||||
end
|
||||
|
||||
it "does not reward beloved comment to non-qualifying comment" do
|
||||
create(:badge, title: "Beloved comment", slug: "beloved-comment")
|
||||
create(:comment, commentable: create(:article))
|
||||
described_class.award_beloved_comment_badges
|
||||
expect(BadgeAchievement.count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
it "rewards top seven badge to users" do
|
||||
badge = create(:badge, title: "Top 7")
|
||||
user = create(:user)
|
||||
user_other = create(:user)
|
||||
described_class.award_top_seven_badges([user.username, user_other.username])
|
||||
expect(BadgeAchievement.where(badge_id: badge.id).size).to eq(2)
|
||||
end
|
||||
|
||||
it "rewards fab five badge to users" do
|
||||
badge = create(:badge, title: "Fab 5")
|
||||
user = create(:user)
|
||||
user_other = create(:user)
|
||||
described_class.award_fab_five_badges([user.username, user_other.username])
|
||||
expect(BadgeAchievement.where(badge_id: badge.id).size).to eq(2)
|
||||
end
|
||||
|
||||
it "rewards contributor badges" do
|
||||
badge = create(:badge, title: "Dev Contributor")
|
||||
user = create(:user)
|
||||
user_other = create(:user)
|
||||
described_class.award_contributor_badges([user.username, user_other.username])
|
||||
expect(BadgeAchievement.where(badge_id: badge.id).size).to eq(2)
|
||||
end
|
||||
|
||||
describe "::award_four_week_streak_badge" do
|
||||
it "calls award_streak_badge with argument 4" do
|
||||
allow(described_class).to receive(:award_streak_badge)
|
||||
described_class.award_four_week_streak_badge
|
||||
expect(described_class).to have_received(:award_streak_badge).with(4)
|
||||
end
|
||||
end
|
||||
|
||||
describe "::award_eight_week_streak_badge" do
|
||||
it "calls award_streak_badge with argument 8" do
|
||||
allow(described_class).to receive(:award_streak_badge)
|
||||
described_class.award_eight_week_streak_badge
|
||||
expect(described_class).to have_received(:award_streak_badge).with(8)
|
||||
end
|
||||
end
|
||||
|
||||
describe "::award_sixteen_week_streak_badge" do
|
||||
it "calls award_streak_badge with argument 16" do
|
||||
allow(described_class).to receive(:award_streak_badge)
|
||||
described_class.award_sixteen_week_streak_badge
|
||||
expect(described_class).to have_received(:award_streak_badge).with(16)
|
||||
end
|
||||
end
|
||||
|
||||
describe "::award_streak_badge" do
|
||||
it "rewards badge to users with four straight weeks of articles" do
|
||||
create(:badge, title: "4 Week Streak", slug: "4-week-streak")
|
||||
user = create(:user)
|
||||
create(:article, user: user, published: true, published_at: 26.days.ago)
|
||||
create(:article, user: user, published: true, published_at: 19.days.ago)
|
||||
create(:article, user: user, published: true, published_at: 12.days.ago)
|
||||
create(:article, user: user, published: true, published_at: 5.days.ago)
|
||||
described_class.award_streak_badge(4)
|
||||
expect(user.badges.size).to eq(1)
|
||||
end
|
||||
|
||||
it "does not reward the badge to not qualified users" do
|
||||
create(:badge, title: "4 Week Streak", slug: "4-week-streak")
|
||||
user = create(:user)
|
||||
create(:article, user: user, published: true, published_at: 26.days.ago)
|
||||
create(:article, user: user, published: true, published_at: 19.days.ago)
|
||||
create(:article, user: user, published: true, published_at: 5.days.ago)
|
||||
described_class.award_streak_badge(4)
|
||||
expect(user.badges.size).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
describe "::award_contributor_badges_from_github", vcr: true do
|
||||
let(:user) { create(:user, :with_identity, identities: ["github"]) }
|
||||
let(:badge) { create(:badge, title: "DEV Contributor") }
|
||||
|
||||
before do
|
||||
badge
|
||||
omniauth_mock_github_payload
|
||||
|
||||
stub_const("BadgeRewarder::REPOSITORIES", ["rust-lang/rust"])
|
||||
|
||||
user.identities.github.update_all(uid: "3372342")
|
||||
end
|
||||
|
||||
it "awards contributor badge" do
|
||||
expect do
|
||||
Timecop.freeze("2020-05-15T13:49:20Z") do
|
||||
VCR.use_cassette("github_client_commits_contributor_badge") do
|
||||
described_class.award_contributor_badges_from_github
|
||||
end
|
||||
end
|
||||
end.to change(user.badge_achievements, :count).by(1)
|
||||
end
|
||||
|
||||
it "awards contributor badge once" do
|
||||
expect do
|
||||
Timecop.freeze("2020-05-15T13:49:20Z") do
|
||||
VCR.use_cassette("github_client_commits_contributor_badge_twice") do
|
||||
described_class.award_contributor_badges_from_github
|
||||
described_class.award_contributor_badges_from_github
|
||||
end
|
||||
end
|
||||
end.to change(user.badge_achievements, :count).by(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe "::award_tag_badges" do
|
||||
let(:user) { create(:user) }
|
||||
let(:second_user) { create(:user) }
|
||||
let(:third_user) { create(:user) }
|
||||
let(:article) { create(:article, user_id: user.id) }
|
||||
let(:second_article) { create(:article, user_id: second_user.id) }
|
||||
let(:third_article) { create(:article, user_id: third_user.id) }
|
||||
let(:badge) { create(:badge) }
|
||||
let(:tag) { create(:tag, badge_id: badge.id) }
|
||||
|
||||
it "awards badge if qualifying article by score and tagged appropriately" do
|
||||
article.update_columns(cached_tag_list: tag.name, score: 101)
|
||||
described_class.award_tag_badges
|
||||
expect(user.badge_achievements.size).to eq(1)
|
||||
expect(user.badge_achievements.last.badge_id).to eq(badge.id)
|
||||
end
|
||||
|
||||
it "renders html for message" do
|
||||
article.update_columns(cached_tag_list: tag.name, score: 101)
|
||||
described_class.award_tag_badges
|
||||
expect(user.badge_achievements.size).to eq(1)
|
||||
expect(user.badge_achievements.last.rewarding_context_message).to include("<a ")
|
||||
expect(user.badge_achievements.last.rewarding_context_message).to include(ApplicationConfig["APP_DOMAIN"])
|
||||
expect(user.badge_achievements.last.rewarding_context_message).to include(article.title)
|
||||
expect(user.badge_achievements.last.rewarding_context_message).to include(article.path)
|
||||
end
|
||||
|
||||
it "does not award badge if qualifying article by score but not tagged appropriately" do
|
||||
article.update_columns(cached_tag_list: "differenttag", score: 101)
|
||||
described_class.award_tag_badges
|
||||
expect(user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
|
||||
it "does not award badge if qualifying article by score but not from past week" do
|
||||
article.update_columns(published_at: 8.days.ago, cached_tag_list: tag.name, score: 333)
|
||||
described_class.award_tag_badges
|
||||
expect(user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
|
||||
it "does not award badge if tagged appropriately but not published" do
|
||||
article.update_columns(cached_tag_list: tag.name, score: 101, published: false)
|
||||
described_class.award_tag_badges
|
||||
expect(user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
|
||||
it "does not award badge to user who has previously won" do
|
||||
article.update_columns(cached_tag_list: tag.name, score: 201)
|
||||
second_article.update_columns(cached_tag_list: tag.name, score: 150)
|
||||
third_article.update_columns(cached_tag_list: tag.name, score: 120)
|
||||
described_class.award_tag_badges
|
||||
expect(user.reload.badge_achievements.size).to eq(1)
|
||||
expect(second_user.reload.badge_achievements.size).to eq(0)
|
||||
described_class.award_tag_badges
|
||||
expect(user.reload.badge_achievements.size).to eq(1)
|
||||
expect(second_user.reload.badge_achievements.size).to eq(1)
|
||||
expect(third_user.reload.badge_achievements.size).to eq(0)
|
||||
described_class.award_tag_badges
|
||||
expect(user.reload.badge_achievements.size).to eq(1)
|
||||
expect(second_user.reload.badge_achievements.size).to eq(1)
|
||||
expect(third_user.reload.badge_achievements.size).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe "::award_badges" do
|
||||
let!(:badge) { create(:badge, title: "one-year-club") }
|
||||
let(:user) { create(:user) }
|
||||
let(:user2) { create(:user) }
|
||||
|
||||
it "awards badges" do
|
||||
expect do
|
||||
described_class.award_badges([user.username, user2.username], "one-year-club", "Congrats on a badge!")
|
||||
end.to change(BadgeAchievement, :count).by(2)
|
||||
end
|
||||
|
||||
it "creates correct badge acheivements" do
|
||||
described_class.award_badges([user.username, user2.username], "one-year-club", "Congrats on a badge!")
|
||||
expect(user.badge_achievements.pluck(:badge_id)).to eq([badge.id])
|
||||
expect(user2.badge_achievements.pluck(:rewarding_context_message_markdown)).to eq(["Congrats on a badge!"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -18,6 +18,18 @@ RSpec.describe Badge, type: :model do
|
|||
end
|
||||
end
|
||||
|
||||
describe "class methods" do
|
||||
describe ".id_for_slug" do
|
||||
it "returns the id of an existing slug" do
|
||||
expect(described_class.id_for_slug(badge.slug)).to eq badge.id
|
||||
end
|
||||
|
||||
it "returns nil for non-existing slugs" do
|
||||
expect(described_class.id_for_slug("ohnoes")).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when callbacks are triggered after save" do
|
||||
let!(:badge) { create(:badge) }
|
||||
|
||||
|
|
|
|||
24
spec/services/badges/award_beloved_comment_spec.rb
Normal file
24
spec/services/badges/award_beloved_comment_spec.rb
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::AwardBelovedComment, type: :service do
|
||||
let!(:comment) { create(:comment, commentable: create(:article)) }
|
||||
|
||||
before do
|
||||
create(:badge, title: "Beloved comment", slug: "beloved-comment")
|
||||
end
|
||||
|
||||
describe ".call" do
|
||||
it "awards beloved comment to folks who have a qualifying comment" do
|
||||
comment.update(public_reactions_count: 25)
|
||||
expect do
|
||||
described_class.call
|
||||
end.to change(BadgeAchievement, :count).by(1)
|
||||
end
|
||||
|
||||
it "does not reward beloved comment to non-qualifying comment" do
|
||||
expect do
|
||||
described_class.call
|
||||
end.not_to change(BadgeAchievement, :count)
|
||||
end
|
||||
end
|
||||
end
|
||||
36
spec/services/badges/award_contributor_from_github_spec.rb
Normal file
36
spec/services/badges/award_contributor_from_github_spec.rb
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::AwardContributorFromGithub, type: :service, vcr: true do
|
||||
let(:user) { create(:user, :with_identity, identities: ["github"]) }
|
||||
let(:badge) { create(:badge, title: "DEV Contributor") }
|
||||
|
||||
before do
|
||||
badge
|
||||
omniauth_mock_github_payload
|
||||
|
||||
stub_const("#{described_class}::REPOSITORIES", ["rust-lang/rust"])
|
||||
|
||||
user.identities.github.update_all(uid: "3372342")
|
||||
end
|
||||
|
||||
it "awards contributor badge" do
|
||||
expect do
|
||||
Timecop.freeze("2020-05-15T13:49:20Z") do
|
||||
VCR.use_cassette("github_client_commits_contributor_badge") do
|
||||
described_class.call
|
||||
end
|
||||
end
|
||||
end.to change(user.badge_achievements, :count).by(1)
|
||||
end
|
||||
|
||||
it "awards contributor badge once" do
|
||||
expect do
|
||||
Timecop.freeze("2020-05-15T13:49:20Z") do
|
||||
VCR.use_cassette("github_client_commits_contributor_badge_twice") do
|
||||
described_class.call
|
||||
described_class.call
|
||||
end
|
||||
end
|
||||
end.to change(user.badge_achievements, :count).by(1)
|
||||
end
|
||||
end
|
||||
13
spec/services/badges/award_contributor_spec.rb
Normal file
13
spec/services/badges/award_contributor_spec.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::AwardContributor, type: :service do
|
||||
it "awards contributor badge to users" do
|
||||
create(:badge, title: "DEV Contributor")
|
||||
user = create(:user)
|
||||
other_user = create(:user)
|
||||
|
||||
expect do
|
||||
described_class.call([user.username, other_user.username])
|
||||
end.to change(BadgeAchievement, :count).by(2)
|
||||
end
|
||||
end
|
||||
9
spec/services/badges/award_eight_week_streak_spec.rb
Normal file
9
spec/services/badges/award_eight_week_streak_spec.rb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::AwardEightWeekStreak, type: :service do
|
||||
it "calls Badges::AwardStreak with argument 8" do
|
||||
allow(Badges::AwardStreak).to receive(:call)
|
||||
described_class.call
|
||||
expect(Badges::AwardStreak).to have_received(:call).with(weeks: 8)
|
||||
end
|
||||
end
|
||||
13
spec/services/badges/award_fab_five_spec.rb
Normal file
13
spec/services/badges/award_fab_five_spec.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::AwardFabFive, type: :service do
|
||||
it "awards fab five badge to users" do
|
||||
create(:badge, title: "Fab 5")
|
||||
user = create(:user)
|
||||
other_user = create(:user)
|
||||
|
||||
expect do
|
||||
described_class.call([user.username, other_user.username])
|
||||
end.to change(BadgeAchievement, :count).by(2)
|
||||
end
|
||||
end
|
||||
9
spec/services/badges/award_four_week_streak_spec.rb
Normal file
9
spec/services/badges/award_four_week_streak_spec.rb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::AwardFourWeekStreak, type: :service do
|
||||
it "calls Badges::AwardStreak with argument 4" do
|
||||
allow(Badges::AwardStreak).to receive(:call)
|
||||
described_class.call
|
||||
expect(Badges::AwardStreak).to have_received(:call).with(weeks: 4)
|
||||
end
|
||||
end
|
||||
9
spec/services/badges/award_sixteen_week_streak_spec.rb
Normal file
9
spec/services/badges/award_sixteen_week_streak_spec.rb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::AwardSixteenWeekStreak, type: :service do
|
||||
it "calls Badges::AwardStreak with argument 16" do
|
||||
allow(Badges::AwardStreak).to receive(:call)
|
||||
described_class.call
|
||||
expect(Badges::AwardStreak).to have_received(:call).with(weeks: 16)
|
||||
end
|
||||
end
|
||||
22
spec/services/badges/award_spec.rb
Normal file
22
spec/services/badges/award_spec.rb
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::Award, type: :service do
|
||||
describe ".call" do
|
||||
let!(:badge) { create(:badge, title: "one-year-club") }
|
||||
let!(:user) { create(:user) }
|
||||
let!(:user2) { create(:user) }
|
||||
|
||||
it "awards badges" do
|
||||
expect do
|
||||
described_class.call(User.all, "one-year-club", "Congrats on a badge!")
|
||||
end.to change(BadgeAchievement, :count).by(2)
|
||||
end
|
||||
|
||||
it "creates correct badge achievements" do
|
||||
described_class.call(User.all, "one-year-club", "Congrats on a badge!")
|
||||
expect(user.badge_achievements.pluck(:badge_id)).to eq([badge.id])
|
||||
expect(user2.badge_achievements.pluck(:rewarding_context_message_markdown))
|
||||
.to eq(["Congrats on a badge!"])
|
||||
end
|
||||
end
|
||||
end
|
||||
25
spec/services/badges/award_streak_spec.rb
Normal file
25
spec/services/badges/award_streak_spec.rb
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::AwardStreak, type: :service do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
create(:badge, title: "4 Week Streak", slug: "4-week-streak")
|
||||
create(:article, user: user, published: true, published_at: 26.days.ago)
|
||||
create(:article, user: user, published: true, published_at: 19.days.ago)
|
||||
create(:article, user: user, published: true, published_at: 5.days.ago)
|
||||
end
|
||||
|
||||
it "awards badge to users with four straight weeks of articles" do
|
||||
create(:article, user: user, published: true, published_at: 12.days.ago)
|
||||
expect do
|
||||
described_class.call(weeks: 4)
|
||||
end.to change { user.reload.badges.size }.by(1)
|
||||
end
|
||||
|
||||
it "does not award the badge to not qualified users" do
|
||||
expect do
|
||||
described_class.call(weeks: 4)
|
||||
end.not_to change { user.reload.badges.size }
|
||||
end
|
||||
end
|
||||
64
spec/services/badges/award_tag_spec.rb
Normal file
64
spec/services/badges/award_tag_spec.rb
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::AwardTag, type: :service do
|
||||
let(:user) { create(:user) }
|
||||
let(:second_user) { create(:user) }
|
||||
let(:third_user) { create(:user) }
|
||||
let(:article) { create(:article, user_id: user.id) }
|
||||
let(:second_article) { create(:article, user_id: second_user.id) }
|
||||
let(:third_article) { create(:article, user_id: third_user.id) }
|
||||
let(:badge) { create(:badge) }
|
||||
let(:tag) { create(:tag, badge_id: badge.id) }
|
||||
|
||||
it "awards badge if qualifying article by score and tagged appropriately" do
|
||||
article.update_columns(cached_tag_list: tag.name, score: 101)
|
||||
described_class.call
|
||||
expect(user.badge_achievements.size).to eq(1)
|
||||
expect(user.badge_achievements.last.badge_id).to eq(badge.id)
|
||||
end
|
||||
|
||||
it "renders html for message" do
|
||||
article.update_columns(cached_tag_list: tag.name, score: 101)
|
||||
described_class.call
|
||||
expect(user.badge_achievements.size).to eq(1)
|
||||
expect(user.badge_achievements.last.rewarding_context_message).to include("<a ")
|
||||
expect(user.badge_achievements.last.rewarding_context_message).to include(ApplicationConfig["APP_DOMAIN"])
|
||||
expect(user.badge_achievements.last.rewarding_context_message).to include(article.title)
|
||||
expect(user.badge_achievements.last.rewarding_context_message).to include(article.path)
|
||||
end
|
||||
|
||||
it "does not award badge if qualifying article by score but not tagged appropriately" do
|
||||
article.update_columns(cached_tag_list: "differenttag", score: 101)
|
||||
described_class.call
|
||||
expect(user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
|
||||
it "does not award badge if qualifying article by score but not from past week" do
|
||||
article.update_columns(published_at: 8.days.ago, cached_tag_list: tag.name, score: 333)
|
||||
described_class.call
|
||||
expect(user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
|
||||
it "does not award badge if tagged appropriately but not published" do
|
||||
article.update_columns(cached_tag_list: tag.name, score: 101, published: false)
|
||||
described_class.call
|
||||
expect(user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
|
||||
it "does not award badge to user who has previously won" do
|
||||
article.update_columns(cached_tag_list: tag.name, score: 201)
|
||||
second_article.update_columns(cached_tag_list: tag.name, score: 150)
|
||||
third_article.update_columns(cached_tag_list: tag.name, score: 120)
|
||||
described_class.call
|
||||
expect(user.reload.badge_achievements.size).to eq(1)
|
||||
expect(second_user.reload.badge_achievements.size).to eq(0)
|
||||
described_class.call
|
||||
expect(user.reload.badge_achievements.size).to eq(1)
|
||||
expect(second_user.reload.badge_achievements.size).to eq(1)
|
||||
expect(third_user.reload.badge_achievements.size).to eq(0)
|
||||
described_class.call
|
||||
expect(user.reload.badge_achievements.size).to eq(1)
|
||||
expect(second_user.reload.badge_achievements.size).to eq(1)
|
||||
expect(third_user.reload.badge_achievements.size).to eq(1)
|
||||
end
|
||||
end
|
||||
13
spec/services/badges/award_top_seven_spec.rb
Normal file
13
spec/services/badges/award_top_seven_spec.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::AwardTopSeven, type: :service do
|
||||
it "awards top seven badge to users" do
|
||||
create(:badge, title: "Top 7")
|
||||
user = create(:user)
|
||||
other_user = create(:user)
|
||||
|
||||
expect do
|
||||
described_class.call([user.username, other_user.username])
|
||||
end.to change(BadgeAchievement, :count).by(2)
|
||||
end
|
||||
end
|
||||
51
spec/services/badges/award_yearly_club_spec.rb
Normal file
51
spec/services/badges/award_yearly_club_spec.rb
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badges::AwardYearlyClub, type: :service do
|
||||
describe ".call" do
|
||||
before do
|
||||
stub_const("#{described_class}::YEARS", described_class::YEARS.slice(1, 2, 3))
|
||||
allow(ApplicationConfig).to receive(:[])
|
||||
allow(SiteConfig).to receive(:community_copyright_start_year).and_return(3.years.ago.year)
|
||||
create(:badge, title: "one-year-club")
|
||||
create(:badge, title: "two-year-club")
|
||||
create(:badge, title: "three-year-club")
|
||||
create(:badge, title: "heysddssdhey")
|
||||
end
|
||||
|
||||
it "awards birthday badge to birthday folks who registered a year ago" do
|
||||
user = create(:user, created_at: 366.days.ago)
|
||||
newer_user = create(:user, created_at: 6.days.ago)
|
||||
older_user = create(:user, created_at: 390.days.ago)
|
||||
|
||||
described_class.call
|
||||
|
||||
expect(user.badge_achievements.size).to eq(1)
|
||||
expect(newer_user.badge_achievements.size).to eq(0)
|
||||
expect(older_user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
|
||||
it "rewards 2-year birthday badge to birthday folks who registered 2 years ago" do
|
||||
user = create(:user, created_at: 731.days.ago)
|
||||
newer_user = create(:user, created_at: 6.days.ago)
|
||||
older_user = create(:user, created_at: 800.days.ago)
|
||||
|
||||
described_class.call
|
||||
|
||||
expect(user.badge_achievements.size).to eq(1)
|
||||
expect(newer_user.badge_achievements.size).to eq(0)
|
||||
expect(older_user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
|
||||
it "rewards 3-year birthday badge to birthday folks who registered 3 years ago" do
|
||||
user = create(:user, created_at: 1096.days.ago)
|
||||
newer_user = create(:user, created_at: 6.days.ago)
|
||||
older_user = create(:user, created_at: 1200.days.ago)
|
||||
|
||||
described_class.call
|
||||
|
||||
expect(user.badge_achievements.size).to eq(1)
|
||||
expect(newer_user.badge_achievements.size).to eq(0)
|
||||
expect(older_user.badge_achievements.size).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -2,31 +2,32 @@ require "rails_helper"
|
|||
|
||||
RSpec.describe BadgeAchievements::BadgeAwardWorker, type: :worker do
|
||||
let(:worker) { subject }
|
||||
let(:badge_rewarder) { BadgeRewarder }
|
||||
|
||||
# passing in a random badge_achievement_id argument since the worker itself won't be executed
|
||||
include_examples "#enqueues_on_correct_queue", "high_priority", [456]
|
||||
|
||||
describe "#perform_now" do
|
||||
before do
|
||||
allow(badge_rewarder).to receive(:award_badges)
|
||||
allow(Badges::Award).to receive(:call)
|
||||
end
|
||||
|
||||
context "with badge achievement" do
|
||||
it "sends badge email" do
|
||||
worker.perform("jess", "test", "yo")
|
||||
relation = User.none
|
||||
allow(User).to receive(:where).with(username: ["jess"]).and_return(relation)
|
||||
worker.perform(["jess"], "test", "yo")
|
||||
|
||||
expect(badge_rewarder).to have_received(:award_badges).with("jess", "test", "yo")
|
||||
expect(Badges::Award).to have_received(:call).with(relation, "test", "yo")
|
||||
end
|
||||
end
|
||||
|
||||
context "with predefined badge_slug" do
|
||||
it "sends badge email" do
|
||||
allow(badge_rewarder).to receive(:award_yearly_club_badges)
|
||||
worker.perform("", "award_yearly_club_badges", "")
|
||||
allow(Badges::AwardYearlyClub).to receive(:call)
|
||||
worker.perform([], "award_yearly_club", "")
|
||||
|
||||
expect(badge_rewarder).to have_received(:award_yearly_club_badges)
|
||||
expect(badge_rewarder).not_to have_received(:award_badges)
|
||||
expect(Badges::AwardYearlyClub).to have_received(:call)
|
||||
expect(Badges::Award).not_to have_received(:call)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue