123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- # frozen_string_literal: true
- require 'rails_helper'
- RSpec.describe SpamCheck do
- let!(:sender) { Fabricate(:account) }
- let!(:alice) { Fabricate(:account, username: 'alice') }
- let!(:bob) { Fabricate(:account, username: 'bob') }
- def status_with_html(text, options = {})
- status = PostStatusService.new.call(sender, { text: text }.merge(options))
- status.update_columns(text: Formatter.instance.format(status), local: false)
- status
- end
- describe '#hashable_text' do
- it 'removes mentions from HTML for remote statuses' do
- status = status_with_html('@alice Hello')
- expect(described_class.new(status).hashable_text).to eq 'hello'
- end
- it 'removes mentions from text for local statuses' do
- status = PostStatusService.new.call(alice, text: "Hey @#{sender.username}, how are you?")
- expect(described_class.new(status).hashable_text).to eq 'hey , how are you?'
- end
- end
- describe '#insufficient_data?' do
- it 'returns true when there is no text' do
- status = status_with_html('@alice')
- expect(described_class.new(status).insufficient_data?).to be true
- end
- it 'returns false when there is text' do
- status = status_with_html('@alice h')
- expect(described_class.new(status).insufficient_data?).to be false
- end
- end
- describe '#digest' do
- it 'returns a string' do
- status = status_with_html('@alice Hello world')
- expect(described_class.new(status).digest).to be_a String
- end
- end
- describe '#spam?' do
- it 'returns false for a unique status' do
- status = status_with_html('@alice Hello')
- expect(described_class.new(status).spam?).to be false
- end
- it 'returns false for different statuses to the same recipient' do
- status1 = status_with_html('@alice Hello')
- described_class.new(status1).remember!
- status2 = status_with_html('@alice Are you available to talk?')
- expect(described_class.new(status2).spam?).to be false
- end
- it 'returns false for statuses with different content warnings' do
- status1 = status_with_html('@alice Are you available to talk?')
- described_class.new(status1).remember!
- status2 = status_with_html('@alice Are you available to talk?', spoiler_text: 'This is a completely different matter than what I was talking about previously, I swear!')
- expect(described_class.new(status2).spam?).to be false
- end
- it 'returns false for different statuses to different recipients' do
- status1 = status_with_html('@alice How is it going?')
- described_class.new(status1).remember!
- status2 = status_with_html('@bob Are you okay?')
- expect(described_class.new(status2).spam?).to be false
- end
- it 'returns false for very short different statuses to different recipients' do
- status1 = status_with_html('@alice 🙄')
- described_class.new(status1).remember!
- status2 = status_with_html('@bob Huh?')
- expect(described_class.new(status2).spam?).to be false
- end
- it 'returns false for statuses with no text' do
- status1 = status_with_html('@alice')
- described_class.new(status1).remember!
- status2 = status_with_html('@bob')
- expect(described_class.new(status2).spam?).to be false
- end
- it 'returns true for duplicate statuses to the same recipient' do
- described_class::THRESHOLD.times do
- status1 = status_with_html('@alice Hello')
- described_class.new(status1).remember!
- end
- status2 = status_with_html('@alice Hello')
- expect(described_class.new(status2).spam?).to be true
- end
- it 'returns true for duplicate statuses to different recipients' do
- described_class::THRESHOLD.times do
- status1 = status_with_html('@alice Hello')
- described_class.new(status1).remember!
- end
- status2 = status_with_html('@bob Hello')
- expect(described_class.new(status2).spam?).to be true
- end
- it 'returns true for nearly identical statuses with random numbers' do
- source_text = 'Sodium, atomic number 11, was first isolated by Humphry Davy in 1807. A chemical component of salt, he named it Na in honor of the saltiest region on earth, North America.'
- described_class::THRESHOLD.times do
- status1 = status_with_html('@alice ' + source_text + ' 1234')
- described_class.new(status1).remember!
- end
- status2 = status_with_html('@bob ' + source_text + ' 9568')
- expect(described_class.new(status2).spam?).to be true
- end
- end
- describe '#skip?' do
- it 'returns true when the sender is already silenced' do
- status = status_with_html('@alice Hello')
- sender.silence!
- expect(described_class.new(status).skip?).to be true
- end
- it 'returns true when the mentioned person follows the sender' do
- status = status_with_html('@alice Hello')
- alice.follow!(sender)
- expect(described_class.new(status).skip?).to be true
- end
- it 'returns false when even one mentioned person doesn\'t follow the sender' do
- status = status_with_html('@alice @bob Hello')
- alice.follow!(sender)
- expect(described_class.new(status).skip?).to be false
- end
- it 'returns true when the sender is replying to a status that mentions the sender' do
- parent = PostStatusService.new.call(alice, text: "Hey @#{sender.username}, how are you?")
- status = status_with_html('@alice @bob Hello', thread: parent)
- expect(described_class.new(status).skip?).to be true
- end
- end
- describe '#remember!' do
- let(:status) { status_with_html('@alice') }
- let(:spam_check) { described_class.new(status) }
- let(:redis_key) { spam_check.send(:redis_key) }
- it 'remembers' do
- expect(Redis.current.exists?(redis_key)).to be true
- spam_check.remember!
- expect(Redis.current.exists?(redis_key)).to be true
- end
- end
- describe '#reset!' do
- let(:status) { status_with_html('@alice') }
- let(:spam_check) { described_class.new(status) }
- let(:redis_key) { spam_check.send(:redis_key) }
- before do
- spam_check.remember!
- end
- it 'resets' do
- expect(Redis.current.exists?(redis_key)).to be true
- spam_check.reset!
- expect(Redis.current.exists?(redis_key)).to be false
- end
- end
- describe '#flag!' do
- let!(:status1) { status_with_html('@alice General Kenobi you are a bold one') }
- let!(:status2) { status_with_html('@alice @bob General Kenobi, you are a bold one') }
- before do
- described_class.new(status1).remember!
- described_class.new(status2).flag!
- end
- it 'creates a report about the account' do
- expect(sender.targeted_reports.unresolved.count).to eq 1
- end
- it 'attaches both matching statuses to the report' do
- expect(sender.targeted_reports.first.status_ids).to include(status1.id, status2.id)
- end
- end
- end
|