mirror of
https://github.com/discourse/discourse.git
synced 2024-11-30 18:48:33 +08:00
c2332d7505
* FEATURE: reduce avatar sizes to 6 from 20 This PR introduces 3 changes: 1. SiteSetting.avatar_sizes, now does what is says on the tin. previously it would introduce a large number of extra sizes, to allow for various DPIs. Instead we now trust the admin with the size list. 2. When `avatar_sizes` changes, we ensure consistency and remove resized avatars that are not longer allowed per site setting. This happens on the 12 hourly job and limited out of the box to 20k cleanups per cycle, given this may reach out to AWS 20k times to remove things. 3.Our default avatar sizes are now "24|48|72|96|144|288" these sizes were very specifically picked to limit amount of bluriness introduced by webkit. Our avatars are already blurry due to 1px border, so this corrects old blur. This change heavily reduces storage required by forums which simplifies site moves and more. Co-authored-by: David Taylor <david@taylorhq.com>
305 lines
8.7 KiB
Ruby
305 lines
8.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe Badge do
|
|
describe "Validations" do
|
|
subject(:badge) { Fabricate.build(:badge) }
|
|
|
|
it { is_expected.to validate_length_of(:name).is_at_most(100) }
|
|
it { is_expected.to validate_length_of(:description).is_at_most(500) }
|
|
it { is_expected.to validate_length_of(:long_description).is_at_most(1000) }
|
|
it { is_expected.to validate_presence_of(:name) }
|
|
it { is_expected.to validate_presence_of(:badge_type) }
|
|
it { is_expected.to validate_uniqueness_of(:name) }
|
|
end
|
|
|
|
it "has a valid system attribute for new badges" do
|
|
expect(Badge.create!(name: "test", badge_type_id: 1).system?).to be false
|
|
end
|
|
|
|
it "auto translates name" do
|
|
badge = Badge.find_by_name("Basic User")
|
|
name_english = badge.name
|
|
|
|
I18n.with_locale(:fr) { expect(badge.display_name).not_to eq(name_english) }
|
|
end
|
|
|
|
it "handles changes on badge description and long description correctly for system badges" do
|
|
badge = Badge.find_by_name("Basic User")
|
|
badge.description = badge.description.dup
|
|
badge.long_description = badge.long_description.dup
|
|
badge.save
|
|
badge.reload
|
|
|
|
expect(badge[:description]).to eq(nil)
|
|
expect(badge[:long_description]).to eq(nil)
|
|
|
|
badge.description = "testing"
|
|
badge.long_description = "testing it"
|
|
|
|
badge.save
|
|
badge.reload
|
|
|
|
expect(badge[:description]).to eq("testing")
|
|
expect(badge[:long_description]).to eq("testing it")
|
|
end
|
|
|
|
it "can ensure consistency" do
|
|
b = Badge.find_by_name("Basic User")
|
|
|
|
b.grant_count = 100
|
|
b.save
|
|
|
|
UserBadge.create!(
|
|
user_id: User.minimum(:id) - 1,
|
|
badge_id: b.id,
|
|
granted_at: 1.minute.ago,
|
|
granted_by_id: -1,
|
|
)
|
|
UserBadge.create!(
|
|
user_id: User.first.id,
|
|
badge_id: b.id,
|
|
granted_at: 1.minute.ago,
|
|
granted_by_id: -1,
|
|
)
|
|
|
|
Badge.ensure_consistency!
|
|
|
|
b.reload
|
|
expect(b.grant_count).to eq(1)
|
|
end
|
|
|
|
it "sanitizes the description" do
|
|
xss = "<b onmouseover=alert('Wufff!')>click me!</b><script>alert('TEST');</script>"
|
|
badge = Fabricate(:badge)
|
|
|
|
badge.update!(description: xss)
|
|
|
|
expect(badge.description).to eq("<b>click me!</b>alert('TEST');")
|
|
end
|
|
|
|
describe "#manually_grantable?" do
|
|
fab!(:badge) { Fabricate(:badge, name: "Test Badge") }
|
|
subject { badge.manually_grantable? }
|
|
|
|
context "when system badge" do
|
|
before { badge.system = true }
|
|
it { is_expected.to be false }
|
|
end
|
|
|
|
context "when has query" do
|
|
before { badge.query = "SELECT id FROM users" }
|
|
it { is_expected.to be false }
|
|
end
|
|
|
|
context "when neither system nor has query" do
|
|
before { badge.update_columns(system: false, query: nil) }
|
|
it { is_expected.to be true }
|
|
end
|
|
end
|
|
|
|
describe "#image_url" do
|
|
it "has CDN url" do
|
|
SiteSetting.enable_s3_uploads = true
|
|
SiteSetting.s3_cdn_url = "https://some-s3-cdn.amzn.com"
|
|
upload = Fabricate(:upload_s3)
|
|
badge = Fabricate(:badge, image_upload_id: upload.id)
|
|
expect(badge.image_url).to start_with("https://some-s3-cdn.amzn.com")
|
|
end
|
|
end
|
|
|
|
describe ".i18n_name" do
|
|
it "transforms to lower case letters, and replaces spaces with underscores" do
|
|
expect(Badge.i18n_name("Basic User")).to eq("basic_user")
|
|
end
|
|
end
|
|
|
|
describe ".display_name" do
|
|
it "fetches from translations when i18n_name key exists" do
|
|
expect(Badge.display_name("basic_user")).to eq("Basic")
|
|
expect(Badge.display_name("Basic User")).to eq("Basic")
|
|
end
|
|
|
|
it "fallbacks to argument value when translation does not exist" do
|
|
expect(Badge.display_name("Not In Translations")).to eq("Not In Translations")
|
|
end
|
|
end
|
|
|
|
describe ".find_system_badge_id_from_translation_key" do
|
|
let(:translation_key) { "badges.regular.name" }
|
|
|
|
it "uses a translation key to get a system badge id, mainly to find which badge a translation override corresponds to" do
|
|
expect(Badge.find_system_badge_id_from_translation_key(translation_key)).to eq(Badge::Regular)
|
|
end
|
|
|
|
context "when the translation key is snake case" do
|
|
let(:translation_key) { "badges.crazy_in_love.name" }
|
|
|
|
it "works to get the badge" do
|
|
expect(Badge.find_system_badge_id_from_translation_key(translation_key)).to eq(
|
|
Badge::CrazyInLove,
|
|
)
|
|
end
|
|
end
|
|
|
|
context "when a translation key not for a badge is provided" do
|
|
let(:translation_key) { "reports.flags.title" }
|
|
it "returns nil" do
|
|
expect(Badge.find_system_badge_id_from_translation_key(translation_key)).to eq(nil)
|
|
end
|
|
end
|
|
|
|
context "when translation key doesn't match its class" do
|
|
let(:translation_key) { "badges.licensed.long_description" }
|
|
|
|
it "returns nil" do
|
|
expect(Badge.find_system_badge_id_from_translation_key(translation_key)).to eq(nil)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "First Quote" do
|
|
let(:quoted_post_badge) { Badge.find(Badge::FirstQuote) }
|
|
|
|
it "Awards at the correct award date" do
|
|
freeze_time
|
|
post1 = create_post
|
|
|
|
raw = <<~RAW
|
|
[quote="#{post1.user.username}, post:#{post1.post_number}, topic:#{post1.topic_id}"]
|
|
lorem
|
|
[/quote]
|
|
RAW
|
|
|
|
post2 = create_post(raw: raw)
|
|
|
|
quoted_post = QuotedPost.find_by(post_id: post2.id)
|
|
freeze_time 1.year.from_now
|
|
quoted_post.update!(created_at: Time.now)
|
|
|
|
BadgeGranter.backfill(quoted_post_badge)
|
|
user_badge = post2.user.user_badges.find_by(badge_id: quoted_post_badge.id)
|
|
|
|
expect(user_badge.granted_at).to eq_time(post2.created_at)
|
|
end
|
|
end
|
|
|
|
describe "WikiEditor badge" do
|
|
it "is awarded" do
|
|
wiki_editor_badge = Badge.find(Badge::WikiEditor)
|
|
post = Fabricate(:post, wiki: true)
|
|
revisor = PostRevisor.new(post)
|
|
revisor.revise!(post.user, { raw: "I am editing a wiki" }, force_new_version: true)
|
|
|
|
BadgeGranter.backfill(wiki_editor_badge)
|
|
|
|
expect(UserBadge.where(user_id: post.user.id, badge_id: Badge::WikiEditor).count).to eq(1)
|
|
end
|
|
end
|
|
|
|
describe "PopularLink badge" do
|
|
let(:popular_link_badge) { Badge.find(Badge::PopularLink) }
|
|
|
|
before do
|
|
popular_link_badge.query = BadgeQueries.linking_badge(2)
|
|
popular_link_badge.save!
|
|
end
|
|
|
|
it "is awarded" do
|
|
post = create_post(raw: "https://www.discourse.org/")
|
|
|
|
TopicLinkClick.create_from(
|
|
url: "https://www.discourse.org/",
|
|
post_id: post.id,
|
|
topic_id: post.topic.id,
|
|
ip: "192.168.0.100",
|
|
)
|
|
BadgeGranter.backfill(popular_link_badge)
|
|
expect(UserBadge.where(user_id: post.user.id, badge_id: Badge::PopularLink).count).to eq(0)
|
|
|
|
TopicLinkClick.create_from(
|
|
url: "https://www.discourse.org/",
|
|
post_id: post.id,
|
|
topic_id: post.topic.id,
|
|
ip: "192.168.0.101",
|
|
)
|
|
BadgeGranter.backfill(popular_link_badge)
|
|
expect(UserBadge.where(user_id: post.user.id, badge_id: Badge::PopularLink).count).to eq(1)
|
|
end
|
|
|
|
it "is not awarded for links in a restricted category" do
|
|
category = Fabricate(:category)
|
|
post = create_post(raw: "https://www.discourse.org/", category: category)
|
|
|
|
category.set_permissions({})
|
|
category.save!
|
|
|
|
TopicLinkClick.create_from(
|
|
url: "https://www.discourse.org/",
|
|
post_id: post.id,
|
|
topic_id: post.topic.id,
|
|
ip: "192.168.0.100",
|
|
)
|
|
TopicLinkClick.create_from(
|
|
url: "https://www.discourse.org/",
|
|
post_id: post.id,
|
|
topic_id: post.topic.id,
|
|
ip: "192.168.0.101",
|
|
)
|
|
BadgeGranter.backfill(popular_link_badge)
|
|
expect(UserBadge.where(user_id: post.user.id, badge_id: Badge::PopularLink).count).to eq(0)
|
|
end
|
|
end
|
|
|
|
describe "#seed" do
|
|
let(:badge_id) { Badge.maximum(:id) + 1 }
|
|
|
|
it "`allow_title` is not updated for existing records" do
|
|
Badge.seed do |b|
|
|
b.id = badge_id
|
|
b.name = "Foo"
|
|
b.badge_type_id = BadgeType::Bronze
|
|
b.default_allow_title = true
|
|
end
|
|
|
|
badge = Badge.find(badge_id)
|
|
expect(badge.allow_title).to eq(true)
|
|
|
|
badge.update!(allow_title: false)
|
|
|
|
Badge.seed do |b|
|
|
b.id = badge_id
|
|
b.name = "Foo"
|
|
b.badge_type_id = BadgeType::Bronze
|
|
b.default_allow_title = true
|
|
end
|
|
|
|
badge.reload
|
|
expect(badge.allow_title).to eq(false)
|
|
end
|
|
|
|
it "`enabled` is not updated for existing records" do
|
|
Badge.seed do |b|
|
|
b.id = badge_id
|
|
b.name = "Foo"
|
|
b.badge_type_id = BadgeType::Bronze
|
|
b.default_enabled = false
|
|
end
|
|
|
|
badge = Badge.find(badge_id)
|
|
expect(badge.enabled).to eq(false)
|
|
|
|
badge.update!(enabled: true)
|
|
|
|
Badge.seed do |b|
|
|
b.id = badge_id
|
|
b.name = "Foo"
|
|
b.badge_type_id = BadgeType::Bronze
|
|
b.default_enabled = false
|
|
end
|
|
|
|
badge.reload
|
|
expect(badge.enabled).to eq(true)
|
|
end
|
|
end
|
|
end
|