diff options
Diffstat (limited to 'spec/services/spam/spam_action_service_spec.rb')
-rw-r--r-- | spec/services/spam/spam_action_service_spec.rb | 182 |
1 files changed, 137 insertions, 45 deletions
diff --git a/spec/services/spam/spam_action_service_spec.rb b/spec/services/spam/spam_action_service_spec.rb index 8edd9406bce..371923f1518 100644 --- a/spec/services/spam/spam_action_service_spec.rb +++ b/spec/services/spam/spam_action_service_spec.rb @@ -24,41 +24,16 @@ RSpec.describe Spam::SpamActionService do issue.spam = false end - describe '#initialize' do - subject { described_class.new(spammable: issue, request: request, user: user) } - - context 'when the request is nil' do - let(:request) { nil } - - it 'assembles the options with information from the spammable' do - aggregate_failures do - expect(subject.options[:ip_address]).to eq(issue.ip_address) - expect(subject.options[:user_agent]).to eq(issue.user_agent) - expect(subject.options.key?(:referrer)).to be_falsey - end - end - end - - context 'when the request is present' do - let(:request) { double(:request, env: env) } - - it 'assembles the options with information from the spammable' do - aggregate_failures do - expect(subject.options[:ip_address]).to eq(fake_ip) - expect(subject.options[:user_agent]).to eq(fake_user_agent) - expect(subject.options[:referrer]).to eq(fake_referrer) - end - end - end - end - shared_examples 'only checks for spam if a request is provided' do context 'when request is missing' do - subject { described_class.new(spammable: issue, request: nil, user: user) } + let(:request) { nil } it "doesn't check as spam" do - subject + expect(fake_verdict_service).not_to receive(:execute) + + response = subject + expect(response.message).to match(/request was not present/) expect(issue).not_to be_spam end end @@ -66,34 +41,88 @@ RSpec.describe Spam::SpamActionService do context 'when request exists' do it 'creates a spam log' do expect { subject } - .to log_spam(title: issue.title, description: issue.description, noteable_type: 'Issue') + .to log_spam(title: issue.title, description: issue.description, noteable_type: 'Issue') end end end + shared_examples 'creates a spam log' do + it do + expect { subject }.to change { SpamLog.count }.by(1) + + new_spam_log = SpamLog.last + expect(new_spam_log.user_id).to eq(user.id) + expect(new_spam_log.title).to eq(issue.title) + expect(new_spam_log.description).to eq(issue.description) + expect(new_spam_log.source_ip).to eq(fake_ip) + expect(new_spam_log.user_agent).to eq(fake_user_agent) + expect(new_spam_log.noteable_type).to eq('Issue') + expect(new_spam_log.via_api).to eq(false) + end + end + describe '#execute' do let(:request) { double(:request, env: env) } + let(:fake_captcha_verification_service) { double(:captcha_verification_service) } let(:fake_verdict_service) { double(:spam_verdict_service) } let(:allowlisted) { false } + let(:api) { nil } + let(:captcha_response) { 'abc123' } + let(:spam_log_id) { existing_spam_log.id } + let(:spam_params) do + Spam::SpamActionService.filter_spam_params!( + api: api, + captcha_response: captcha_response, + spam_log_id: spam_log_id + ) + end + + let(:verdict_service_opts) do + { + ip_address: fake_ip, + user_agent: fake_user_agent, + referrer: fake_referrer + } + end + + let(:verdict_service_args) do + { + target: issue, + user: user, + request: request, + options: verdict_service_opts, + context: { + action: :create, + target_type: 'Issue' + } + } + end let_it_be(:existing_spam_log) { create(:spam_log, user: user, recaptcha_verified: false) } subject do - described_service = described_class.new(spammable: issue, request: request, user: user) + described_service = described_class.new(spammable: issue, request: request, user: user, action: :create) allow(described_service).to receive(:allowlisted?).and_return(allowlisted) - described_service.execute(api: nil, recaptcha_verified: recaptcha_verified, spam_log_id: existing_spam_log.id) + described_service.execute(spam_params: spam_params) end before do - allow(Spam::SpamVerdictService).to receive(:new).and_return(fake_verdict_service) + allow(Captcha::CaptchaVerificationService).to receive(:new) { fake_captcha_verification_service } + allow(Spam::SpamVerdictService).to receive(:new).with(verdict_service_args).and_return(fake_verdict_service) end - context 'when reCAPTCHA was already verified' do - let(:recaptcha_verified) { true } + context 'when captcha response verification returns true' do + before do + expect(fake_captcha_verification_service) + .to receive(:execute).with(captcha_response: captcha_response, request: request) { true } + end it "doesn't check with the SpamVerdictService" do aggregate_failures do - expect(SpamLog).to receive(:verify_recaptcha!) + expect(SpamLog).to receive(:verify_recaptcha!).with( + user_id: user.id, + id: spam_log_id + ) expect(fake_verdict_service).not_to receive(:execute) end @@ -105,8 +134,11 @@ RSpec.describe Spam::SpamActionService do end end - context 'when reCAPTCHA was not verified' do - let(:recaptcha_verified) { false } + context 'when captcha response verification returns false' do + before do + expect(fake_captcha_verification_service) + .to receive(:execute).with(captcha_response: captcha_response, request: request) { false } + end context 'when spammable attributes have not changed' do before do @@ -120,6 +152,10 @@ RSpec.describe Spam::SpamActionService do end context 'when spammable attributes have changed' do + let(:expected_service_check_response_message) do + /check Issue spammable model for any errors or captcha requirement/ + end + before do issue.description = 'SPAM!' end @@ -130,7 +166,9 @@ RSpec.describe Spam::SpamActionService do it 'does not perform spam check' do expect(Spam::SpamVerdictService).not_to receive(:new) - subject + response = subject + + expect(response.message).to match(/user was allowlisted/) end end @@ -147,8 +185,9 @@ RSpec.describe Spam::SpamActionService do it_behaves_like 'only checks for spam if a request is provided' it 'marks as spam' do - subject + response = subject + expect(response.message).to match(expected_service_check_response_message) expect(issue).to be_spam end end @@ -157,8 +196,9 @@ RSpec.describe Spam::SpamActionService do it_behaves_like 'only checks for spam if a request is provided' it 'does not mark as spam' do - subject + response = subject + expect(response.message).to match(expected_service_check_response_message) expect(issue).not_to be_spam end end @@ -176,15 +216,19 @@ RSpec.describe Spam::SpamActionService do it_behaves_like 'only checks for spam if a request is provided' + it_behaves_like 'creates a spam log' + it 'does not mark as spam' do - subject + response = subject + expect(response.message).to match(expected_service_check_response_message) expect(issue).not_to be_spam end it 'marks as needing reCAPTCHA' do - subject + response = subject + expect(response.message).to match(expected_service_check_response_message) expect(issue.needs_recaptcha?).to be_truthy end end @@ -192,9 +236,12 @@ RSpec.describe Spam::SpamActionService do context 'when allow_possible_spam feature flag is true' do it_behaves_like 'only checks for spam if a request is provided' + it_behaves_like 'creates a spam log' + it 'does not mark as needing reCAPTCHA' do - subject + response = subject + expect(response.message).to match(expected_service_check_response_message) expect(issue.needs_recaptcha).to be_falsey end end @@ -209,6 +256,51 @@ RSpec.describe Spam::SpamActionService do expect { subject } .not_to change { SpamLog.count } end + + it 'clears spam flags' do + expect(issue).to receive(:clear_spam_flags!) + + subject + end + end + + context 'spam verdict service options' do + before do + allow(fake_verdict_service).to receive(:execute) { ALLOW } + end + + context 'when the request is nil' do + let(:request) { nil } + let(:issue_ip_address) { '1.2.3.4' } + let(:issue_user_agent) { 'lynx' } + let(:verdict_service_opts) do + { + ip_address: issue_ip_address, + user_agent: issue_user_agent + } + end + + before do + allow(issue).to receive(:ip_address) { issue_ip_address } + allow(issue).to receive(:user_agent) { issue_user_agent } + end + + it 'assembles the options with information from the spammable' do + # TODO: This code untestable, because we do not perform a verification if there is not a + # request. See corresponding comment in code + # expect(Spam::SpamVerdictService).to receive(:new).with(verdict_service_args) + + subject + end + end + + context 'when the request is present' do + it 'assembles the options with information from the request' do + expect(Spam::SpamVerdictService).to receive(:new).with(verdict_service_args) + + subject + end + end end end end |