mirror of
https://github.com/discourse/discourse.git
synced 2024-12-01 10:25:02 +08:00
5c37a5d0f2
Currently we can’t add a case-sensitive watched word if another one exists with a different case. For example, the existing watched word `Meta` has been created and is case-sensitive. Now an admin tries to add `metA` while marking it as case-sensitive too, this won’t work and the word won’t be added. This patch changes this behavior by allowing to add same words that have different cases, so the example above will now work as expected. We still check for uniqueness but case-sensitivy is now taken into account. It means that if the watched word `meta` already exists and is not case-sensitive then it will not be possible to add `Meta` (case-sensitive or not) as `meta` already matches every possible variations of this word.
161 lines
5.9 KiB
Ruby
161 lines
5.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe WatchedWord do
|
|
|
|
it "can't have duplicate words" do
|
|
Fabricate(:watched_word, word: "darn", action: described_class.actions[:block])
|
|
w = Fabricate.build(:watched_word, word: "darn", action: described_class.actions[:block])
|
|
expect(w.save).to eq(false)
|
|
w = Fabricate.build(:watched_word, word: "darn", action: described_class.actions[:flag])
|
|
expect(w.save).to eq(false)
|
|
expect(described_class.count).to eq(1)
|
|
end
|
|
|
|
it "doesn't downcase words" do
|
|
expect(described_class.create(word: "ShooT").word).to eq('ShooT')
|
|
end
|
|
|
|
it "strips leading and trailing spaces" do
|
|
expect(described_class.create(word: " poutine ").word).to eq('poutine')
|
|
end
|
|
|
|
it "squeezes multiple asterisks" do
|
|
expect(described_class.create(word: "a**les").word).to eq('a*les')
|
|
end
|
|
|
|
it "is case-insensitive by default" do
|
|
expect(described_class.create(word: "Jest").case_sensitive?).to eq(false)
|
|
end
|
|
|
|
describe "action_key=" do
|
|
let(:w) { WatchedWord.new(word: "troll") }
|
|
|
|
it "sets action attr from symbol" do
|
|
described_class.actions.keys.each do |k|
|
|
w.action_key = k
|
|
expect(w.action).to eq(described_class.actions[k])
|
|
end
|
|
end
|
|
|
|
it "sets action attr from string" do
|
|
described_class.actions.keys.each do |k|
|
|
w.action_key = k.to_s
|
|
expect(w.action).to eq(described_class.actions[k])
|
|
end
|
|
end
|
|
|
|
it "sets error for invalid key" do
|
|
w.action_key = "shame"
|
|
expect(w).to_not be_valid
|
|
expect(w.errors[:action]).to be_present
|
|
end
|
|
end
|
|
|
|
describe '#create_or_update_word' do
|
|
it "can create a new record" do
|
|
expect {
|
|
w = described_class.create_or_update_word(word: 'nickelback', action_key: :block)
|
|
expect(w.reload.action).to eq(described_class.actions[:block])
|
|
}.to change { described_class.count }.by(1)
|
|
end
|
|
|
|
it "can update an existing record with different action" do
|
|
existing = Fabricate(:watched_word, action: described_class.actions[:flag])
|
|
expect {
|
|
w = described_class.create_or_update_word(word: existing.word, action_key: :block)
|
|
expect(w.reload.action).to eq(described_class.actions[:block])
|
|
expect(w.id).to eq(existing.id)
|
|
}.to_not change { described_class.count }
|
|
end
|
|
|
|
it "doesn't error for existing record with same action" do
|
|
existing = Fabricate(:watched_word, action: described_class.actions[:flag], created_at: 1.day.ago, updated_at: 1.day.ago)
|
|
expect {
|
|
w = described_class.create_or_update_word(word: existing.word, action_key: :flag)
|
|
expect(w.id).to eq(existing.id)
|
|
expect(w.updated_at).to eq_time(w.updated_at)
|
|
}.to_not change { described_class.count }
|
|
end
|
|
|
|
it "allows action param instead of action_key" do
|
|
expect {
|
|
w = described_class.create_or_update_word(word: 'nickelback', action: described_class.actions[:block])
|
|
expect(w.reload.action).to eq(described_class.actions[:block])
|
|
}.to change { described_class.count }.by(1)
|
|
end
|
|
|
|
it "normalizes input" do
|
|
existing = Fabricate(:watched_word, action: described_class.actions[:flag])
|
|
expect {
|
|
w = described_class.create_or_update_word(word: " #{existing.word.upcase} ", action_key: :block)
|
|
expect(w.reload.action).to eq(described_class.actions[:block])
|
|
expect(w.id).to eq(existing.id)
|
|
}.to_not change { described_class.count }
|
|
end
|
|
|
|
it "error when an tag action is created without valid tags" do
|
|
expect {
|
|
described_class.create!(word: "ramones", action: described_class.actions[:tag])
|
|
}.to raise_error(ActiveRecord::RecordInvalid)
|
|
end
|
|
|
|
it "replaces link with absolute URL" do
|
|
word = Fabricate(:watched_word, action: described_class.actions[:link], word: "meta1")
|
|
expect(word.replacement).to eq("http://test.localhost/")
|
|
|
|
word = Fabricate(:watched_word, action: described_class.actions[:link], word: "meta2", replacement: "test")
|
|
expect(word.replacement).to eq("http://test.localhost/test")
|
|
|
|
word = Fabricate(:watched_word, action: described_class.actions[:link], word: "meta3", replacement: "/test")
|
|
expect(word.replacement).to eq("http://test.localhost/test")
|
|
end
|
|
|
|
it "sets case-sensitivity of a word" do
|
|
word = described_class.create_or_update_word(word: 'joker', action_key: :block, case_sensitive: true)
|
|
expect(word.case_sensitive?).to eq(true)
|
|
|
|
word = described_class.create_or_update_word(word: 'free', action_key: :block)
|
|
expect(word.case_sensitive?).to eq(false)
|
|
end
|
|
|
|
it "updates case-sensitivity of a word" do
|
|
existing = Fabricate(:watched_word, action: described_class.actions[:block], case_sensitive: true)
|
|
updated = described_class.create_or_update_word(word: existing.word, action_key: :block, case_sensitive: false)
|
|
|
|
expect(updated.case_sensitive?).to eq(false)
|
|
end
|
|
|
|
context "when a case-sensitive word already exists" do
|
|
subject(:create_or_update) do
|
|
described_class.create_or_update_word(word: word, action_key: :block, case_sensitive: true)
|
|
end
|
|
|
|
fab!(:existing_word) { Fabricate(:watched_word, case_sensitive: true, word: "Meta") }
|
|
|
|
context "when providing the exact same word" do
|
|
let(:word) { existing_word.word }
|
|
|
|
it "doesn't create a new watched word" do
|
|
expect { create_or_update }.not_to change { described_class.count }
|
|
end
|
|
|
|
it "returns the existing watched word" do
|
|
expect(create_or_update).to eq(existing_word)
|
|
end
|
|
end
|
|
|
|
context "when providing the same word with a different case" do
|
|
let(:word) { "metA" }
|
|
|
|
it "creates a new watched word" do
|
|
expect(create_or_update).not_to eq(existing_word)
|
|
end
|
|
|
|
it "returns the new watched word" do
|
|
expect(create_or_update).to have_attributes word: "metA", case_sensitive: true, action: 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|