mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: Move spec/components to spec/lib (#15987)
Lib specs were inexplicably split into two directories (`lib` and `components`) This moves them all into `lib`.
This commit is contained in:
46
spec/lib/validators/allowed_ip_address_validator_spec.rb
Normal file
46
spec/lib/validators/allowed_ip_address_validator_spec.rb
Normal file
@@ -0,0 +1,46 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe AllowedIpAddressValidator do
|
||||
|
||||
let(:record) { Fabricate.build(:user, trust_level: TrustLevel[0], ip_address: '99.232.23.123') }
|
||||
let(:validator) { described_class.new(attributes: :ip_address) }
|
||||
subject(:validate) { validator.validate_each(record, :ip_address, record.ip_address) }
|
||||
|
||||
context "ip address should be blocked" do
|
||||
it 'should add an error' do
|
||||
ScreenedIpAddress.stubs(:should_block?).returns(true)
|
||||
validate
|
||||
expect(record.errors[:ip_address]).to be_present
|
||||
expect(record.errors[:ip_address][0]).to eq(I18n.t('user.ip_address.blocked'))
|
||||
end
|
||||
end
|
||||
|
||||
context "ip address isn't allowed for registration" do
|
||||
it 'should add an error' do
|
||||
SpamHandler.stubs(:should_prevent_registration_from_ip?).returns(true)
|
||||
validate
|
||||
expect(record.errors[:ip_address]).to be_present
|
||||
expect(record.errors[:ip_address][0]).to eq(I18n.t('user.ip_address.max_new_accounts_per_registration_ip'))
|
||||
end
|
||||
end
|
||||
|
||||
context "ip address should not be blocked" do
|
||||
it "shouldn't add an error" do
|
||||
ScreenedIpAddress.stubs(:should_block?).returns(false)
|
||||
validate
|
||||
expect(record.errors[:ip_address]).not_to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context 'ip_address is nil' do
|
||||
it "shouldn't add an error" do
|
||||
ScreenedIpAddress.expects(:should_block?).never
|
||||
record.ip_address = nil
|
||||
validate
|
||||
expect(record.errors[:ip_address]).not_to be_present
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require 'validators/category_search_priority_weights_validator'
|
||||
|
||||
RSpec.describe CategorySearchPriorityWeightsValidator do
|
||||
it "should validate the results correctly" do
|
||||
[1, 1.1].each do |value|
|
||||
expect do
|
||||
SiteSetting.category_search_priority_low_weight = value
|
||||
end.to raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
|
||||
[1, "0.9"].each do |value|
|
||||
expect do
|
||||
SiteSetting.category_search_priority_high_weight = value
|
||||
end.to raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
end
|
||||
end
|
||||
23
spec/lib/validators/css_color_validator_spec.rb
Normal file
23
spec/lib/validators/css_color_validator_spec.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe CssColorValidator do
|
||||
subject { described_class.new }
|
||||
|
||||
it "validates hex colors" do
|
||||
expect(subject.valid_value?('#0')).to eq(false)
|
||||
expect(subject.valid_value?('#00')).to eq(false)
|
||||
expect(subject.valid_value?('#000')).to eq(true)
|
||||
expect(subject.valid_value?('#0000')).to eq(false)
|
||||
expect(subject.valid_value?('#00000')).to eq(false)
|
||||
expect(subject.valid_value?('#000000')).to eq(true)
|
||||
end
|
||||
|
||||
it "validates css colors" do
|
||||
expect(subject.valid_value?('red')).to eq(true)
|
||||
expect(subject.valid_value?('green')).to eq(true)
|
||||
expect(subject.valid_value?('blue')).to eq(true)
|
||||
expect(subject.valid_value?('hello')).to eq(false)
|
||||
end
|
||||
end
|
||||
17
spec/lib/validators/email_address_validator_spec.rb
Normal file
17
spec/lib/validators/email_address_validator_spec.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe EmailAddressValidator do
|
||||
it 'should match valid emails' do
|
||||
['test@discourse.org', 'good_user@discourse.org', 'incoming+%{reply_key}@discourse.org'].each do |email|
|
||||
expect(EmailAddressValidator.valid_value?(email)).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should not match invalid emails' do
|
||||
['testdiscourse.org', 'frank@invalid_host.contoso.com', 'frank@invalid_host.com', 'test@discourse.org; a@discourse.org', 'random', ''].each do |email|
|
||||
expect(EmailAddressValidator.valid_value?(email)).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
22
spec/lib/validators/email_setting_validator_spec.rb
Normal file
22
spec/lib/validators/email_setting_validator_spec.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe EmailSettingValidator do
|
||||
describe '#valid_value?' do
|
||||
subject(:validator) { described_class.new }
|
||||
|
||||
it "returns true for blank values" do
|
||||
expect(validator.valid_value?('')).to eq(true)
|
||||
expect(validator.valid_value?(nil)).to eq(true)
|
||||
end
|
||||
|
||||
it "returns true if value is a valid email address" do
|
||||
expect(validator.valid_value?('vader@example.com')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if value is not a valid email address" do
|
||||
expect(validator.valid_value?('my house')).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
60
spec/lib/validators/email_validator_spec.rb
Normal file
60
spec/lib/validators/email_validator_spec.rb
Normal file
@@ -0,0 +1,60 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe EmailValidator do
|
||||
def blocks?(email)
|
||||
user = Fabricate.build(:user, email: email)
|
||||
validator = EmailValidator.new(attributes: :email)
|
||||
validator.validate_each(user, :email, user.email)
|
||||
user.errors[:email].present?
|
||||
end
|
||||
|
||||
context "blocked email" do
|
||||
it "doesn't add an error when email doesn't match a blocked email" do
|
||||
expect(blocks?('sam@sam.com')).to eq(false)
|
||||
end
|
||||
|
||||
it "adds an error when email matches a blocked email" do
|
||||
ScreenedEmail.create!(email: 'sam@sam.com', action_type: ScreenedEmail.actions[:block])
|
||||
expect(blocks?('sam@sam.com')).to eq(true)
|
||||
expect(blocks?('SAM@sam.com')).to eq(true)
|
||||
end
|
||||
|
||||
it "blocks based on blocked_email_domains" do
|
||||
SiteSetting.blocked_email_domains = "email.com|mail.com|e-mail.com"
|
||||
expect(blocks?('sam@email.com')).to eq(true)
|
||||
expect(blocks?('sam@EMAIL.com')).to eq(true)
|
||||
expect(blocks?('sam@bob.email.com')).to eq(true)
|
||||
expect(blocks?('sam@e-mail.com')).to eq(true)
|
||||
expect(blocks?('sam@googlemail.com')).to eq(false)
|
||||
end
|
||||
|
||||
it "blocks based on allowed_email_domains" do
|
||||
SiteSetting.allowed_email_domains = "googlemail.com|email.com"
|
||||
expect(blocks?('sam@email.com')).to eq(false)
|
||||
expect(blocks?('sam@EMAIL.com')).to eq(false)
|
||||
expect(blocks?('sam@bob.email.com')).to eq(false)
|
||||
expect(blocks?('sam@e-mail.com')).to eq(true)
|
||||
expect(blocks?('sam@googlemail.com')).to eq(false)
|
||||
expect(blocks?('sam@email.computers.are.evil.com')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "auto approve email domains" do
|
||||
it "works as expected" do
|
||||
SiteSetting.auto_approve_email_domains = "example.com"
|
||||
|
||||
expect(EmailValidator.can_auto_approve_user?("foobar@example.com.fr")).to eq(false)
|
||||
expect(EmailValidator.can_auto_approve_user?("foobar@example.com")).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if domain not present in allowed_email_domains" do
|
||||
SiteSetting.allowed_email_domains = "googlemail.com"
|
||||
SiteSetting.auto_approve_email_domains = "example.com|googlemail.com"
|
||||
|
||||
expect(EmailValidator.can_auto_approve_user?("foobar@example.com")).to eq(false)
|
||||
expect(EmailValidator.can_auto_approve_user?("foobar@googlemail.com")).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
33
spec/lib/validators/enable_invite_only_validator_spec.rb
Normal file
33
spec/lib/validators/enable_invite_only_validator_spec.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe EnableInviteOnlyValidator do
|
||||
subject { described_class.new }
|
||||
|
||||
context "when sso is enabled" do
|
||||
before do
|
||||
SiteSetting.discourse_connect_url = "https://example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
end
|
||||
|
||||
it "is valid when false" do
|
||||
expect(subject.valid_value?('f')).to eq(true)
|
||||
end
|
||||
|
||||
it "is isn't value for true" do
|
||||
expect(subject.valid_value?('t')).to eq(false)
|
||||
expect(subject.error_message).to eq(I18n.t(
|
||||
'site_settings.errors.discourse_connect_invite_only'
|
||||
))
|
||||
end
|
||||
end
|
||||
|
||||
context "when sso isn't enabled" do
|
||||
it "is valid when true or false" do
|
||||
expect(subject.valid_value?('f')).to eq(true)
|
||||
expect(subject.valid_value?('t')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,49 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe EnableLocalLoginsViaEmailValidator do
|
||||
subject { described_class.new }
|
||||
|
||||
describe '#valid_value?' do
|
||||
describe "when 'enable_local_logins' is false" do
|
||||
before do
|
||||
SiteSetting.enable_local_logins = false
|
||||
end
|
||||
|
||||
describe 'when val is false' do
|
||||
it 'should be valid' do
|
||||
expect(subject.valid_value?('f')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when value is true' do
|
||||
it 'should not be valid' do
|
||||
expect(subject.valid_value?('t')).to eq(false)
|
||||
|
||||
expect(subject.error_message).to eq(I18n.t(
|
||||
'site_settings.errors.enable_local_logins_disabled'
|
||||
))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "when 'enable_local_logins' is true" do
|
||||
before do
|
||||
SiteSetting.enable_local_logins = true
|
||||
end
|
||||
|
||||
describe 'when val is false' do
|
||||
it 'should be valid' do
|
||||
expect(subject.valid_value?('f')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when value is true' do
|
||||
it 'should be valid' do
|
||||
expect(subject.valid_value?('t')).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
68
spec/lib/validators/enable_sso_validator_spec.rb
Normal file
68
spec/lib/validators/enable_sso_validator_spec.rb
Normal file
@@ -0,0 +1,68 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe EnableSsoValidator do
|
||||
subject { described_class.new }
|
||||
|
||||
describe '#valid_value?' do
|
||||
describe "when 'sso url' is empty" do
|
||||
before do
|
||||
SiteSetting.discourse_connect_url = ""
|
||||
end
|
||||
|
||||
describe 'when val is false' do
|
||||
it 'should be valid' do
|
||||
expect(subject.valid_value?('f')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when value is true' do
|
||||
it 'should not be valid' do
|
||||
expect(subject.valid_value?('t')).to eq(false)
|
||||
|
||||
expect(subject.error_message).to eq(I18n.t(
|
||||
'site_settings.errors.discourse_connect_url_is_empty'
|
||||
))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "when invite_only is set" do
|
||||
before do
|
||||
SiteSetting.invite_only = true
|
||||
SiteSetting.discourse_connect_url = 'https://example.com/sso'
|
||||
end
|
||||
|
||||
it 'allows a false value' do
|
||||
expect(subject.valid_value?('f')).to eq(true)
|
||||
end
|
||||
|
||||
it "doesn't allow true" do
|
||||
expect(subject.valid_value?('t')).to eq(false)
|
||||
expect(subject.error_message).to eq(I18n.t(
|
||||
'site_settings.errors.discourse_connect_invite_only'
|
||||
))
|
||||
end
|
||||
end
|
||||
|
||||
describe "when 'sso url' is present" do
|
||||
before do
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
end
|
||||
|
||||
describe 'when value is false' do
|
||||
it 'should be valid' do
|
||||
expect(subject.valid_value?('f')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when value is true' do
|
||||
it 'should be valid' do
|
||||
expect(subject.valid_value?('t')).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,27 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ExternalSystemAvatarsValidator do
|
||||
subject { described_class.new }
|
||||
|
||||
it "disallows disabling external system avatars when Unicode usernames are enabled" do
|
||||
SiteSetting.unicode_usernames = true
|
||||
|
||||
expect(subject.valid_value?("f")).to eq(false)
|
||||
expect(subject.error_message).to eq(I18n.t("site_settings.errors.unicode_usernames_avatars"))
|
||||
|
||||
expect(subject.valid_value?("t")).to eq(true)
|
||||
expect(subject.error_message).to be_blank
|
||||
end
|
||||
|
||||
it "allows disabling external system avatars when Unicode usernames are disabled" do
|
||||
SiteSetting.unicode_usernames = false
|
||||
|
||||
expect(subject.valid_value?("t")).to eq(true)
|
||||
expect(subject.error_message).to be_blank
|
||||
|
||||
expect(subject.valid_value?("f")).to eq(true)
|
||||
expect(subject.error_message).to be_blank
|
||||
end
|
||||
end
|
||||
23
spec/lib/validators/group_setting_validator_spec.rb
Normal file
23
spec/lib/validators/group_setting_validator_spec.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe GroupSettingValidator do
|
||||
describe '#valid_value?' do
|
||||
subject(:validator) { described_class.new }
|
||||
|
||||
it "returns true for blank values" do
|
||||
expect(validator.valid_value?('')).to eq(true)
|
||||
expect(validator.valid_value?(nil)).to eq(true)
|
||||
end
|
||||
|
||||
it "returns true if value matches an existing group" do
|
||||
Fabricate(:group, name: "hello")
|
||||
expect(validator.valid_value?('hello')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if value does not match a group" do
|
||||
expect(validator.valid_value?('notagroup')).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
31
spec/lib/validators/host_list_setting_validator_spec.rb
Normal file
31
spec/lib/validators/host_list_setting_validator_spec.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe HostListSettingValidator do
|
||||
subject(:validator) { described_class.new() }
|
||||
|
||||
describe '#valid_value?' do
|
||||
describe "returns false for values containing *" do
|
||||
it { expect(validator.valid_value?("*")).to eq false }
|
||||
it { expect(validator.valid_value?("**")).to eq false }
|
||||
it { expect(validator.valid_value?(".*")).to eq false }
|
||||
it { expect(validator.valid_value?("a")).to eq true }
|
||||
end
|
||||
|
||||
describe "returns false for values containing ?" do
|
||||
it { expect(validator.valid_value?("?")).to eq false }
|
||||
it { expect(validator.valid_value?("??")).to eq false }
|
||||
it { expect(validator.valid_value?(".?")).to eq false }
|
||||
it { expect(validator.valid_value?("a")).to eq true }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#error_message" do
|
||||
it "returns invalid domain hostname error" do
|
||||
expect(validator.error_message).to eq(I18n.t(
|
||||
'site_settings.errors.invalid_domain_hostname'
|
||||
))
|
||||
end
|
||||
end
|
||||
end
|
||||
112
spec/lib/validators/integer_setting_validator_spec.rb
Normal file
112
spec/lib/validators/integer_setting_validator_spec.rb
Normal file
@@ -0,0 +1,112 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe IntegerSettingValidator do
|
||||
describe '#valid_value?' do
|
||||
|
||||
shared_examples "for all IntegerSettingValidator opts" do
|
||||
it "returns false for blank values" do
|
||||
expect(validator.valid_value?('')).to eq(false)
|
||||
expect(validator.valid_value?(nil)).to eq(false)
|
||||
end
|
||||
|
||||
it "returns false if value is not a valid integer" do
|
||||
expect(validator.valid_value?('two')).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "without min and max" do
|
||||
subject(:validator) { described_class.new }
|
||||
|
||||
include_examples "for all IntegerSettingValidator opts"
|
||||
|
||||
it "returns true if value is a valid integer" do
|
||||
expect(validator.valid_value?(1)).to eq(true)
|
||||
expect(validator.valid_value?('1')).to eq(true)
|
||||
end
|
||||
|
||||
it "defaults min to 0" do
|
||||
expect(validator.valid_value?(-1)).to eq(false)
|
||||
expect(validator.valid_value?('-1')).to eq(false)
|
||||
expect(validator.valid_value?(0)).to eq(true)
|
||||
expect(validator.valid_value?('0')).to eq(true)
|
||||
end
|
||||
|
||||
it "defaults max to 2_000_000_000" do
|
||||
expect(validator.valid_value?(2_000_000_001)).to eq(false)
|
||||
expect(validator.valid_value?('2000000001')).to eq(false)
|
||||
expect(validator.valid_value?(2_000_000_000)).to eq(true)
|
||||
expect(validator.valid_value?('2000000000')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "with min" do
|
||||
subject(:validator) { described_class.new(min: 2) }
|
||||
|
||||
include_examples "for all IntegerSettingValidator opts"
|
||||
|
||||
it "returns true if value is equal to min" do
|
||||
expect(validator.valid_value?(2)).to eq(true)
|
||||
expect(validator.valid_value?('2')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns true if value is greater than min" do
|
||||
expect(validator.valid_value?(3)).to eq(true)
|
||||
expect(validator.valid_value?('3')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if value is less than min" do
|
||||
expect(validator.valid_value?(1)).to eq(false)
|
||||
expect(validator.valid_value?('1')).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "with max" do
|
||||
subject(:validator) { described_class.new(max: 3) }
|
||||
|
||||
include_examples "for all IntegerSettingValidator opts"
|
||||
|
||||
it "returns true if value is equal to max" do
|
||||
expect(validator.valid_value?(3)).to eq(true)
|
||||
expect(validator.valid_value?('3')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns true if value is less than max" do
|
||||
expect(validator.valid_value?(2)).to eq(true)
|
||||
expect(validator.valid_value?('2')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if value is greater than min" do
|
||||
expect(validator.valid_value?(4)).to eq(false)
|
||||
expect(validator.valid_value?('4')).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "with min and max" do
|
||||
subject(:validator) { described_class.new(min: -1, max: 3) }
|
||||
|
||||
include_examples "for all IntegerSettingValidator opts"
|
||||
|
||||
it "returns true if value is in range" do
|
||||
expect(validator.valid_value?(-1)).to eq(true)
|
||||
expect(validator.valid_value?(0)).to eq(true)
|
||||
expect(validator.valid_value?(3)).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if value is out of range" do
|
||||
expect(validator.valid_value?(4)).to eq(false)
|
||||
expect(validator.valid_value?(-2)).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "when setting is hidden" do
|
||||
subject(:validator) { described_class.new(hidden: true) }
|
||||
|
||||
it "does not impose default validations" do
|
||||
expect(validator.valid_value?(-1)).to eq(true)
|
||||
expect(validator.valid_value?(20001)).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
30
spec/lib/validators/ip_address_format_validator_spec.rb
Normal file
30
spec/lib/validators/ip_address_format_validator_spec.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe IpAddressFormatValidator do
|
||||
|
||||
let(:record) { Fabricate.build(:screened_ip_address, ip_address: '99.232.23.123') }
|
||||
let(:validator) { described_class.new(attributes: :ip_address) }
|
||||
subject(:validate) { validator.validate_each(record, :ip_address, record.ip_address) }
|
||||
|
||||
['99.232.23.123', '99.232.0.0/16', 'fd12:db8::ff00:42:8329', 'fc00::/7'].each do |arg|
|
||||
it "should not add an error for #{arg}" do
|
||||
record.ip_address = arg
|
||||
validate
|
||||
expect(record.errors[:ip_address]).not_to be_present
|
||||
end
|
||||
end
|
||||
|
||||
it 'should add an error for nil IP address' do
|
||||
record.ip_address = nil
|
||||
validate
|
||||
expect(record.errors[:ip_address]).to be_present
|
||||
end
|
||||
|
||||
it 'should add an error for invalid IP address' do
|
||||
record.ip_address = '99.99.99'
|
||||
validate
|
||||
expect(record.errors[:ip_address]).to be_present
|
||||
end
|
||||
end
|
||||
57
spec/lib/validators/max_emojis_validator_spec.rb
Normal file
57
spec/lib/validators/max_emojis_validator_spec.rb
Normal file
@@ -0,0 +1,57 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require 'validators/max_emojis_validator'
|
||||
|
||||
describe MaxEmojisValidator do
|
||||
|
||||
# simulate Rails behavior (singleton)
|
||||
def validate
|
||||
@validator ||= MaxEmojisValidator.new(attributes: :title)
|
||||
@validator.validate_each(record, :title, record.title)
|
||||
end
|
||||
|
||||
shared_examples "validating any topic title" do
|
||||
it 'adds an error when emoji count is greater than SiteSetting.max_emojis_in_title' do
|
||||
SiteSetting.max_emojis_in_title = 3
|
||||
CustomEmoji.create!(name: 'trout', upload: Fabricate(:upload))
|
||||
Emoji.clear_cache
|
||||
record.title = '🧐 Lots of emojis here 🎃 :trout: :)'
|
||||
validate
|
||||
expect(record.errors[:title][0]).to eq(I18n.t("errors.messages.max_emojis", max_emojis_count: 3))
|
||||
|
||||
record.title = ':joy: :blush: :smile: is not only about emojis: Happiness::start()'
|
||||
validate
|
||||
expect(record.valid?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe 'topic' do
|
||||
let(:record) { Fabricate.build(:topic) }
|
||||
|
||||
it 'does not add an error when emoji count is good' do
|
||||
SiteSetting.max_emojis_in_title = 2
|
||||
|
||||
record.title = 'To Infinity and beyond! 🚀 :woman:t5:'
|
||||
validate
|
||||
expect(record.errors[:title]).to_not be_present
|
||||
end
|
||||
|
||||
include_examples "validating any topic title"
|
||||
end
|
||||
|
||||
describe 'private message' do
|
||||
let(:record) { Fabricate.build(:private_message_topic) }
|
||||
|
||||
it 'does not add an error when emoji count is good' do
|
||||
SiteSetting.max_emojis_in_title = 1
|
||||
|
||||
record.title = 'To Infinity and beyond! 🚀'
|
||||
validate
|
||||
expect(record.errors[:title]).to_not be_present
|
||||
end
|
||||
|
||||
include_examples "validating any topic title"
|
||||
end
|
||||
end
|
||||
28
spec/lib/validators/max_username_length_validator_spec.rb
Normal file
28
spec/lib/validators/max_username_length_validator_spec.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe MaxUsernameLengthValidator do
|
||||
it "checks for minimum range" do
|
||||
SiteSetting.min_username_length = 6
|
||||
|
||||
validator = described_class.new
|
||||
expect(validator.valid_value?(5)).to eq(false)
|
||||
expect(validator.error_message).to eq(I18n.t("site_settings.errors.max_username_length_range"))
|
||||
end
|
||||
|
||||
it "checks for users with short usernames" do
|
||||
user = Fabricate(:user, username: 'jackjackjack')
|
||||
|
||||
validator = described_class.new
|
||||
expect(validator.valid_value?(12)).to eq(true)
|
||||
|
||||
validator = described_class.new
|
||||
expect(validator.valid_value?(11)).to eq(false)
|
||||
|
||||
expect(validator.error_message).to eq(I18n.t(
|
||||
"site_settings.errors.max_username_length_exists",
|
||||
username: 'jackjackjack'
|
||||
))
|
||||
end
|
||||
end
|
||||
28
spec/lib/validators/min_username_length_validator_spec.rb
Normal file
28
spec/lib/validators/min_username_length_validator_spec.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe MinUsernameLengthValidator do
|
||||
it "checks for maximum range" do
|
||||
SiteSetting.max_username_length = 10
|
||||
|
||||
validator = described_class.new
|
||||
expect(validator.valid_value?(11)).to eq(false)
|
||||
expect(validator.error_message).to eq(I18n.t("site_settings.errors.min_username_length_range"))
|
||||
end
|
||||
|
||||
it "checks for users with short usernames" do
|
||||
user = Fabricate(:user, username: 'jack')
|
||||
|
||||
validator = described_class.new
|
||||
expect(validator.valid_value?(4)).to eq(true)
|
||||
|
||||
validator = described_class.new
|
||||
expect(validator.valid_value?(5)).to eq(false)
|
||||
|
||||
expect(validator.error_message).to eq(I18n.t(
|
||||
"site_settings.errors.min_username_length_exists",
|
||||
username: 'jack'
|
||||
))
|
||||
end
|
||||
end
|
||||
181
spec/lib/validators/password_validator_spec.rb
Normal file
181
spec/lib/validators/password_validator_spec.rb
Normal file
@@ -0,0 +1,181 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe PasswordValidator do
|
||||
|
||||
def password_error_message(key)
|
||||
I18n.t("activerecord.errors.models.user.attributes.password.#{key.to_s}")
|
||||
end
|
||||
|
||||
let(:validator) { described_class.new(attributes: :password) }
|
||||
subject(:validate) { validator.validate_each(record, :password, @password) }
|
||||
|
||||
context "password required" do
|
||||
let(:record) { u = Fabricate.build(:user, password: @password); u.password_required!; u }
|
||||
|
||||
context "password is not common" do
|
||||
before do
|
||||
CommonPasswords.stubs(:common_password?).returns(false)
|
||||
end
|
||||
|
||||
context "min password length is 8" do
|
||||
before { SiteSetting.min_password_length = 8 }
|
||||
|
||||
it "doesn't add an error when password is good" do
|
||||
@password = "weron235alsfn234"
|
||||
validate
|
||||
expect(record.errors[:password]).not_to be_present
|
||||
end
|
||||
|
||||
it "adds an error when password is too short" do
|
||||
@password = "p"
|
||||
validate
|
||||
expect(record.errors[:password]).to be_present
|
||||
end
|
||||
|
||||
it "adds an error when password is blank" do
|
||||
@password = ''
|
||||
validate
|
||||
expect(record.errors[:password]).to be_present
|
||||
end
|
||||
|
||||
it "adds an error when password is nil" do
|
||||
@password = nil
|
||||
validate
|
||||
expect(record.errors[:password]).to be_present
|
||||
end
|
||||
|
||||
it "adds an error when user is admin and password is less than 15 chars" do
|
||||
SiteSetting.min_admin_password_length = 15
|
||||
|
||||
@password = "12345678912"
|
||||
record.admin = true
|
||||
validate
|
||||
expect(record.errors[:password]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context "min password length is 12" do
|
||||
before { SiteSetting.min_password_length = 12 }
|
||||
|
||||
it "adds an error when password length is 11" do
|
||||
@password = "gt38sdt92bv"
|
||||
validate
|
||||
expect(record.errors[:password]).to be_present
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "password is commonly used" do
|
||||
before do
|
||||
SiteSetting.min_password_length = 8
|
||||
CommonPasswords.stubs(:common_password?).returns(true)
|
||||
end
|
||||
|
||||
it "adds an error when block_common_passwords is enabled" do
|
||||
SiteSetting.block_common_passwords = true
|
||||
@password = "password"
|
||||
validate
|
||||
expect(record.errors[:password]).to include(password_error_message(:common))
|
||||
end
|
||||
|
||||
it "doesn't add an error when block_common_passwords is disabled" do
|
||||
SiteSetting.block_common_passwords = false
|
||||
@password = "password"
|
||||
validate
|
||||
expect(record.errors[:password]).not_to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context "password_unique_characters is 5" do
|
||||
before do
|
||||
SiteSetting.password_unique_characters = 5
|
||||
end
|
||||
|
||||
it "adds an error when there are too few unique characters" do
|
||||
SiteSetting.password_unique_characters = 6
|
||||
@password = "aaaaaa5432"
|
||||
validate
|
||||
expect(record.errors[:password]).to include(password_error_message(:unique_characters))
|
||||
end
|
||||
|
||||
it "doesn't add an error when there are enough unique characters" do
|
||||
@password = "aaaaa12345"
|
||||
validate
|
||||
expect(record.errors[:password]).not_to be_present
|
||||
end
|
||||
|
||||
it "counts capital letters as different" do
|
||||
@password = "aaaAaa1234"
|
||||
validate
|
||||
expect(record.errors[:password]).not_to be_present
|
||||
end
|
||||
end
|
||||
|
||||
it "adds an error when password is the same as the username" do
|
||||
@password = "porkchops1234"
|
||||
record.username = @password
|
||||
validate
|
||||
expect(record.errors[:password]).to include(password_error_message(:same_as_username))
|
||||
end
|
||||
|
||||
it "adds an error when password is the same as the name" do
|
||||
@password = "myawesomepassword"
|
||||
record.name = @password
|
||||
validate
|
||||
expect(record.errors[:password]).to include(password_error_message(:same_as_name))
|
||||
end
|
||||
|
||||
it "adds an error when password is the same as the email" do
|
||||
@password = "pork@chops.com"
|
||||
record.email = @password
|
||||
validate
|
||||
expect(record.errors[:password]).to include(password_error_message(:same_as_email))
|
||||
end
|
||||
|
||||
it "adds an error when new password is same as current password" do
|
||||
@password = "mypetsname"
|
||||
record.save!
|
||||
record.reload
|
||||
record.password = @password
|
||||
validate
|
||||
expect(record.errors[:password]).to include(password_error_message(:same_as_current))
|
||||
end
|
||||
|
||||
it "validation required if password is required" do
|
||||
expect(record.password_validation_required?).to eq(true)
|
||||
end
|
||||
|
||||
it "validation not required after save until a new password is set" do
|
||||
@password = "myoldpassword"
|
||||
record.save!
|
||||
record.reload
|
||||
expect(record.password_validation_required?).to eq(false)
|
||||
record.password = "mynewpassword"
|
||||
expect(record.password_validation_required?).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "password not required" do
|
||||
let(:record) { Fabricate.build(:user, password: @password) }
|
||||
|
||||
it "doesn't add an error if password is not required" do
|
||||
@password = nil
|
||||
validate
|
||||
expect(record.errors[:password]).not_to be_present
|
||||
end
|
||||
|
||||
it "validation required if a password is set" do
|
||||
@password = "mygameshow"
|
||||
expect(record.password_validation_required?).to eq(true)
|
||||
end
|
||||
|
||||
it "adds an error even password not required" do
|
||||
@password = "p"
|
||||
validate
|
||||
expect(record.errors[:password]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
361
spec/lib/validators/post_validator_spec.rb
Normal file
361
spec/lib/validators/post_validator_spec.rb
Normal file
@@ -0,0 +1,361 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe PostValidator do
|
||||
fab!(:topic) { Fabricate(:topic) }
|
||||
let(:post) { build(:post, topic: topic) }
|
||||
let(:validator) { PostValidator.new({}) }
|
||||
|
||||
context "#post_body_validator" do
|
||||
it 'should not allow a post with an empty raw' do
|
||||
post.raw = ""
|
||||
validator.post_body_validator(post)
|
||||
expect(post.errors).to_not be_empty
|
||||
end
|
||||
|
||||
context "when empty raw can bypass validation" do
|
||||
let(:validator) { PostValidator.new(skip_post_body: true) }
|
||||
|
||||
it "should be allowed for empty raw based on site setting" do
|
||||
post.raw = ""
|
||||
validator.post_body_validator(post)
|
||||
expect(post.errors).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe "when post's topic is a PM between a human and a non human user" do
|
||||
fab!(:robot) { Fabricate(:user, id: -3) }
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
||||
let(:topic) do
|
||||
Fabricate(:private_message_topic, topic_allowed_users: [
|
||||
Fabricate.build(:topic_allowed_user, user: robot),
|
||||
Fabricate.build(:topic_allowed_user, user: user)
|
||||
])
|
||||
end
|
||||
|
||||
it 'should allow a post with an empty raw' do
|
||||
post = Fabricate.build(:post, topic: topic)
|
||||
post.raw = ""
|
||||
validator.post_body_validator(post)
|
||||
|
||||
expect(post.errors).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "stripped_length" do
|
||||
it "adds an error for short raw" do
|
||||
post.raw = "abc"
|
||||
validator.stripped_length(post)
|
||||
expect(post.errors.count).to eq(1)
|
||||
end
|
||||
|
||||
it "counts emoji as a single character" do
|
||||
post.raw = ":smiling_face_with_three_hearts:" * (SiteSetting.min_post_length - 1)
|
||||
validator.stripped_length(post)
|
||||
expect(post.errors.count).to eq(1)
|
||||
|
||||
post = build(:post, topic: topic)
|
||||
post.raw = ":smiling_face_with_three_hearts:" * SiteSetting.min_post_length
|
||||
validator.stripped_length(post)
|
||||
expect(post.errors.count).to eq(0)
|
||||
end
|
||||
|
||||
it "counts multiple characters as a single character" do
|
||||
post.raw = "." * SiteSetting.min_post_length
|
||||
validator.stripped_length(post)
|
||||
expect(post.errors.count).to eq(1)
|
||||
|
||||
post = build(:post, topic: topic)
|
||||
post.raw = "," * SiteSetting.min_post_length
|
||||
validator.stripped_length(post)
|
||||
expect(post.errors.count).to eq(1)
|
||||
|
||||
post = build(:post, topic: topic)
|
||||
post.raw = "<!-- #{'very long comment' * SiteSetting.min_post_length} -->"
|
||||
validator.stripped_length(post)
|
||||
expect(post.errors.count).to eq(1)
|
||||
end
|
||||
|
||||
it "adds no error for long raw" do
|
||||
post.raw = "this is a long topic body testing 123"
|
||||
validator.stripped_length(post)
|
||||
expect(post.errors.count).to eq(0)
|
||||
end
|
||||
|
||||
it "ignores an html comment" do
|
||||
post.raw = "<!-- an html comment -->abc"
|
||||
validator.stripped_length(post)
|
||||
expect(post.errors.count).to eq(1)
|
||||
end
|
||||
|
||||
it "ignores multiple html comments" do
|
||||
post.raw = "<!-- an html comment -->\n abc \n<!-- a comment -->"
|
||||
validator.stripped_length(post)
|
||||
expect(post.errors.count).to eq(1)
|
||||
end
|
||||
|
||||
it "ignores nested html comments" do
|
||||
post.raw = "<!-- <!-- an html comment --> -->"
|
||||
validator.stripped_length(post)
|
||||
expect(post.errors.count).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context "too_many_posts" do
|
||||
it "should be invalid when the user has posted too much" do
|
||||
post.user.expects(:posted_too_much_in_topic?).returns(true)
|
||||
validator.max_posts_validator(post)
|
||||
expect(post.errors.count).to be > 0
|
||||
end
|
||||
|
||||
it "should be allowed to edit when the user has posted too much" do
|
||||
post.user.stubs(:posted_too_much_in_topic?).returns(true)
|
||||
post.expects(:new_record?).returns(false)
|
||||
validator.max_posts_validator(post)
|
||||
expect(post.errors.count).to be(0)
|
||||
end
|
||||
|
||||
it "should be valid when the user hasn't posted too much" do
|
||||
post.user.expects(:posted_too_much_in_topic?).returns(false)
|
||||
validator.max_posts_validator(post)
|
||||
expect(post.errors.count).to be(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "too_many_mentions" do
|
||||
before do
|
||||
SiteSetting.newuser_max_mentions_per_post = 2
|
||||
SiteSetting.max_mentions_per_post = 3
|
||||
end
|
||||
|
||||
it "should be invalid when new user exceeds max mentions limit" do
|
||||
post.acting_user = build(:newuser)
|
||||
post.expects(:raw_mentions).returns(['jake', 'finn', 'jake_old'])
|
||||
validator.max_mention_validator(post)
|
||||
expect(post.errors.count).to be > 0
|
||||
end
|
||||
|
||||
it "should be invalid when leader user exceeds max mentions limit" do
|
||||
post.acting_user = build(:trust_level_4)
|
||||
post.expects(:raw_mentions).returns(['jake', 'finn', 'jake_old', 'jake_new'])
|
||||
validator.max_mention_validator(post)
|
||||
expect(post.errors.count).to be > 0
|
||||
end
|
||||
|
||||
it "should be valid when new user does not exceed max mentions limit" do
|
||||
post.acting_user = build(:newuser)
|
||||
post.expects(:raw_mentions).returns(['jake', 'finn'])
|
||||
validator.max_mention_validator(post)
|
||||
expect(post.errors.count).to be(0)
|
||||
end
|
||||
|
||||
it "should be valid when new user exceeds max mentions limit in PM" do
|
||||
post.acting_user = build(:newuser)
|
||||
post.topic.expects(:private_message?).returns(true)
|
||||
post.expects(:raw_mentions).returns(['jake', 'finn', 'jake_old'])
|
||||
validator.max_mention_validator(post)
|
||||
expect(post.errors.count).to be(0)
|
||||
end
|
||||
|
||||
it "should be valid when leader user does not exceed max mentions limit" do
|
||||
post.acting_user = build(:trust_level_4)
|
||||
post.expects(:raw_mentions).returns(['jake', 'finn', 'jake_old'])
|
||||
validator.max_mention_validator(post)
|
||||
expect(post.errors.count).to be(0)
|
||||
end
|
||||
|
||||
it "should be valid for moderator in all cases" do
|
||||
post.acting_user = build(:moderator)
|
||||
post.expects(:raw_mentions).never
|
||||
validator.max_mention_validator(post)
|
||||
expect(post.errors.count).to be(0)
|
||||
end
|
||||
|
||||
it "should be valid for admin in all cases" do
|
||||
post.acting_user = build(:admin)
|
||||
post.expects(:raw_mentions).never
|
||||
validator.max_mention_validator(post)
|
||||
expect(post.errors.count).to be(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "too_many_embedded_media" do
|
||||
before do
|
||||
SiteSetting.min_trust_to_post_embedded_media = 0
|
||||
SiteSetting.newuser_max_embedded_media = 2
|
||||
end
|
||||
|
||||
it "should be invalid when new user exceeds max mentions limit" do
|
||||
post.acting_user = build(:newuser)
|
||||
post.expects(:embedded_media_count).returns(3)
|
||||
validator.max_embedded_media_validator(post)
|
||||
expect(post.errors.count).to be > 0
|
||||
end
|
||||
|
||||
it "should be valid when new user does not exceed max mentions limit" do
|
||||
post.acting_user = build(:newuser)
|
||||
post.expects(:embedded_media_count).returns(2)
|
||||
validator.max_embedded_media_validator(post)
|
||||
expect(post.errors.count).to be(0)
|
||||
end
|
||||
|
||||
it "should be invalid when user trust level is not sufficient" do
|
||||
SiteSetting.min_trust_to_post_embedded_media = 4
|
||||
post.acting_user = build(:leader)
|
||||
post.expects(:embedded_media_count).returns(2)
|
||||
validator.max_embedded_media_validator(post)
|
||||
expect(post.errors.count).to be > 0
|
||||
end
|
||||
|
||||
it "should be valid for moderator in all cases" do
|
||||
post.acting_user = build(:moderator)
|
||||
post.expects(:embedded_media_count).never
|
||||
validator.max_embedded_media_validator(post)
|
||||
expect(post.errors.count).to be(0)
|
||||
end
|
||||
|
||||
it "should be valid for admin in all cases" do
|
||||
post.acting_user = build(:admin)
|
||||
post.expects(:embedded_media_count).never
|
||||
validator.max_embedded_media_validator(post)
|
||||
expect(post.errors.count).to be(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "invalid post" do
|
||||
it "should be invalid" do
|
||||
validator.validate(post)
|
||||
expect(post.errors.count).to be > 0
|
||||
end
|
||||
end
|
||||
|
||||
describe "unique_post_validator" do
|
||||
fab!(:user) { Fabricate(:user, id: 999) }
|
||||
fab!(:post) { Fabricate(:post, user: user, topic: topic) }
|
||||
|
||||
before do
|
||||
SiteSetting.unique_posts_mins = 5
|
||||
post.store_unique_post_key
|
||||
@key = post.unique_post_key
|
||||
end
|
||||
|
||||
after do
|
||||
Discourse.redis.del(@key)
|
||||
end
|
||||
|
||||
context "post is unique" do
|
||||
let(:new_post) do
|
||||
Fabricate.build(:post, user: user, raw: "unique content", topic: topic)
|
||||
end
|
||||
|
||||
it "should not add an error" do
|
||||
validator.unique_post_validator(new_post)
|
||||
expect(new_post.errors.count).to eq(0)
|
||||
end
|
||||
|
||||
it 'should not add an error when changing an existing post' do
|
||||
post.raw = "changing raw"
|
||||
|
||||
validator.unique_post_validator(post)
|
||||
expect(post.errors.count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "post is not unique" do
|
||||
let(:new_post) do
|
||||
Fabricate.build(:post, user: user, raw: post.raw, topic: topic)
|
||||
end
|
||||
|
||||
it "should add an error" do
|
||||
validator.unique_post_validator(new_post)
|
||||
expect(new_post.errors.to_hash.keys).to contain_exactly(:raw)
|
||||
end
|
||||
|
||||
it "should not add an error if post.skip_unique_check is true" do
|
||||
new_post.skip_unique_check = true
|
||||
validator.unique_post_validator(new_post)
|
||||
expect(new_post.errors.count).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "force_edit_last_validator" do
|
||||
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
fab!(:other_user) { Fabricate(:user) }
|
||||
fab!(:topic) { Fabricate(:topic) }
|
||||
|
||||
before do
|
||||
SiteSetting.max_consecutive_replies = 2
|
||||
end
|
||||
|
||||
it "should always allow original poster to post" do
|
||||
[user, user, user, other_user, user, user, user].each_with_index do |u, i|
|
||||
post = Post.new(user: u, topic: topic, raw: "post number #{i}")
|
||||
validator.force_edit_last_validator(post)
|
||||
expect(post.errors.count).to eq(0)
|
||||
post.save!
|
||||
end
|
||||
end
|
||||
|
||||
it "should not allow posting more than 2 consecutive replies" do
|
||||
Post.create!(user: user, topic: topic, raw: "post number 2", post_number: 2)
|
||||
Post.create!(user: user, topic: topic, raw: "post number 3", post_number: 3)
|
||||
Post.create!(user: other_user, topic: topic, raw: "post number 1", post_number: 1)
|
||||
|
||||
post = Post.new(user: user, topic: topic, raw: "post number 4", post_number: 4)
|
||||
validator.force_edit_last_validator(post)
|
||||
expect(post.errors.count).to eq(1)
|
||||
end
|
||||
|
||||
it "should always allow editing" do
|
||||
post = Fabricate(:post, user: user, topic: topic)
|
||||
post = Fabricate(:post, user: user, topic: topic)
|
||||
|
||||
revisor = PostRevisor.new(post)
|
||||
revisor.revise!(post.user, raw: 'hello world123456789')
|
||||
end
|
||||
|
||||
it "should allow posting more than 2 replies" do
|
||||
3.times do
|
||||
post = Fabricate(:post, user: user, topic: topic)
|
||||
Fabricate(:post, user: other_user, topic: topic)
|
||||
validator.force_edit_last_validator(post)
|
||||
expect(post.errors.count).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples "almost no validations" do
|
||||
it "skips most validations" do
|
||||
validator.expects(:stripped_length).never
|
||||
validator.expects(:raw_quality).never
|
||||
validator.expects(:max_posts_validator).never
|
||||
validator.expects(:max_mention_validator).never
|
||||
validator.expects(:max_embedded_media_validator).never
|
||||
validator.expects(:max_attachments_validator).never
|
||||
validator.expects(:newuser_links_validator).never
|
||||
validator.expects(:unique_post_validator).never
|
||||
validator.expects(:force_edit_last_validator).never
|
||||
validator.validate(post)
|
||||
end
|
||||
end
|
||||
|
||||
context "admin editing a static page" do
|
||||
before do
|
||||
post.acting_user = build(:admin)
|
||||
SiteSetting.tos_topic_id = post.topic_id
|
||||
end
|
||||
|
||||
include_examples "almost no validations"
|
||||
end
|
||||
|
||||
context "staged user" do
|
||||
before { post.acting_user = build(:user, staged: true) }
|
||||
include_examples "almost no validations"
|
||||
end
|
||||
|
||||
end
|
||||
91
spec/lib/validators/quality_title_validator_spec.rb
Normal file
91
spec/lib/validators/quality_title_validator_spec.rb
Normal file
@@ -0,0 +1,91 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require 'validators/quality_title_validator'
|
||||
require 'ostruct'
|
||||
|
||||
module QualityTitleValidatorSpec
|
||||
class Validatable < OpenStruct
|
||||
include ActiveModel::Validations
|
||||
validates :title, quality_title: { unless: :private_message? }
|
||||
end
|
||||
end
|
||||
|
||||
describe "A record validated with QualityTitleValidator" do
|
||||
let(:valid_title) { "hello this is my cool topic! welcome: all;" }
|
||||
let(:short_title) { valid_title.slice(0, SiteSetting.min_topic_title_length - 1) }
|
||||
let(:long_title) { valid_title.center(SiteSetting.max_topic_title_length + 1, 'x') }
|
||||
let(:xxxxx_title) { valid_title.gsub(/./, 'x') }
|
||||
|
||||
let(:meaningless_title) { "asdf asdf asdf" }
|
||||
let(:loud_title) { "ALL CAPS INVALID TITLE" }
|
||||
let(:pretentious_title) { "superverylongwordintitlefornoparticularreason" }
|
||||
|
||||
subject(:topic) { QualityTitleValidatorSpec::Validatable.new }
|
||||
|
||||
before(:each) do
|
||||
topic.stubs(private_message?: false)
|
||||
end
|
||||
|
||||
it "allows a regular title with a few ascii characters" do
|
||||
topic.title = valid_title
|
||||
expect(topic).to be_valid
|
||||
end
|
||||
|
||||
it "allows non ascii" do
|
||||
topic.title = "Iñtërnâtiônàlizætiøn"
|
||||
expect(topic).to be_valid
|
||||
end
|
||||
|
||||
it 'allows Chinese characters' do
|
||||
topic.title = '现在发现使用中文标题没法发帖子了'
|
||||
expect(topic).to be_valid
|
||||
end
|
||||
|
||||
it "allows anything in a private message" do
|
||||
topic.stubs(private_message?: true)
|
||||
[short_title, long_title, xxxxx_title].each do |bad_title|
|
||||
topic.title = bad_title
|
||||
expect(topic).to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
it "strips a title when identifying length" do
|
||||
topic.title = short_title.center(SiteSetting.min_topic_title_length + 1, ' ')
|
||||
expect(topic).not_to be_valid
|
||||
end
|
||||
|
||||
it "doesn't allow a long title" do
|
||||
topic.title = long_title
|
||||
expect(topic).not_to be_valid
|
||||
end
|
||||
|
||||
it "doesn't allow a short title" do
|
||||
topic.title = short_title
|
||||
expect(topic).not_to be_valid
|
||||
end
|
||||
|
||||
it "doesn't allow a title of one repeated character" do
|
||||
topic.title = xxxxx_title
|
||||
expect(topic).not_to be_valid
|
||||
end
|
||||
|
||||
it "doesn't allow a meaningless title" do
|
||||
topic.title = meaningless_title
|
||||
expect(topic).not_to be_valid
|
||||
expect(topic.errors.full_messages.first).to include(I18n.t("errors.messages.is_invalid_meaningful"))
|
||||
end
|
||||
|
||||
it "doesn't allow a pretentious title" do
|
||||
topic.title = pretentious_title
|
||||
expect(topic).not_to be_valid
|
||||
expect(topic.errors.full_messages.first).to include(I18n.t("errors.messages.is_invalid_unpretentious"))
|
||||
end
|
||||
|
||||
it "doesn't allow a loud title" do
|
||||
topic.title = loud_title
|
||||
expect(topic).not_to be_valid
|
||||
expect(topic.errors.full_messages.first).to include(I18n.t("errors.messages.is_invalid_quiet"))
|
||||
end
|
||||
end
|
||||
33
spec/lib/validators/regex_presence_validator_spec.rb
Normal file
33
spec/lib/validators/regex_presence_validator_spec.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe RegexPresenceValidator do
|
||||
subject { described_class.new(regex: 'latest', regex_error: 'site_settings.errors.must_include_latest') }
|
||||
|
||||
describe "#valid_value?" do
|
||||
describe "when value is present" do
|
||||
it "without regex match" do
|
||||
expect(subject.valid_value?("categories|new")).to eq(false)
|
||||
|
||||
expect(subject.error_message).to eq(I18n.t(
|
||||
"site_settings.errors.must_include_latest"
|
||||
))
|
||||
end
|
||||
|
||||
it "with regex match" do
|
||||
expect(subject.valid_value?("latest|categories")).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe "when value is empty" do
|
||||
it "should not be valid" do
|
||||
expect(subject.valid_value?("")).to eq(false)
|
||||
|
||||
expect(subject.error_message).to eq(I18n.t(
|
||||
"site_settings.errors.must_include_latest"
|
||||
))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
26
spec/lib/validators/regex_setting_validator_spec.rb
Normal file
26
spec/lib/validators/regex_setting_validator_spec.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe RegexSettingValidator do
|
||||
describe '#valid_value?' do
|
||||
subject(:validator) { described_class.new }
|
||||
|
||||
it "returns true for blank values" do
|
||||
expect(validator.valid_value?('')).to eq(true)
|
||||
expect(validator.valid_value?(nil)).to eq(true)
|
||||
end
|
||||
|
||||
it "return false for invalid regex" do
|
||||
expect(validator.valid_value?('(()')).to eq(false)
|
||||
end
|
||||
|
||||
it "returns false for regex with dangerous matches" do
|
||||
expect(validator.valid_value?('(.)*')).to eq(false)
|
||||
end
|
||||
|
||||
it "returns true for safe regex" do
|
||||
expect(validator.valid_value?('\d{3}-\d{4}')).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
41
spec/lib/validators/reply_by_email_address_validator_spec.rb
Normal file
41
spec/lib/validators/reply_by_email_address_validator_spec.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ReplyByEmailAddressValidator do
|
||||
|
||||
describe '#valid_value?' do
|
||||
subject(:validator) { described_class.new }
|
||||
|
||||
it "returns true for blank values" do
|
||||
expect(validator.valid_value?('')).to eq(true)
|
||||
expect(validator.valid_value?(nil)).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if value is not an email address" do
|
||||
expect(validator.valid_value?('WAT%{reply_key}.com')).to eq(false)
|
||||
expect(validator.valid_value?('word +%{reply_key}@example.com')).to eq(false)
|
||||
end
|
||||
|
||||
it "returns false if value does not contain '%{reply_key}'" do
|
||||
expect(validator.valid_value?('foo@bar.com')).to eq(false)
|
||||
end
|
||||
|
||||
it "returns true if value does not contain '%{reply_key}' but 'find_related_post_with_key' is also disabled" do
|
||||
SiteSetting.find_related_post_with_key = false
|
||||
expect(validator.valid_value?('foo@bar.com')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if value is the same as SiteSetting.notification_email" do
|
||||
SiteSetting.expects(:notification_email).returns("foo@bar.com")
|
||||
expect(validator.valid_value?('foo+%{reply_key}@bar.com')).to eq(false)
|
||||
end
|
||||
|
||||
it "returns true when value is OK" do
|
||||
SiteSetting.expects(:notification_email).returns("foo@bar.com")
|
||||
expect(validator.valid_value?('bar%{reply_key}@foo.com')).to eq(true)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
33
spec/lib/validators/reply_by_email_enabled_validator_spec.rb
Normal file
33
spec/lib/validators/reply_by_email_enabled_validator_spec.rb
Normal file
@@ -0,0 +1,33 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe ReplyByEmailEnabledValidator do
|
||||
|
||||
describe '#valid_value?' do
|
||||
subject(:validator) { described_class.new }
|
||||
|
||||
it "only validates when enabling the setting" do
|
||||
expect(validator.valid_value?("f")).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if reply_by_email_address is missing" do
|
||||
SiteSetting.expects(:reply_by_email_address).returns("")
|
||||
expect(validator.valid_value?("t")).to eq(false)
|
||||
end
|
||||
|
||||
it "returns false if email polling is disabled" do
|
||||
SiteSetting.expects(:reply_by_email_address).returns("foo.%{reply_key}+42@bar.com")
|
||||
SiteSetting.expects(:email_polling_enabled?).returns(false)
|
||||
expect(validator.valid_value?("t")).to eq(false)
|
||||
end
|
||||
|
||||
it "returns true when email polling is enabled and the reply_by_email_address is configured" do
|
||||
SiteSetting.expects(:reply_by_email_address).returns("foo.%{reply_key}+42@bar.com")
|
||||
SiteSetting.expects(:email_polling_enabled?).returns(true)
|
||||
expect(validator.valid_value?("t")).to eq(true)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe SearchTokenizeChineseValidator do
|
||||
it 'does not allow search_tokenize_chinese to be enabled when search_tokenize_japanese is enabled' do
|
||||
SiteSetting.search_tokenize_japanese = true
|
||||
|
||||
expect { SiteSetting.search_tokenize_chinese = true }.to raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe SearchTokenizeJapaneseValidator do
|
||||
it 'does not allow search_tokenize_japanese to be enabled when search_tokenize_chinese is enabled' do
|
||||
SiteSetting.search_tokenize_chinese = true
|
||||
|
||||
expect { SiteSetting.search_tokenize_japanese = true }.to raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,30 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe SelectableAvatarsEnabledValidator do
|
||||
describe '#valid_value?' do
|
||||
subject(:validator) { described_class.new }
|
||||
|
||||
it "returns true when disabling" do
|
||||
SiteSetting.selectable_avatars = ""
|
||||
expect(validator.valid_value?("f")).to eq(true)
|
||||
|
||||
SiteSetting.selectable_avatars = [Fabricate(:image_upload), Fabricate(:image_upload)]
|
||||
expect(validator.valid_value?("f")).to eq(true)
|
||||
end
|
||||
|
||||
it "returns true when there are at least two selectable avatars" do
|
||||
SiteSetting.selectable_avatars = [Fabricate(:image_upload), Fabricate(:image_upload)]
|
||||
expect(validator.valid_value?("t")).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false when selectable avatars is blank or has one avatar" do
|
||||
SiteSetting.selectable_avatars = ""
|
||||
expect(validator.valid_value?("t")).to eq(false)
|
||||
|
||||
SiteSetting.selectable_avatars = [Fabricate(:image_upload)]
|
||||
expect(validator.valid_value?("t")).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
53
spec/lib/validators/sso_overrides_email_validator_spec.rb
Normal file
53
spec/lib/validators/sso_overrides_email_validator_spec.rb
Normal file
@@ -0,0 +1,53 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe SsoOverridesEmailValidator do
|
||||
subject { described_class.new }
|
||||
|
||||
describe '#valid_value?' do
|
||||
describe "when 'email editable' is true" do
|
||||
before do
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.email_editable = true
|
||||
end
|
||||
|
||||
describe 'when val is false' do
|
||||
it 'should be valid' do
|
||||
expect(subject.valid_value?('f')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when value is true' do
|
||||
it 'should not be valid' do
|
||||
expect(subject.valid_value?('t')).to eq(false)
|
||||
|
||||
expect(subject.error_message).to eq(I18n.t(
|
||||
'site_settings.errors.email_editable_enabled'
|
||||
))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "when 'email editable' is false" do
|
||||
before do
|
||||
SiteSetting.discourse_connect_url = "https://www.example.com/sso"
|
||||
SiteSetting.enable_discourse_connect = true
|
||||
SiteSetting.email_editable = false
|
||||
end
|
||||
|
||||
describe 'when value is false' do
|
||||
it 'should be valid' do
|
||||
expect(subject.valid_value?('f')).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when value is true' do
|
||||
it 'should be valid' do
|
||||
expect(subject.valid_value?('t')).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
102
spec/lib/validators/string_setting_validator_spec.rb
Normal file
102
spec/lib/validators/string_setting_validator_spec.rb
Normal file
@@ -0,0 +1,102 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe StringSettingValidator do
|
||||
|
||||
describe '#valid_value?' do
|
||||
shared_examples "for all StringSettingValidator opts" do
|
||||
it "returns true for blank values" do
|
||||
expect(validator.valid_value?('')).to eq(true)
|
||||
expect(validator.valid_value?(nil)).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a regex' do
|
||||
subject(:validator) { described_class.new(regex: 'bacon') }
|
||||
|
||||
include_examples "for all StringSettingValidator opts"
|
||||
|
||||
it "returns true if value matches the regex" do
|
||||
expect(validator.valid_value?('The bacon is delicious')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if the value doesn't match the regex" do
|
||||
expect(validator.valid_value?('The vegetables are delicious')).to eq(false)
|
||||
end
|
||||
|
||||
it "test some other regexes" do
|
||||
v = described_class.new(regex: '^(chocolate|banana)$')
|
||||
expect(v.valid_value?('chocolate')).to eq(true)
|
||||
expect(v.valid_value?('chocolates')).to eq(false)
|
||||
|
||||
v = described_class.new(regex: '^[\w]+$')
|
||||
expect(v.valid_value?('the_file')).to eq(true)
|
||||
expect(v.valid_value?('the_file.bat')).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with min' do
|
||||
subject(:validator) { described_class.new(min: 2) }
|
||||
|
||||
include_examples "for all StringSettingValidator opts"
|
||||
|
||||
it "returns true if length is ok" do
|
||||
expect(validator.valid_value?('ok')).to eq(true)
|
||||
expect(validator.valid_value?('yep long enough')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if too short" do
|
||||
expect(validator.valid_value?('x')).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with max' do
|
||||
subject(:validator) { described_class.new(max: 5) }
|
||||
|
||||
include_examples "for all StringSettingValidator opts"
|
||||
|
||||
it "returns true if length is ok" do
|
||||
expect(validator.valid_value?('Z')).to eq(true)
|
||||
expect(validator.valid_value?('abcde')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if too long" do
|
||||
expect(validator.valid_value?('banana')).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'combinations of options' do
|
||||
it "min and regex" do
|
||||
v = described_class.new(regex: '^[\w]+$', min: 3)
|
||||
expect(v.valid_value?('chocolate')).to eq(true)
|
||||
expect(v.valid_value?('hi')).to eq(false)
|
||||
expect(v.valid_value?('game.exe')).to eq(false)
|
||||
end
|
||||
|
||||
it "max and regex" do
|
||||
v = described_class.new(regex: '^[\w]+$', max: 5)
|
||||
expect(v.valid_value?('chocolate')).to eq(false)
|
||||
expect(v.valid_value?('a_b_c')).to eq(true)
|
||||
expect(v.valid_value?('a b c')).to eq(false)
|
||||
end
|
||||
|
||||
it "min and max" do
|
||||
v = described_class.new(min: 3, max: 5)
|
||||
expect(v.valid_value?('chocolate')).to eq(false)
|
||||
expect(v.valid_value?('a')).to eq(false)
|
||||
expect(v.valid_value?('a b c')).to eq(true)
|
||||
expect(v.valid_value?('a b')).to eq(true)
|
||||
end
|
||||
|
||||
it "min, max, and regex" do
|
||||
v = described_class.new(min: 3, max: 12, regex: 'bacon')
|
||||
expect(v.valid_value?('go bacon!')).to eq(true)
|
||||
expect(v.valid_value?('sprinkle bacon on your cereal')).to eq(false)
|
||||
expect(v.valid_value?('ba')).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
71
spec/lib/validators/topic_title_length_validator_spec.rb
Normal file
71
spec/lib/validators/topic_title_length_validator_spec.rb
Normal file
@@ -0,0 +1,71 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require 'validators/topic_title_length_validator'
|
||||
|
||||
describe TopicTitleLengthValidator do
|
||||
|
||||
# simulate Rails behavior (singleton)
|
||||
def validate
|
||||
@validator ||= TopicTitleLengthValidator.new(attributes: :title)
|
||||
@validator.validate_each(record, :title, record.title)
|
||||
end
|
||||
|
||||
shared_examples "validating any topic title" do
|
||||
it 'adds an error when topic title is greater than SiteSetting.max_topic_title_length' do
|
||||
record.title = 'a' * (SiteSetting.max_topic_title_length + 1)
|
||||
validate
|
||||
expect(record.errors[:title]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
describe 'topic' do
|
||||
let(:record) { Fabricate.build(:topic) }
|
||||
|
||||
it 'adds an error when topic title is shorter than SiteSetting.min_topic_title_length' do
|
||||
record.title = 'a' * (SiteSetting.min_topic_title_length - 1)
|
||||
validate
|
||||
expect(record.errors[:title]).to be_present
|
||||
end
|
||||
|
||||
it 'does not add an error when length is good' do
|
||||
record.title = 'a' * (SiteSetting.min_topic_title_length)
|
||||
validate
|
||||
expect(record.errors[:title]).to_not be_present
|
||||
end
|
||||
|
||||
it 'is up to date' do
|
||||
record.title = 'a' * (SiteSetting.min_topic_title_length)
|
||||
validate
|
||||
expect(record.errors[:title]).to_not be_present
|
||||
|
||||
SiteSetting.min_topic_title_length = 2
|
||||
|
||||
record.title = 'aaa'
|
||||
validate
|
||||
expect(record.errors[:title]).to_not be_present
|
||||
end
|
||||
|
||||
include_examples "validating any topic title"
|
||||
end
|
||||
|
||||
describe 'private message' do
|
||||
let(:record) { Fabricate.build(:private_message_topic) }
|
||||
|
||||
it 'adds an error when topic title is shorter than SiteSetting.min_personal_message_title_length' do
|
||||
record.title = 'a' * (SiteSetting.min_personal_message_title_length - 1)
|
||||
validate
|
||||
expect(record.errors[:title]).to be_present
|
||||
end
|
||||
|
||||
it 'does not add an error when topic title is shorter than SiteSetting.min_topic_title_length' do
|
||||
record.title = 'a' * (SiteSetting.min_personal_message_title_length)
|
||||
validate
|
||||
expect(record.errors[:title]).to_not be_present
|
||||
end
|
||||
|
||||
include_examples "validating any topic title"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,38 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe UnicodeUsernameAllowlistValidator do
|
||||
subject { described_class.new }
|
||||
|
||||
it "allows an empty allowlist" do
|
||||
expect(subject.valid_value?("")).to eq(true)
|
||||
expect(subject.error_message).to be_blank
|
||||
end
|
||||
|
||||
it "disallows leading and trailing slashes" do
|
||||
expected_error = I18n.t("site_settings.errors.allowed_unicode_usernames.leading_trailing_slash")
|
||||
|
||||
expect(subject.valid_value?("/foo/")).to eq(false)
|
||||
expect(subject.error_message).to eq(expected_error)
|
||||
|
||||
expect(subject.valid_value?("foo/")).to eq(true)
|
||||
expect(subject.error_message).to be_blank
|
||||
|
||||
expect(subject.valid_value?("/foo")).to eq(true)
|
||||
expect(subject.error_message).to be_blank
|
||||
|
||||
expect(subject.valid_value?("f/o/o")).to eq(true)
|
||||
expect(subject.error_message).to be_blank
|
||||
|
||||
expect(subject.valid_value?("/foo/i")).to eq(false)
|
||||
expect(subject.error_message).to eq(expected_error)
|
||||
end
|
||||
|
||||
it "detects invalid regular expressions" do
|
||||
expected_error = I18n.t("site_settings.errors.allowed_unicode_usernames.regex_invalid", error: "")
|
||||
|
||||
expect(subject.valid_value?("\\p{Foo}")).to eq(false)
|
||||
expect(subject.error_message).to start_with(expected_error)
|
||||
end
|
||||
end
|
||||
27
spec/lib/validators/unicode_username_validator_spec.rb
Normal file
27
spec/lib/validators/unicode_username_validator_spec.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe UnicodeUsernameValidator do
|
||||
subject { described_class.new }
|
||||
|
||||
it "disallows Unicode usernames when external system avatars are disabled" do
|
||||
SiteSetting.external_system_avatars_enabled = false
|
||||
|
||||
expect(subject.valid_value?("t")).to eq(false)
|
||||
expect(subject.error_message).to eq(I18n.t("site_settings.errors.unicode_usernames_avatars"))
|
||||
|
||||
expect(subject.valid_value?("f")).to eq(true)
|
||||
expect(subject.error_message).to be_blank
|
||||
end
|
||||
|
||||
it "allows Unicode usernames when external system avatars are enabled" do
|
||||
SiteSetting.external_system_avatars_enabled = true
|
||||
|
||||
expect(subject.valid_value?("t")).to eq(true)
|
||||
expect(subject.error_message).to be_blank
|
||||
|
||||
expect(subject.valid_value?("f")).to eq(true)
|
||||
expect(subject.error_message).to be_blank
|
||||
end
|
||||
end
|
||||
110
spec/lib/validators/upload_validator_spec.rb
Normal file
110
spec/lib/validators/upload_validator_spec.rb
Normal file
@@ -0,0 +1,110 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe UploadValidator do
|
||||
subject(:validator) { described_class.new }
|
||||
|
||||
describe 'validate' do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
let(:filename) { "discourse.csv" }
|
||||
let(:csv_file) { file_from_fixtures(filename, "csv") }
|
||||
|
||||
it "should create an invalid upload when the filename is blank" do
|
||||
SiteSetting.authorized_extensions = "*"
|
||||
created_upload = UploadCreator.new(csv_file, nil).create_for(user.id)
|
||||
validator.validate(created_upload)
|
||||
expect(created_upload).to_not be_valid
|
||||
expect(created_upload.errors.full_messages.first).to include(I18n.t("activerecord.errors.messages.blank"))
|
||||
end
|
||||
|
||||
it "allows 'gz' as extension when uploading export file" do
|
||||
SiteSetting.authorized_extensions = ""
|
||||
|
||||
expect(UploadCreator.new(csv_file, "#{filename}.zip", for_export: true).create_for(user.id)).to be_valid
|
||||
end
|
||||
|
||||
it "allows uses max_export_file_size_kb when uploading export file" do
|
||||
SiteSetting.max_attachment_size_kb = "0"
|
||||
SiteSetting.authorized_extensions = "zip"
|
||||
|
||||
expect(UploadCreator.new(csv_file, "#{filename}.zip", for_export: true).create_for(user.id)).to be_valid
|
||||
end
|
||||
|
||||
describe "size validation" do
|
||||
it "does not allow images that are too large" do
|
||||
SiteSetting.max_image_size_kb = 1536
|
||||
upload = Fabricate.build(:upload,
|
||||
user: Fabricate(:admin),
|
||||
original_filename: "test.png",
|
||||
filesize: 2097152
|
||||
)
|
||||
subject.validate(upload)
|
||||
expect(upload.errors.full_messages.first).to eq(
|
||||
"Filesize #{I18n.t("upload.images.too_large_humanized", max_size: "1.5 MB")}"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when allow_staff_to_upload_any_file_in_pm is true' do
|
||||
it 'should allow uploads for pm' do
|
||||
upload = Fabricate.build(:upload,
|
||||
user: Fabricate(:admin),
|
||||
original_filename: 'test.ico',
|
||||
for_private_message: true
|
||||
)
|
||||
|
||||
expect(subject.validate(upload)).to eq(true)
|
||||
end
|
||||
|
||||
describe 'for a normal user' do
|
||||
it 'should not allow uploads for pm' do
|
||||
upload = Fabricate.build(:upload,
|
||||
user: Fabricate(:user),
|
||||
original_filename: 'test.ico',
|
||||
for_private_message: true
|
||||
)
|
||||
|
||||
expect(subject.validate(upload)).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'upload for site settings' do
|
||||
fab!(:user) { Fabricate(:admin) }
|
||||
|
||||
let(:upload) do
|
||||
Fabricate.build(:upload,
|
||||
user: user,
|
||||
original_filename: 'test.ico',
|
||||
for_site_setting: true
|
||||
)
|
||||
end
|
||||
|
||||
before do
|
||||
SiteSetting.authorized_extensions = 'png'
|
||||
end
|
||||
|
||||
describe 'for admin user' do
|
||||
it 'should allow the upload' do
|
||||
expect(subject.validate(upload)).to eq(true)
|
||||
end
|
||||
|
||||
describe 'when filename is invalid' do
|
||||
it 'should not allow the upload' do
|
||||
upload.original_filename = 'test.txt'
|
||||
expect(subject.validate(upload)).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'for normal user' do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
||||
it 'should not allow the upload' do
|
||||
expect(subject.validate(upload)).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
37
spec/lib/validators/url_validator_spec.rb
Normal file
37
spec/lib/validators/url_validator_spec.rb
Normal file
@@ -0,0 +1,37 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require 'validators/topic_title_length_validator'
|
||||
|
||||
RSpec.describe UrlValidator do
|
||||
let(:record) { Fabricate.build(:user_profile, user: Fabricate.build(:user)) }
|
||||
let(:validator) { described_class.new(attributes: :website) }
|
||||
subject(:validate) { validator.validate_each(record, :website, record.website) }
|
||||
|
||||
[
|
||||
"http://https://google.com",
|
||||
"http://google/",
|
||||
"ftp://ftp.google.com",
|
||||
"http:///what.is.this",
|
||||
'http://meta.discourse.org TEST'
|
||||
].each do |invalid_url|
|
||||
it "#{invalid_url} should not be valid" do
|
||||
record.website = invalid_url
|
||||
validate
|
||||
expect(record.errors[:website]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
[
|
||||
"http://discourse.productions",
|
||||
"https://google.com",
|
||||
'http://xn--nw2a.xn--j6w193g/',
|
||||
"http://見.香港/",
|
||||
].each do |valid_url|
|
||||
it "#{valid_url} should be valid" do
|
||||
record.website = valid_url
|
||||
validate
|
||||
expect(record.errors[:website]).to_not be_present
|
||||
end
|
||||
end
|
||||
end
|
||||
47
spec/lib/validators/user_full_name_validator_spec.rb
Normal file
47
spec/lib/validators/user_full_name_validator_spec.rb
Normal file
@@ -0,0 +1,47 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
describe UserFullNameValidator do
|
||||
let(:validator) { described_class.new(attributes: :name) }
|
||||
subject(:validate) { validator.validate_each(record, :name, @name) }
|
||||
let(:record) { Fabricate.build(:user, name: @name) }
|
||||
|
||||
context "name not required" do
|
||||
before { SiteSetting.full_name_required = false }
|
||||
|
||||
it "allows no name" do
|
||||
@name = nil
|
||||
validate
|
||||
expect(record.errors[:name]).not_to be_present
|
||||
end
|
||||
|
||||
it "allows name being set" do
|
||||
@name = "Bigfoot"
|
||||
validate
|
||||
expect(record.errors[:name]).not_to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context "name required" do
|
||||
before { SiteSetting.full_name_required = true }
|
||||
|
||||
it "adds error for nil name" do
|
||||
@name = nil
|
||||
validate
|
||||
expect(record.errors[:name]).to be_present
|
||||
end
|
||||
|
||||
it "adds error for empty string name" do
|
||||
@name = ""
|
||||
validate
|
||||
expect(record.errors[:name]).to be_present
|
||||
end
|
||||
|
||||
it "allows name being set" do
|
||||
@name = "Bigfoot"
|
||||
validate
|
||||
expect(record.errors[:name]).not_to be_present
|
||||
end
|
||||
end
|
||||
end
|
||||
44
spec/lib/validators/username_setting_validator_spec.rb
Normal file
44
spec/lib/validators/username_setting_validator_spec.rb
Normal file
@@ -0,0 +1,44 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe UsernameSettingValidator do
|
||||
describe '#valid_value?' do
|
||||
subject(:validator) { described_class.new }
|
||||
|
||||
it "returns true for blank values" do
|
||||
expect(validator.valid_value?('')).to eq(true)
|
||||
expect(validator.valid_value?(nil)).to eq(true)
|
||||
end
|
||||
|
||||
it "returns true if value matches an existing user's username" do
|
||||
Fabricate(:user, username: 'vader')
|
||||
expect(validator.valid_value?('vader')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if value does not match a user's username" do
|
||||
expect(validator.valid_value?('no way')).to eq(false)
|
||||
end
|
||||
|
||||
context "regex support" do
|
||||
fab!(:darthvader) { Fabricate(:user, username: 'darthvader') }
|
||||
fab!(:luke) { Fabricate(:user, username: 'luke') }
|
||||
|
||||
it "returns false if regex doesn't match" do
|
||||
v = described_class.new(regex: 'darth')
|
||||
expect(v.valid_value?('luke')).to eq(false)
|
||||
expect(v.valid_value?('vader')).to eq(false)
|
||||
end
|
||||
|
||||
it "returns true if regex matches" do
|
||||
v = described_class.new(regex: 'darth')
|
||||
expect(v.valid_value?('darthvader')).to eq(true)
|
||||
end
|
||||
|
||||
it "returns false if regex matches but username doesn't match a user" do
|
||||
v = described_class.new(regex: 'darth')
|
||||
expect(v.valid_value?('darthmaul')).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user