discourse/spec/models/user_badge_spec.rb
Alan Guo Xiang Tan 3e4eac0fed
PERF: Enqueue Job::BackfillBadge in Jobs::BadgeGrant (#30945)
This commit updates the `Jobs::BadgeGrant` scheduled job to enqueue on
`Job::BackfillBadge` regular job for each enabled badge on the site.

The rationale for this change is that we started seeing the
`Jobs::BadgeGrant` job taking hours on sites with lots of enabled badges
as well as users because the job was backfilling all enabled badges
serially within the job. This is bad as it means that a `mini_scheduler`
thread is tied up
by this job thus reducing the overall capacity of `mini_scheduler` for
hours.
2025-01-24 09:35:01 +08:00

136 lines
4.0 KiB
Ruby

# frozen_string_literal: true
RSpec.describe UserBadge do
fab!(:badge)
fab!(:user)
describe "Validations" do
let(:subject) { BadgeGranter.grant(badge, user) }
it { is_expected.to validate_presence_of(:badge_id) }
it { is_expected.to validate_presence_of(:user_id) }
it { is_expected.to validate_presence_of(:granted_at) }
it { is_expected.to validate_presence_of(:granted_by) }
it { is_expected.to validate_uniqueness_of(:badge_id).scoped_to(:user_id) }
end
describe "#save" do
it "triggers the 'user_badge_granted' DiscourseEvent" do
user_badge =
UserBadge.new(
badge: badge,
user: user,
granted_at: Time.zone.now,
granted_by: Discourse.system_user,
)
event =
DiscourseEvent.track(:user_badge_granted, args: [badge.id, user.id]) { user_badge.save! }
expect(event).to be_present
end
end
describe "#destroy" do
it "triggers the 'user_badge_revoked' DiscourseEvent" do
user_badge =
UserBadge.create(
badge: badge,
user: user,
granted_at: Time.zone.now,
granted_by: Discourse.system_user,
)
event = DiscourseEvent.track(:user_badge_revoked) { user_badge.destroy! }
expect(event).to be_present
end
end
describe "featured rank" do
fab!(:user)
fab!(:user_badge_tl1) do
UserBadge.create!(
badge_id: Badge::BasicUser,
user: user,
granted_by: Discourse.system_user,
granted_at: Time.now,
)
end
fab!(:user_badge_tl2) do
UserBadge.create!(
badge_id: Badge::Member,
user: user,
granted_by: Discourse.system_user,
granted_at: Time.now,
)
end
fab!(:user_badge_wiki) do
UserBadge.create!(
badge_id: Badge::WikiEditor,
user: user,
granted_by: Discourse.system_user,
granted_at: Time.now,
)
end
fab!(:user_badge_like) do
UserBadge.create!(
badge_id: Badge::FirstLike,
user: user,
granted_by: Discourse.system_user,
granted_at: Time.now,
)
end
it "gives user badges the correct rank" do
expect(user_badge_tl2.reload.featured_rank).to eq(1)
expect(user_badge_wiki.reload.featured_rank).to eq(2)
expect(user_badge_like.reload.featured_rank).to eq(3)
expect(user_badge_tl1.reload.featured_rank).to eq(4) # Previous trust level badges last
end
it "gives duplicate user_badges the same rank" do
ub1 =
UserBadge.create!(
badge_id: Badge::GreatTopic,
user: user,
granted_by: Discourse.system_user,
granted_at: Time.now,
)
ub2 =
UserBadge.create!(
badge_id: Badge::GreatTopic,
user: user,
granted_by: Discourse.system_user,
granted_at: Time.now,
seq: 1,
)
expect(ub1.reload.featured_rank).to eq(2)
expect(ub2.reload.featured_rank).to eq(2)
end
it "skips disabled badges" do
user_badge_wiki.badge.update(enabled: false)
expect(user_badge_tl2.reload.featured_rank).to eq(1)
expect(user_badge_like.reload.featured_rank).to eq(2)
expect(user_badge_tl1.reload.featured_rank).to eq(3) # Previous trust level badges last
expect(user_badge_wiki.reload.featured_rank).to eq(4) # Disabled
end
it "can ensure consistency per user" do
user_badge_tl2.update_column(:featured_rank, 20) # Update without hooks
expect(user_badge_tl2.reload.featured_rank).to eq(20) # Double check
UserBadge.update_featured_ranks!([user.id])
expect(user_badge_tl2.reload.featured_rank).to eq(1)
end
it "can ensure consistency for all users" do
user_badge_tl2.update_column(:featured_rank, 20) # Update without hooks
expect(user_badge_tl2.reload.featured_rank).to eq(20) # Double check
UserBadge.update_featured_ranks!([user.id])
expect(user_badge_tl2.reload.featured_rank).to eq(1)
end
end
end