<commit_before>require 'rails_helper'

describe BadgeGranter do

  let(:badge) { Fabricate(:badge) }
  let(:user) { Fabricate(:user) }

  describe 'revoke_titles' do
    it 'can correctly revoke titles' do
      badge = Fabricate(:badge, allow_title: true)
      user = Fabricate(:user, title: badge.name)
      user.reload

      user.user_profile.update_column(:badge_granted_title, true)

      BadgeGranter.grant(badge, user)
      BadgeGranter.revoke_ungranted_titles!

      user.reload
      expect(user.title).to eq(badge.name)

      badge.update_column(:allow_title, false)
      BadgeGranter.revoke_ungranted_titles!

      user.reload
      expect(user.title).to eq('')

      user.title = "CEO"
      user.save

      BadgeGranter.revoke_ungranted_titles!

      user.reload
      expect(user.title).to eq("CEO")
    end
  end

  describe 'preview' do
    it 'can correctly preview' do
      Fabricate(:user, email: '<EMAIL>')
      result = BadgeGranter.preview('select id user_id, null post_id, created_at granted_at from users
                                     where email like \'%gmail.com\'', explain: true)
      expect(result[:grant_count]).to eq(1)
      expect(result[:query_plan]).to be_present
    end
  end

  describe 'backfill' do

    it 'has no broken badge queries' do
      Badge.all.each do |b|
        BadgeGranter.backfill(b)
      end
    end

    it 'can backfill the welcome badge' do
      post = Fabricate(:post)
      user2 = Fabricate(:user)
      PostAction.act(user2, post, PostActionType.types[:like])

      UserBadge.destroy_all
      BadgeGranter.backfill(Badge.find(Badge::Welcome))
      BadgeGranter.backfill(Badge.find(Badge::FirstLike))

      b = UserBadge.find_by(user_id: post.user_id)
      expect(b.post_id).to eq(post.id)
      b.badge_id = Badge::Welcome

      b = UserBadge.find_by(user_id: user2.id)
      expect(b.post_id).to eq(post.id)
      b.badge_id = Badge::FirstLike
    end

    it 'should grant missing badges' do
      good_topic = Badge.find(Badge::GoodTopic)

      post = Fabricate(:post, like_count: 30)
      2.times {
        BadgeGranter.backfill(Badge.find(Badge::NiceTopic), post_ids: [post.id])
        BadgeGranter.backfill(good_topic)
      }

      # TODO add welcome
      expect(post.user.user_badges.pluck(:badge_id).sort).to eq([Badge::NiceTopic,Badge::GoodTopic])

      expect(post.user.notifications.count).to eq(2)

      notification = post.user.notifications.last
      data = notification.data_hash
      expect(data["badge_id"]).to eq(good_topic.id)
      expect(data["badge_slug"]).to eq(good_topic.slug)
      expect(data["username"]).to eq(post.user.username)

      expect(Badge.find(Badge::NiceTopic).grant_count).to eq(1)
      expect(Badge.find(Badge::GoodTopic).grant_count).to eq(1)
    end
  end

  describe 'grant' do

    it 'allows overriding of granted_at does not notify old bronze' do
      badge = Fabricate(:badge, badge_type_id: BadgeType::Bronze)
      time = 1.year.ago

      user_badge = BadgeGranter.grant(badge, user, created_at: time)

      expect(user_badge.granted_at).to eq(time)
      expect(Notification.where(user_id: user.id).count).to eq(0)
    end

    it "doesn't grant disabled badges" do
      badge = Fabricate(:badge, badge_type_id: BadgeType::Bronze, enabled: false)<commit_msg>Add specs for localized notifications on backfilled badges<commit_after>require 'rails_helper'

describe BadgeGranter do

  let(:badge) { Fabricate(:badge) }
  let(:user) { Fabricate(:user) }

  describe 'revoke_titles' do
    it 'can correctly revoke titles' do
      badge = Fabricate(:badge, allow_title: true)
      user = Fabricate(:user, title: badge.name)
      user.reload

      user.user_profile.update_column(:badge_granted_title, true)

      BadgeGranter.grant(badge, user)
      BadgeGranter.revoke_ungranted_titles!

      user.reload
      expect(user.title).to eq(badge.name)

      badge.update_column(:allow_title, false)
      BadgeGranter.revoke_ungranted_titles!

      user.reload
      expect(user.title).to eq('')

      user.title = "CEO"
      user.save

      BadgeGranter.revoke_ungranted_titles!

      user.reload
      expect(user.title).to eq("CEO")
    end
  end

  describe 'preview' do
    it 'can correctly preview' do
      Fabricate(:user, email: '<EMAIL>')
      result = BadgeGranter.preview('select id user_id, null post_id, created_at granted_at from users
                                     where email like \'%gmail.com\'', explain: true)
      expect(result[:grant_count]).to eq(1)
      expect(result[:query_plan]).to be_present
    end
  end

  describe 'backfill' do

    it 'has no broken badge queries' do
      Badge.all.each do |b|
        BadgeGranter.backfill(b)
      end
    end

    it 'can backfill the welcome badge' do
      post = Fabricate(:post)
      user2 = Fabricate(:user)
      PostAction.act(user2, post, PostActionType.types[:like])

      UserBadge.destroy_all
      BadgeGranter.backfill(Badge.find(Badge::Welcome))
      BadgeGranter.backfill(Badge.find(Badge::FirstLike))

      b = UserBadge.find_by(user_id: post.user_id)
      expect(b.post_id).to eq(post.id)
      b.badge_id = Badge::Welcome

      b = UserBadge.find_by(user_id: user2.id)
      expect(b.post_id).to eq(post.id)
      b.badge_id = Badge::FirstLike
    end

    it 'should grant missing badges' do
      good_topic = Badge.find(Badge::GoodTopic)

      post = Fabricate(:post, like_count: 30)
      2.times {
        BadgeGranter.backfill(Badge.find(Badge::NiceTopic), post_ids: [post.id])
        BadgeGranter.backfill(good_topic)
      }

      # TODO add welcome
      expect(post.user.user_badges.pluck(:badge_id).sort).to eq([Badge::NiceTopic,Badge::GoodTopic])

      expect(post.user.notifications.count).to eq(2)

      notification = post.user.notifications.last
      data = notification.data_hash
      expect(data["badge_id"]).to eq(good_topic.id)
      expect(data["badge_slug"]).to eq(good_topic.slug)
      expect(data["username"]).to eq(post.user.username)

      expect(Badge.find(Badge::NiceTopic).grant_count).to eq(1)
      expect(Badge.find(Badge::GoodTopic).grant_count).to eq(1)
    end

    it 'should grant badges in the user locale' do

      SiteSetting.allow_user_locale = true

      nice_topic = Badge.find(Badge::NiceTopic)
      name_english = nice_topic.name

      user = Fabricate(:user, locale: 'fr')
      post = Fabricate(:post, like_count: 10, user: user)

      BadgeGranter.backfill(nice_topic)

      notification_badge_name = JSON.parse(post.user.notifications.first.data)['badge_name']

      expect(notification_badge_name).not_to eq(name_english)
    end
  end

  describe 'grant' do

    it 'allows overriding of granted_at does not notify old bronze' do
      badge = Fabricate(:badge, badge_type_id: BadgeType::Bronze)
      time = 1.year.ago

      user_badge = BadgeGranter.grant(badge, user, created_at: time)

      expect(user_badge.granted_at).to eq(time)
      expect(Notification.where(user_id: user.id).count).to eq(0)
    end

    it "doesn't grant disabled badges" do
      badge = Fabricate(:badge, badge_type_id: BadgeType::Bronze, enabled: false)
{'fraction_non_alphanumeric': 0.1145165784341042, 'fraction_numerical': 0.003622178879910839, 'mean_word_length': 3.0929304446978336, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6701391', 'n_tokens_mistral': 2553, 'n_tokens_neox': 2451, 'n_words': 465}