208 lines
7.2 KiB
Ruby
208 lines
7.2 KiB
Ruby
# frozen_string_literal: true
|
||
|
||
require 'rails_helper'
|
||
|
||
describe UsernameValidator do
|
||
def expect_valid(*usernames)
|
||
usernames.each do |username|
|
||
validator = UsernameValidator.new(username)
|
||
|
||
aggregate_failures do
|
||
expect(validator.valid_format?).to eq(true), "expected '#{username}' to be valid"
|
||
expect(validator.errors).to be_empty
|
||
end
|
||
end
|
||
end
|
||
|
||
def expect_invalid(*usernames, error_message:)
|
||
usernames.each do |username|
|
||
validator = UsernameValidator.new(username)
|
||
|
||
aggregate_failures do
|
||
expect(validator.valid_format?).to eq(false), "expected '#{username}' to be invalid"
|
||
expect(validator.errors).to include(error_message)
|
||
end
|
||
end
|
||
end
|
||
|
||
shared_examples 'ASCII username' do
|
||
it 'is invalid when the username is blank' do
|
||
expect_invalid('', error_message: I18n.t(:'user.username.blank'))
|
||
end
|
||
|
||
it 'is invalid when the username is too short' do
|
||
SiteSetting.min_username_length = 4
|
||
|
||
expect_invalid('a', 'ab', 'abc',
|
||
error_message: I18n.t(:'user.username.short', min: 4))
|
||
end
|
||
|
||
it 'is valid when the username has the minimum length' do
|
||
SiteSetting.min_username_length = 4
|
||
|
||
expect_valid('abcd')
|
||
end
|
||
|
||
it 'is invalid when the username is too long' do
|
||
SiteSetting.max_username_length = 8
|
||
|
||
expect_invalid('abcdefghi',
|
||
error_message: I18n.t(:'user.username.long', max: 8))
|
||
end
|
||
|
||
it 'is valid when the username has the maximum length' do
|
||
SiteSetting.max_username_length = 8
|
||
|
||
expect_valid('abcdefgh')
|
||
end
|
||
|
||
it 'is valid when the username contains alphanumeric characters, dots, underscores and dashes' do
|
||
expect_valid('ab-cd.123_ABC-xYz')
|
||
end
|
||
|
||
it 'is invalid when the username contains non-alphanumeric characters other than dots, underscores and dashes' do
|
||
expect_invalid('abc|', 'a#bc', 'abc xyz',
|
||
error_message: I18n.t(:'user.username.characters'))
|
||
end
|
||
|
||
it 'is valid when the username starts with a alphanumeric character or underscore' do
|
||
expect_valid('abcd', '1abc', '_abc')
|
||
end
|
||
|
||
it 'is invalid when the username starts with a dot or dash' do
|
||
expect_invalid('.abc', '-abc',
|
||
error_message: I18n.t(:'user.username.must_begin_with_alphanumeric_or_underscore'))
|
||
end
|
||
|
||
it 'is valid when the username ends with a alphanumeric character' do
|
||
expect_valid('abcd', 'abc9')
|
||
end
|
||
|
||
it 'is invalid when the username ends with an underscore, a dot or dash' do
|
||
expect_invalid('abc_', 'abc.', 'abc-',
|
||
error_message: I18n.t(:'user.username.must_end_with_alphanumeric'))
|
||
end
|
||
|
||
it 'is invalid when the username contains consecutive underscores, dots or dashes' do
|
||
expect_invalid('a__bc', 'a..bc', 'a--bc',
|
||
error_message: I18n.t(:'user.username.must_not_contain_two_special_chars_in_seq'))
|
||
end
|
||
|
||
it 'is invalid when the username ends with certain file extensions' do
|
||
expect_invalid('abc.json', 'abc.png',
|
||
error_message: I18n.t(:'user.username.must_not_end_with_confusing_suffix'))
|
||
end
|
||
end
|
||
|
||
context 'when Unicode usernames are disabled' do
|
||
before { SiteSetting.unicode_usernames = false }
|
||
|
||
include_examples 'ASCII username'
|
||
|
||
it 'is invalid when the username contains non-ASCII characters except dots, underscores and dashes' do
|
||
expect_invalid('abcö', 'abc象',
|
||
error_message: I18n.t(:'user.username.characters'))
|
||
end
|
||
end
|
||
|
||
context 'when Unicode usernames are enabled' do
|
||
before { SiteSetting.unicode_usernames = true }
|
||
|
||
context "ASCII usernames" do
|
||
include_examples 'ASCII username'
|
||
end
|
||
|
||
context "Unicode usernames" do
|
||
before { SiteSetting.min_username_length = 1 }
|
||
|
||
it 'is invalid when the username is too short' do
|
||
SiteSetting.min_username_length = 3
|
||
|
||
expect_invalid('鳥', 'পাখি',
|
||
error_message: I18n.t(:'user.username.short', min: 3))
|
||
end
|
||
|
||
it 'is valid when the username has the minimum length' do
|
||
SiteSetting.min_username_length = 2
|
||
|
||
expect_valid('পাখি', 'طائر')
|
||
end
|
||
|
||
it 'is invalid when the username is too long' do
|
||
SiteSetting.max_username_length = 8
|
||
|
||
expect_invalid('חוטב_עצים', 'Holzfäller',
|
||
error_message: I18n.t(:'user.username.long', max: 8))
|
||
end
|
||
|
||
it 'is valid when the username has the maximum length' do
|
||
SiteSetting.max_username_length = 9
|
||
|
||
expect_valid('Дровосек', 'چوب-لباسی', 'தமிழ்-தமிழ்')
|
||
end
|
||
|
||
it 'is invalid when the username has too many Unicode codepoints' do
|
||
SiteSetting.max_username_length = 30
|
||
|
||
expect_invalid('য়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়ায়া',
|
||
error_message: I18n.t(:'user.username.too_long'))
|
||
end
|
||
|
||
it 'is valid when the username contains Unicode letters' do
|
||
expect_valid('鳥', 'طائر', 'թռչուն', 'πουλί', 'পাখি', 'madár', '새',
|
||
'پرنده', 'птица', 'fågel', 'นก', 'پرندے', 'ציפור')
|
||
end
|
||
|
||
it 'is valid when the username contains numbers from the Nd or Nl Unicode category' do
|
||
expect_valid('arabic٠١٢٣٤٥٦٧٨٩', 'bengali০১২৩৪৫৬৭৮৯', 'romanⅥ', 'hangzhou〺')
|
||
end
|
||
|
||
it 'is invalid when the username contains numbers from the No Unicode category' do
|
||
expect_invalid('circled㊸', 'fraction¾',
|
||
error_message: I18n.t(:'user.username.characters'))
|
||
end
|
||
|
||
it 'is invalid when the username contains symbols or emojis' do
|
||
SiteSetting.min_username_length = 1
|
||
|
||
expect_invalid('©', '⇨', '“', '±', '‿', '😃', '🚗',
|
||
error_message: I18n.t(:'user.username.characters'))
|
||
end
|
||
|
||
it 'is invalid when the username contains zero width join characters' do
|
||
expect_invalid('ണ്', 'র্যাম',
|
||
error_message: I18n.t(:'user.username.characters'))
|
||
end
|
||
|
||
it 'is valid when the username ends with a Unicode Mark' do
|
||
expect_valid('தமிழ்')
|
||
end
|
||
|
||
it 'allows all Unicode letters when the allowlist is empty' do
|
||
expect_valid('鳥')
|
||
end
|
||
|
||
context "with Unicode allowlist" do
|
||
before { SiteSetting.allowed_unicode_username_characters = "[äöüÄÖÜß]" }
|
||
|
||
it 'is invalid when username contains non-allowlisted letters' do
|
||
expect_invalid('鳥', 'francès', error_message: I18n.t(:'user.username.characters'))
|
||
end
|
||
|
||
it 'is valid when username contains only allowlisted letters' do
|
||
expect_valid('Löwe', 'Ötzi')
|
||
end
|
||
|
||
it 'is valid when username contains only ASCII letters and numbers regardless of allowlist' do
|
||
expect_valid('a-z_A-Z.0-9')
|
||
end
|
||
|
||
it 'is valid after resetting the site setting' do
|
||
SiteSetting.allowed_unicode_username_characters = ""
|
||
expect_valid('鳥')
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|