123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- # frozen_string_literal: true
- require 'rails_helper'
- RSpec.describe NotifyService do
- subject { described_class.new.call(recipient, type, activity) }
- let(:user) { Fabricate(:user) }
- let(:recipient) { user.account }
- let(:sender) { Fabricate(:account, domain: 'example.com') }
- let(:activity) { Fabricate(:follow, account: sender, target_account: recipient) }
- let(:type) { :follow }
- it { expect { subject }.to change(Notification, :count).by(1) }
- it 'does not notify when sender is blocked' do
- recipient.block!(sender)
- expect { subject }.to_not change(Notification, :count)
- end
- it 'does not notify when sender is muted with hide_notifications' do
- recipient.mute!(sender, notifications: true)
- expect { subject }.to_not change(Notification, :count)
- end
- it 'does notify when sender is muted without hide_notifications' do
- recipient.mute!(sender, notifications: false)
- expect { subject }.to change(Notification, :count)
- end
- it 'does not notify when sender\'s domain is blocked' do
- recipient.block_domain!(sender.domain)
- expect { subject }.to_not change(Notification, :count)
- end
- it 'does still notify when sender\'s domain is blocked but sender is followed' do
- recipient.block_domain!(sender.domain)
- recipient.follow!(sender)
- expect { subject }.to change(Notification, :count)
- end
- it 'does not notify when sender is silenced and not followed' do
- sender.silence!
- subject
- expect(Notification.find_by(activity: activity).filtered?).to be true
- end
- it 'does not notify when recipient is suspended' do
- recipient.suspend!
- expect { subject }.to_not change(Notification, :count)
- end
- describe 'reblogs' do
- let(:status) { Fabricate(:status, account: Fabricate(:account)) }
- let(:activity) { Fabricate(:status, account: sender, reblog: status) }
- let(:type) { :reblog }
- it 'shows reblogs by default' do
- recipient.follow!(sender)
- expect { subject }.to change(Notification, :count)
- end
- it 'shows reblogs when explicitly enabled' do
- recipient.follow!(sender, reblogs: true)
- expect { subject }.to change(Notification, :count)
- end
- it 'shows reblogs when disabled' do
- recipient.follow!(sender, reblogs: false)
- expect { subject }.to change(Notification, :count)
- end
- end
- context 'with muted and blocked users' do
- let(:asshole) { Fabricate(:account, username: 'asshole') }
- let(:reply_to) { Fabricate(:status, account: asshole) }
- let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, thread: reply_to)) }
- let(:type) { :mention }
- it 'does not notify when conversation is muted' do
- recipient.mute_conversation!(activity.status.conversation)
- expect { subject }.to_not change(Notification, :count)
- end
- it 'does not notify when it is a reply to a blocked user' do
- recipient.block!(asshole)
- expect { subject }.to_not change(Notification, :count)
- end
- end
- context 'with sender as recipient' do
- let(:sender) { recipient }
- it 'does not notify when recipient is the sender' do
- expect { subject }.to_not change(Notification, :count)
- end
- end
- describe 'email' do
- before do
- user.settings.update('notification_emails.follow': enabled)
- user.save
- end
- context 'when email notification is enabled' do
- let(:enabled) { true }
- it 'sends email', :inline_jobs do
- emails = capture_emails { subject }
- expect(emails.size)
- .to eq(1)
- expect(emails.first)
- .to have_attributes(
- to: contain_exactly(user.email),
- subject: eq(I18n.t('notification_mailer.follow.subject', name: sender.acct))
- )
- end
- end
- context 'when email notification is disabled' do
- let(:enabled) { false }
- it "doesn't send email" do
- emails = capture_emails { subject }
- expect(emails).to be_empty
- end
- end
- end
- context 'when the blocked sender has a role' do
- let(:sender) { Fabricate(:user, role: sender_role).account }
- let(:activity) { Fabricate(:mention, status: Fabricate(:status, account: sender)) }
- let(:type) { :mention }
- before do
- recipient.block!(sender)
- end
- context 'when the role is a visible moderator' do
- let(:sender_role) { Fabricate(:user_role, highlighted: true, permissions: UserRole::FLAGS[:manage_users]) }
- it 'does notify' do
- expect { subject }.to change(Notification, :count)
- end
- end
- context 'when the role is a non-visible moderator' do
- let(:sender_role) { Fabricate(:user_role, highlighted: false, permissions: UserRole::FLAGS[:manage_users]) }
- it 'does not notify' do
- expect { subject }.to_not change(Notification, :count)
- end
- end
- context 'when the role is a visible non-moderator' do
- let(:sender_role) { Fabricate(:user_role, highlighted: true) }
- it 'does not notify' do
- expect { subject }.to_not change(Notification, :count)
- end
- end
- end
- context 'with filtered notifications' do
- let(:unknown) { Fabricate(:account, username: 'unknown') }
- let(:status) { Fabricate(:status, account: unknown) }
- let(:activity) { Fabricate(:mention, account: recipient, status: status) }
- let(:type) { :mention }
- before do
- Fabricate(:notification_policy, account: recipient, filter_not_following: true)
- end
- it 'creates a filtered notification' do
- expect { subject }.to change(Notification, :count)
- expect(Notification.last).to be_filtered
- end
- context 'when no notification request exists' do
- it 'creates a notification request' do
- expect { subject }.to change(NotificationRequest, :count)
- end
- end
- context 'when a notification request exists' do
- let!(:notification_request) do
- Fabricate(:notification_request, account: recipient, from_account: unknown, last_status: Fabricate(:status, account: unknown))
- end
- it 'updates the existing notification request' do
- expect { subject }.to_not change(NotificationRequest, :count)
- expect(notification_request.reload.last_status).to eq status
- end
- end
- end
- describe NotifyService::DropCondition do
- subject { described_class.new(notification) }
- let(:activity) { Fabricate(:mention, status: Fabricate(:status)) }
- let(:notification) { Fabricate(:notification, type: :mention, activity: activity, from_account: activity.status.account, account: activity.account) }
- describe '#drop' do
- context 'when sender is silenced and recipient has a default policy' do
- before do
- notification.from_account.silence!
- end
- it 'returns false' do
- expect(subject.drop?).to be false
- end
- end
- context 'when sender is silenced and recipient has a policy to ignore silenced accounts' do
- before do
- notification.from_account.silence!
- notification.account.create_notification_policy!(for_limited_accounts: :drop)
- end
- it 'returns true' do
- expect(subject.drop?).to be true
- end
- end
- context 'when sender is new and recipient has a default policy' do
- it 'returns false' do
- expect(subject.drop?).to be false
- end
- end
- context 'when sender is new and recipient has a policy to ignore silenced accounts' do
- before do
- notification.account.create_notification_policy!(for_new_accounts: :drop)
- end
- it 'returns true' do
- expect(subject.drop?).to be true
- end
- end
- context 'when sender is new and followed and recipient has a policy to ignore silenced accounts' do
- before do
- notification.account.create_notification_policy!(for_new_accounts: :drop)
- notification.account.follow!(notification.from_account)
- end
- it 'returns false' do
- expect(subject.drop?).to be false
- end
- end
- context 'when recipient has blocked sender' do
- before do
- notification.account.block!(notification.from_account)
- end
- it 'returns true' do
- expect(subject.drop?).to be true
- end
- end
- end
- end
- describe NotifyService::FilterCondition do
- subject { described_class.new(notification) }
- let(:activity) { Fabricate(:mention, status: Fabricate(:status)) }
- let(:notification) { Fabricate(:notification, type: :mention, activity: activity, from_account: activity.status.account, account: activity.account) }
- describe '#filter?' do
- context 'when sender is silenced' do
- before do
- notification.from_account.silence!
- end
- it 'returns true' do
- expect(subject.filter?).to be true
- end
- context 'when recipient follows sender' do
- before do
- notification.account.follow!(notification.from_account)
- end
- it 'returns false' do
- expect(subject.filter?).to be false
- end
- end
- context 'when recipient is allowing limited accounts' do
- before do
- notification.account.create_notification_policy!(for_limited_accounts: :accept)
- end
- it 'returns false' do
- expect(subject.filter?).to be false
- end
- end
- end
- context 'when recipient is filtering not-followed senders' do
- before do
- Fabricate(:notification_policy, account: notification.account, filter_not_following: true)
- end
- it 'returns true' do
- expect(subject.filter?).to be true
- end
- context 'when sender has permission' do
- before do
- Fabricate(:notification_permission, account: notification.account, from_account: notification.from_account)
- end
- it 'returns false' do
- expect(subject.filter?).to be false
- end
- end
- context 'when sender is followed by recipient' do
- before do
- notification.account.follow!(notification.from_account)
- end
- it 'returns false' do
- expect(subject.filter?).to be false
- end
- end
- end
- context 'when recipient is filtering not-followers' do
- before do
- Fabricate(:notification_policy, account: notification.account, filter_not_followers: true)
- end
- it 'returns true' do
- expect(subject.filter?).to be true
- end
- context 'when sender has permission' do
- before do
- Fabricate(:notification_permission, account: notification.account, from_account: notification.from_account)
- end
- it 'returns false' do
- expect(subject.filter?).to be false
- end
- end
- context 'when sender follows recipient' do
- before do
- notification.from_account.follow!(notification.account)
- end
- it 'returns true' do
- expect(subject.filter?).to be true
- end
- end
- context 'when sender follows recipient for longer than 3 days' do
- before do
- follow = notification.from_account.follow!(notification.account)
- follow.update(created_at: 4.days.ago)
- end
- it 'returns false' do
- expect(subject.filter?).to be false
- end
- end
- end
- context 'when recipient is filtering new accounts' do
- before do
- Fabricate(:notification_policy, account: notification.account, filter_new_accounts: true)
- end
- it 'returns true' do
- expect(subject.filter?).to be true
- end
- context 'when sender has permission' do
- before do
- Fabricate(:notification_permission, account: notification.account, from_account: notification.from_account)
- end
- it 'returns false' do
- expect(subject.filter?).to be false
- end
- end
- context 'when sender is older than 30 days' do
- before do
- notification.from_account.update(created_at: 31.days.ago)
- end
- it 'returns false' do
- expect(subject.filter?).to be false
- end
- end
- end
- context 'when recipient is not filtering anyone' do
- before do
- Fabricate(:notification_policy, account: notification.account)
- end
- it 'returns false' do
- expect(subject.filter?).to be false
- end
- end
- context 'when recipient is filtering unsolicited private mentions' do
- before do
- Fabricate(:notification_policy, account: notification.account, filter_private_mentions: true)
- end
- context 'when notification is not a private mention' do
- it 'returns false' do
- expect(subject.filter?).to be false
- end
- end
- context 'when notification is a private mention' do
- before do
- notification.target_status.update(visibility: :direct)
- end
- it 'returns true' do
- expect(subject.filter?).to be true
- end
- context 'when the message chain is initiated by recipient, but sender is not mentioned' do
- before do
- original_status = Fabricate(:status, account: notification.account, visibility: :direct)
- notification.target_status.update(thread: original_status)
- end
- it 'returns true' do
- expect(subject.filter?).to be true
- end
- end
- context 'when the message chain is initiated by recipient, and sender is mentioned' do
- before do
- original_status = Fabricate(:status, account: notification.account, visibility: :direct)
- notification.target_status.update(thread: original_status)
- Fabricate(:mention, status: original_status, account: notification.from_account)
- end
- it 'returns false' do
- expect(subject.filter?).to be false
- end
- end
- context 'when the sender is mentioned in an unrelated message chain' do
- before do
- original_status = Fabricate(:status, visibility: :direct)
- intermediary_status = Fabricate(:status, visibility: :direct, thread: original_status)
- notification.target_status.update(thread: intermediary_status)
- Fabricate(:mention, status: original_status, account: notification.from_account)
- end
- it 'returns true' do
- expect(subject.filter?).to be true
- end
- end
- end
- end
- end
- end
- end
|