Automated First Post Badge (#20600)

* award first post logic, schedule, and tests

* award first post logic, schedule, and tests
This commit is contained in:
Philip How 2024-02-08 15:11:40 +00:00 committed by GitHub
parent 07ffb2e3be
commit 55f191a5ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 87 additions and 0 deletions

View file

@ -0,0 +1,21 @@
module Badges
class AwardFirstPost
BADGE_SLUG = "first-post".freeze
def self.call
return unless (badge_id = Badge.id_for_slug(BADGE_SLUG))
Article.joins(:user)
.where("articles.published_at > ?", 1.week.ago)
.where("articles.published_at < ?", 1.hour.ago)
.where(nth_published_by_author: 1)
.where.not(users: { id: User.with_role(:spam).or(User.with_role(:suspended)) })
.find_each do |article|
BadgeAchievement.create(
user_id: article.user_id,
badge_id: badge_id,
)
end
end
end
end

View file

@ -94,6 +94,14 @@ award_thumbs_up_badges:
- ""
- award_thumbs_up
- ""
award_first_post_badges:
description: "Awards First Post badges to users (runs daily at 02:00 UTC) "
cron: "0 2 * * *"
class: "BadgeAchievements::BadgeAwardWorker"
args:
- ""
- award_first_post
- ""
resave_supported_tags:
description: "Resaves supported tags to recalculate scores (runs daily at 00:25 UTC)"
cron: "25 0 * * *"

View file

@ -0,0 +1,58 @@
require "rails_helper"
RSpec.describe Badges::AwardFirstPost do
describe ".call" do
before do
create(:badge, title: "First Post")
end
after do
Timecop.return
end
context "when the article is created outside the award window" do
it "does not award the badge for an article created more than a week ago" do
Timecop.freeze(2.weeks.ago) do
create(:article)
end
Timecop.return
expect { described_class.call }.not_to change(BadgeAchievement, :count)
end
it "does not award the badge for an article created less than an hour ago" do
create(:article)
expect { described_class.call }.not_to change(BadgeAchievement, :count)
end
end
context "when the article is created within the award window" do
it "awards the badge" do
Timecop.freeze(2.days.ago) do
create(:article, user: create(:user))
end
Timecop.return
expect { described_class.call }.to change(BadgeAchievement, :count).by(1)
end
end
context "when the user has a spam or suspended role" do
it "does not award the badge to a spam user" do
user = create(:user).tap { |u| u.add_role(:spam) }
Timecop.freeze(2.days.ago) do
create(:article, user: user)
end
Timecop.return
expect { described_class.call }.not_to change(BadgeAchievement, :count)
end
it "does not award the badge to a suspended user" do
user = create(:user).tap { |u| u.add_role(:suspended) }
Timecop.freeze(2.days.ago) do
create(:article, user: user)
end
Timecop.return
expect { described_class.call }.not_to change(BadgeAchievement, :count)
end
end
end
end