bastodon/spec/models/tag_spec.rb
Eugen Rochko e7aa2be828
Change how hashtags are normalized (#18795)
* Change how hashtags are normalized

* Fix tests
2022-07-13 15:03:28 +02:00

165 lines
5 KiB
Ruby
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

require 'rails_helper'
RSpec.describe Tag, type: :model do
describe 'validations' do
it 'invalid with #' do
expect(Tag.new(name: '#hello_world')).to_not be_valid
end
it 'invalid with .' do
expect(Tag.new(name: '.abcdef123')).to_not be_valid
end
it 'invalid with spaces' do
expect(Tag.new(name: 'hello world')).to_not be_valid
end
it 'valid with ' do
expect(Tag.new(name: '')).to be_valid
end
end
describe 'HASHTAG_RE' do
subject { Tag::HASHTAG_RE }
it 'does not match URLs with anchors with non-hashtag characters' do
expect(subject.match('Check this out https://medium.com/@alice/some-article#.abcdef123')).to be_nil
end
it 'does not match URLs with hashtag-like anchors' do
expect(subject.match('https://en.wikipedia.org/wiki/Ghostbusters_(song)#Lawsuit')).to be_nil
end
it 'matches #' do
expect(subject.match('this is #').to_s).to eq ' #'
end
it 'matches digits at the start' do
expect(subject.match('hello #3d').to_s).to eq ' #3d'
end
it 'matches digits in the middle' do
expect(subject.match('hello #l33ts35k').to_s).to eq ' #l33ts35k'
end
it 'matches digits at the end' do
expect(subject.match('hello #world2016').to_s).to eq ' #world2016'
end
it 'matches underscores at the beginning' do
expect(subject.match('hello #_test').to_s).to eq ' #_test'
end
it 'matches underscores at the end' do
expect(subject.match('hello #test_').to_s).to eq ' #test_'
end
it 'matches underscores in the middle' do
expect(subject.match('hello #one_two_three').to_s).to eq ' #one_two_three'
end
it 'matches middle dots' do
expect(subject.match('hello #one·two·three').to_s).to eq ' #one·two·three'
end
it 'matches ZWNJ' do
expect(subject.match('just add #نرم‌افزار and').to_s).to eq ' #نرم‌افزار'
end
it 'does not match middle dots at the start' do
expect(subject.match('hello #·one·two·three')).to be_nil
end
it 'does not match middle dots at the end' do
expect(subject.match('hello #one·two·three·').to_s).to eq ' #one·two·three'
end
it 'does not match purely-numeric hashtags' do
expect(subject.match('hello #0123456')).to be_nil
end
end
describe '#to_param' do
it 'returns name' do
tag = Fabricate(:tag, name: 'foo')
expect(tag.to_param).to eq 'foo'
end
end
describe '.find_normalized' do
it 'returns tag for a multibyte case-insensitive name' do
upcase_string = 'abcABCやゆよ'
downcase_string = 'abcabcやゆよ';
tag = Fabricate(:tag, name: HashtagNormalizer.new.normalize(downcase_string))
expect(Tag.find_normalized(upcase_string)).to eq tag
end
end
describe '.matches_name' do
it 'returns tags for multibyte case-insensitive names' do
upcase_string = 'abcABCやゆよ'
downcase_string = 'abcabcやゆよ';
tag = Fabricate(:tag, name: HashtagNormalizer.new.normalize(downcase_string))
expect(Tag.matches_name(upcase_string)).to eq [tag]
end
it 'uses the LIKE operator' do
expect(Tag.matches_name('100%abc').to_sql).to eq %q[SELECT "tags".* FROM "tags" WHERE LOWER("tags"."name") LIKE LOWER('100abc%')]
end
end
describe '.matching_name' do
it 'returns tags for multibyte case-insensitive names' do
upcase_string = 'abcABCやゆよ'
downcase_string = 'abcabcやゆよ';
tag = Fabricate(:tag, name: HashtagNormalizer.new.normalize(downcase_string))
expect(Tag.matching_name(upcase_string)).to eq [tag]
end
end
describe '.find_or_create_by_names' do
it 'runs a passed block once per tag regardless of duplicates' do
upcase_string = 'abcABCやゆよ'
downcase_string = 'abcabcやゆよ';
count = 0
Tag.find_or_create_by_names([upcase_string, downcase_string]) do |tag|
count += 1
end
expect(count).to eq 1
end
end
describe '.search_for' do
it 'finds tag records with matching names' do
tag = Fabricate(:tag, name: "match")
_miss_tag = Fabricate(:tag, name: "miss")
results = Tag.search_for("match")
expect(results).to eq [tag]
end
it 'finds tag records in case insensitive' do
tag = Fabricate(:tag, name: "MATCH")
_miss_tag = Fabricate(:tag, name: "miss")
results = Tag.search_for("match")
expect(results).to eq [tag]
end
it 'finds the exact matching tag as the first item' do
similar_tag = Fabricate(:tag, name: "matchlater", reviewed_at: Time.now.utc)
tag = Fabricate(:tag, name: "match", reviewed_at: Time.now.utc)
results = Tag.search_for("match")
expect(results).to eq [tag, similar_tag]
end
end
end