Update rubocop-rspec to version 2.22.0, fix `RSpec/IndexedLet` cop (#24698)

This commit is contained in:
Matt Jankowski 2023-06-14 10:44:37 -04:00 committed by GitHub
parent 24015ef0cc
commit 4c5aa0e470
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 334 additions and 322 deletions

View File

@ -199,14 +199,9 @@ Naming/VariableNumber:
- 'db/migrate/20190820003045_update_statuses_index.rb' - 'db/migrate/20190820003045_update_statuses_index.rb'
- 'db/migrate/20190823221802_add_local_index_to_statuses.rb' - 'db/migrate/20190823221802_add_local_index_to_statuses.rb'
- 'db/migrate/20200119112504_add_public_index_to_statuses.rb' - 'db/migrate/20200119112504_add_public_index_to_statuses.rb'
- 'spec/controllers/activitypub/followers_synchronizations_controller_spec.rb'
- 'spec/lib/feed_manager_spec.rb'
- 'spec/models/account_spec.rb' - 'spec/models/account_spec.rb'
- 'spec/models/concerns/account_interactions_spec.rb'
- 'spec/models/custom_emoji_filter_spec.rb'
- 'spec/models/domain_block_spec.rb' - 'spec/models/domain_block_spec.rb'
- 'spec/models/user_spec.rb' - 'spec/models/user_spec.rb'
- 'spec/services/activitypub/fetch_featured_collection_service_spec.rb'
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
Performance/UnfreezeString: Performance/UnfreezeString:

View File

@ -606,6 +606,8 @@ GEM
parser (>= 3.2.1.0) parser (>= 3.2.1.0)
rubocop-capybara (2.18.0) rubocop-capybara (2.18.0)
rubocop (~> 1.41) rubocop (~> 1.41)
rubocop-factory_bot (2.23.1)
rubocop (~> 1.33)
rubocop-performance (1.18.0) rubocop-performance (1.18.0)
rubocop (>= 1.7.0, < 2.0) rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0) rubocop-ast (>= 0.4.0)
@ -613,9 +615,10 @@ GEM
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0) rubocop (>= 1.33.0, < 2.0)
rubocop-rspec (2.19.0) rubocop-rspec (2.22.0)
rubocop (~> 1.33) rubocop (~> 1.33)
rubocop-capybara (~> 2.17) rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
ruby-saml (1.13.0) ruby-saml (1.13.0)
nokogiri (>= 1.10.5) nokogiri (>= 1.10.5)

View File

@ -4,16 +4,16 @@ require 'rails_helper'
RSpec.describe ActivityPub::FollowersSynchronizationsController do RSpec.describe ActivityPub::FollowersSynchronizationsController do
let!(:account) { Fabricate(:account) } let!(:account) { Fabricate(:account) }
let!(:follower_1) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/users/a') } let!(:follower_example_com_user_a) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/users/a') }
let!(:follower_2) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/users/b') } let!(:follower_example_com_user_b) { Fabricate(:account, domain: 'example.com', uri: 'https://example.com/users/b') }
let!(:follower_3) { Fabricate(:account, domain: 'foo.com', uri: 'https://foo.com/users/a') } let!(:follower_foo_com_user_a) { Fabricate(:account, domain: 'foo.com', uri: 'https://foo.com/users/a') }
let!(:follower_4) { Fabricate(:account, username: 'instance-actor', domain: 'example.com', uri: 'https://example.com') } let!(:follower_example_com_instance_actor) { Fabricate(:account, username: 'instance-actor', domain: 'example.com', uri: 'https://example.com') }
before do before do
follower_1.follow!(account) follower_example_com_user_a.follow!(account)
follower_2.follow!(account) follower_example_com_user_b.follow!(account)
follower_3.follow!(account) follower_foo_com_user_a.follow!(account)
follower_4.follow!(account) follower_example_com_instance_actor.follow!(account)
allow(controller).to receive(:signed_request_actor).and_return(remote_account) allow(controller).to receive(:signed_request_actor).and_return(remote_account)
end end
@ -47,7 +47,11 @@ RSpec.describe ActivityPub::FollowersSynchronizationsController do
it 'returns orderedItems with followers from example.com' do it 'returns orderedItems with followers from example.com' do
expect(body[:orderedItems]).to be_an Array expect(body[:orderedItems]).to be_an Array
expect(body[:orderedItems]).to contain_exactly(follower_4.uri, follower_1.uri, follower_2.uri) expect(body[:orderedItems]).to contain_exactly(
follower_example_com_instance_actor.uri,
follower_example_com_user_a.uri,
follower_example_com_user_b.uri
)
end end
it 'returns private Cache-Control header' do it 'returns private Cache-Control header' do

View File

@ -7,9 +7,9 @@ RSpec.describe Admin::InstancesController do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) } let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let!(:account) { Fabricate(:account, domain: 'popular') } let!(:account_popular_main) { Fabricate(:account, domain: 'popular') }
let!(:account2) { Fabricate(:account, domain: 'popular') } let!(:account_popular_other) { Fabricate(:account, domain: 'popular') }
let!(:account3) { Fabricate(:account, domain: 'less.popular') } let!(:account_less_popular) { Fabricate(:account, domain: 'less.popular') }
before do before do
sign_in current_user, scope: :user sign_in current_user, scope: :user

View File

@ -5,13 +5,13 @@ require 'rails_helper'
describe FollowerAccountsController do describe FollowerAccountsController do
render_views render_views
let(:alice) { Fabricate(:account) } let(:alice) { Fabricate(:account, username: 'alice') }
let(:follower0) { Fabricate(:account) } let(:follower_bob) { Fabricate(:account, username: 'bob') }
let(:follower1) { Fabricate(:account) } let(:follower_chris) { Fabricate(:account, username: 'curt') }
describe 'GET #index' do describe 'GET #index' do
let!(:follow0) { follower0.follow!(alice) } let!(:follow_from_bob) { follower_bob.follow!(alice) }
let!(:follow1) { follower1.follow!(alice) } let!(:follow_from_chris) { follower_chris.follow!(alice) }
context 'when format is html' do context 'when format is html' do
subject(:response) { get :index, params: { account_username: alice.username, format: :html } } subject(:response) { get :index, params: { account_username: alice.username, format: :html } }

View File

@ -5,13 +5,13 @@ require 'rails_helper'
describe FollowingAccountsController do describe FollowingAccountsController do
render_views render_views
let(:alice) { Fabricate(:account) } let(:alice) { Fabricate(:account, username: 'alice') }
let(:followee0) { Fabricate(:account) } let(:followee_bob) { Fabricate(:account, username: 'bob') }
let(:followee1) { Fabricate(:account) } let(:followee_chris) { Fabricate(:account, username: 'chris') }
describe 'GET #index' do describe 'GET #index' do
let!(:follow0) { alice.follow!(followee0) } let!(:follow_of_bob) { alice.follow!(followee_bob) }
let!(:follow1) { alice.follow!(followee1) } let!(:follow_of_chris) { alice.follow!(followee_chris) }
context 'when format is html' do context 'when format is html' do
subject(:response) { get :index, params: { account_username: alice.username, format: :html } } subject(:response) { get :index, params: { account_username: alice.username, format: :html } }

View File

@ -5,31 +5,31 @@ require 'rails_helper'
RSpec.describe AccountReachFinder do RSpec.describe AccountReachFinder do
let(:account) { Fabricate(:account) } let(:account) { Fabricate(:account) }
let(:follower1) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://example.com/inbox-1') } let(:ap_follower_example_com) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://example.com/inbox-1') }
let(:follower2) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://example.com/inbox-2') } let(:ap_follower_example_org) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://example.org/inbox-2') }
let(:follower3) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://foo.bar/users/a/inbox', shared_inbox_url: 'https://foo.bar/inbox') } let(:ap_follower_with_shared) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://foo.bar/users/a/inbox', shared_inbox_url: 'https://foo.bar/inbox') }
let(:mentioned1) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://foo.bar/users/b/inbox', shared_inbox_url: 'https://foo.bar/inbox') } let(:ap_mentioned_with_shared) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://foo.bar/users/b/inbox', shared_inbox_url: 'https://foo.bar/inbox') }
let(:mentioned2) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://example.com/inbox-3') } let(:ap_mentioned_example_com) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://example.com/inbox-3') }
let(:mentioned3) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://example.com/inbox-4') } let(:ap_mentioned_example_org) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://example.org/inbox-4') }
let(:unrelated_account) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://example.com/unrelated-inbox') } let(:unrelated_account) { Fabricate(:account, protocol: :activitypub, inbox_url: 'https://example.com/unrelated-inbox') }
before do before do
follower1.follow!(account) ap_follower_example_com.follow!(account)
follower2.follow!(account) ap_follower_example_org.follow!(account)
follower3.follow!(account) ap_follower_with_shared.follow!(account)
Fabricate(:status, account: account).tap do |status| Fabricate(:status, account: account).tap do |status|
status.mentions << Mention.new(account: follower1) status.mentions << Mention.new(account: ap_follower_example_com)
status.mentions << Mention.new(account: mentioned1) status.mentions << Mention.new(account: ap_mentioned_with_shared)
end end
Fabricate(:status, account: account) Fabricate(:status, account: account)
Fabricate(:status, account: account).tap do |status| Fabricate(:status, account: account).tap do |status|
status.mentions << Mention.new(account: mentioned2) status.mentions << Mention.new(account: ap_mentioned_example_com)
status.mentions << Mention.new(account: mentioned3) status.mentions << Mention.new(account: ap_mentioned_example_org)
end end
Fabricate(:status).tap do |status| Fabricate(:status).tap do |status|
@ -39,11 +39,11 @@ RSpec.describe AccountReachFinder do
describe '#inboxes' do describe '#inboxes' do
it 'includes the preferred inbox URL of followers' do it 'includes the preferred inbox URL of followers' do
expect(described_class.new(account).inboxes).to include(*[follower1, follower2, follower3].map(&:preferred_inbox_url)) expect(described_class.new(account).inboxes).to include(*[ap_follower_example_com, ap_follower_example_org, ap_follower_with_shared].map(&:preferred_inbox_url))
end end
it 'includes the preferred inbox URL of recently-mentioned accounts' do it 'includes the preferred inbox URL of recently-mentioned accounts' do
expect(described_class.new(account).inboxes).to include(*[mentioned1, mentioned2, mentioned3].map(&:preferred_inbox_url)) expect(described_class.new(account).inboxes).to include(*[ap_mentioned_with_shared, ap_mentioned_example_com, ap_mentioned_example_org].map(&:preferred_inbox_url))
end end
it 'does not include the inbox of unrelated users' do it 'does not include the inbox of unrelated users' do

View File

@ -529,16 +529,22 @@ RSpec.describe FeedManager do
let(:account) { Fabricate(:account) } let(:account) { Fabricate(:account) }
let(:followed_account) { Fabricate(:account) } let(:followed_account) { Fabricate(:account) }
let(:target_account) { Fabricate(:account) } let(:target_account) { Fabricate(:account) }
let(:status_1) { Fabricate(:status, account: followed_account) } let(:status_from_followed_account_first) { Fabricate(:status, account: followed_account) }
let(:status_2) { Fabricate(:status, account: target_account) } let(:status_from_target_account) { Fabricate(:status, account: target_account) }
let(:status_3) { Fabricate(:status, account: followed_account, mentions: [Fabricate(:mention, account: target_account)]) } let(:status_from_followed_account_mentions_target_account) { Fabricate(:status, account: followed_account, mentions: [Fabricate(:mention, account: target_account)]) }
let(:status_4) { Fabricate(:status, mentions: [Fabricate(:mention, account: target_account)]) } let(:status_mentions_target_account) { Fabricate(:status, mentions: [Fabricate(:mention, account: target_account)]) }
let(:status_5) { Fabricate(:status, account: followed_account, reblog: status_4) } let(:status_from_followed_account_reblogs_status_mentions_target_account) { Fabricate(:status, account: followed_account, reblog: status_mentions_target_account) }
let(:status_6) { Fabricate(:status, account: followed_account, reblog: status_2) } let(:status_from_followed_account_reblogs_status_from_target_account) { Fabricate(:status, account: followed_account, reblog: status_from_target_account) }
let(:status_7) { Fabricate(:status, account: followed_account) } let(:status_from_followed_account_next) { Fabricate(:status, account: followed_account) }
before do before do
[status_1, status_3, status_5, status_6, status_7].each do |status| [
status_from_followed_account_first,
status_from_followed_account_mentions_target_account,
status_from_followed_account_reblogs_status_mentions_target_account,
status_from_followed_account_reblogs_status_from_target_account,
status_from_followed_account_next,
].each do |status|
redis.zadd("feed:home:#{account.id}", status.id, status.id) redis.zadd("feed:home:#{account.id}", status.id, status.id)
end end
end end
@ -546,7 +552,7 @@ RSpec.describe FeedManager do
it 'correctly cleans the home timeline' do it 'correctly cleans the home timeline' do
described_class.instance.clear_from_home(account, target_account) described_class.instance.clear_from_home(account, target_account)
expect(redis.zrange("feed:home:#{account.id}", 0, -1)).to eq [status_1.id.to_s, status_7.id.to_s] expect(redis.zrange("feed:home:#{account.id}", 0, -1)).to eq [status_from_followed_account_first.id.to_s, status_from_followed_account_next.id.to_s]
end end
end end
end end

View File

@ -189,22 +189,22 @@ describe Mastodon::CLI::IpBlocks do
end end
context 'with --force option' do context 'with --force option' do
let!(:block1) { IpBlock.create(ip: '192.168.0.0/24', severity: :no_access) } let!(:first_ip_range_block) { IpBlock.create(ip: '192.168.0.0/24', severity: :no_access) }
let!(:block2) { IpBlock.create(ip: '10.0.0.0/16', severity: :no_access) } let!(:second_ip_range_block) { IpBlock.create(ip: '10.0.0.0/16', severity: :no_access) }
let!(:block3) { IpBlock.create(ip: '172.16.0.0/20', severity: :no_access) } let!(:third_ip_range_block) { IpBlock.create(ip: '172.16.0.0/20', severity: :no_access) }
let(:arguments) { ['192.168.0.5', '10.0.1.50'] } let(:arguments) { ['192.168.0.5', '10.0.1.50'] }
let(:options) { { force: true } } let(:options) { { force: true } }
it 'removes blocks for IP ranges that cover given IP(s)' do it 'removes blocks for IP ranges that cover given IP(s)' do
cli.invoke(:remove, arguments, options) cli.invoke(:remove, arguments, options)
expect(IpBlock.where(id: [block1.id, block2.id])).to_not exist expect(IpBlock.where(id: [first_ip_range_block.id, second_ip_range_block.id])).to_not exist
end end
it 'does not remove other IP ranges' do it 'does not remove other IP ranges' do
cli.invoke(:remove, arguments, options) cli.invoke(:remove, arguments, options)
expect(IpBlock.where(id: block3.id)).to exist expect(IpBlock.where(id: third_ip_range_block.id)).to exist
end end
end end
@ -251,22 +251,22 @@ describe Mastodon::CLI::IpBlocks do
end end
describe '#export' do describe '#export' do
let(:block1) { IpBlock.create(ip: '192.168.0.0/24', severity: :no_access) } let(:first_ip_range_block) { IpBlock.create(ip: '192.168.0.0/24', severity: :no_access) }
let(:block2) { IpBlock.create(ip: '10.0.0.0/16', severity: :no_access) } let(:second_ip_range_block) { IpBlock.create(ip: '10.0.0.0/16', severity: :no_access) }
let(:block3) { IpBlock.create(ip: '127.0.0.1', severity: :sign_up_block) } let(:third_ip_range_block) { IpBlock.create(ip: '127.0.0.1', severity: :sign_up_block) }
context 'when --format option is set to "plain"' do context 'when --format option is set to "plain"' do
let(:options) { { format: 'plain' } } let(:options) { { format: 'plain' } }
it 'exports blocked IPs with "no_access" severity in plain format' do it 'exports blocked IPs with "no_access" severity in plain format' do
expect { cli.invoke(:export, nil, options) }.to output( expect { cli.invoke(:export, nil, options) }.to output(
a_string_including("#{block1.ip}/#{block1.ip.prefix}\n#{block2.ip}/#{block2.ip.prefix}") a_string_including("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
).to_stdout ).to_stdout
end end
it 'does not export bloked IPs with different severities' do it 'does not export bloked IPs with different severities' do
expect { cli.invoke(:export, nil, options) }.to_not output( expect { cli.invoke(:export, nil, options) }.to_not output(
a_string_including("#{block3.ip}/#{block1.ip.prefix}") a_string_including("#{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}")
).to_stdout ).to_stdout
end end
end end
@ -276,13 +276,13 @@ describe Mastodon::CLI::IpBlocks do
it 'exports blocked IPs with "no_access" severity in plain format' do it 'exports blocked IPs with "no_access" severity in plain format' do
expect { cli.invoke(:export, nil, options) }.to output( expect { cli.invoke(:export, nil, options) }.to output(
a_string_including("deny #{block1.ip}/#{block1.ip.prefix};\ndeny #{block2.ip}/#{block2.ip.prefix};") a_string_including("deny #{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};\ndeny #{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix};")
).to_stdout ).to_stdout
end end
it 'does not export bloked IPs with different severities' do it 'does not export bloked IPs with different severities' do
expect { cli.invoke(:export, nil, options) }.to_not output( expect { cli.invoke(:export, nil, options) }.to_not output(
a_string_including("deny #{block3.ip}/#{block1.ip.prefix};") a_string_including("deny #{third_ip_range_block.ip}/#{first_ip_range_block.ip.prefix};")
).to_stdout ).to_stdout
end end
end end
@ -290,7 +290,7 @@ describe Mastodon::CLI::IpBlocks do
context 'when --format option is not provided' do context 'when --format option is not provided' do
it 'exports blocked IPs in plain format by default' do it 'exports blocked IPs in plain format by default' do
expect { cli.export }.to output( expect { cli.export }.to output(
a_string_including("#{block1.ip}/#{block1.ip.prefix}\n#{block2.ip}/#{block2.ip.prefix}") a_string_including("#{first_ip_range_block.ip}/#{first_ip_range_block.ip.prefix}\n#{second_ip_range_block.ip}/#{second_ip_range_block.ip.prefix}")
).to_stdout ).to_stdout
end end
end end

View File

@ -266,10 +266,10 @@ RSpec.describe AccountStatusesCleanupPolicy do
let!(:self_bookmarked) { Fabricate(:status, created_at: 1.year.ago, account: account) } let!(:self_bookmarked) { Fabricate(:status, created_at: 1.year.ago, account: account) }
let!(:status_with_poll) { Fabricate(:status, created_at: 1.year.ago, account: account, poll_attributes: { account: account, voters_count: 0, options: %w(a b), expires_in: 2.days }) } let!(:status_with_poll) { Fabricate(:status, created_at: 1.year.ago, account: account, poll_attributes: { account: account, voters_count: 0, options: %w(a b), expires_in: 2.days }) }
let!(:status_with_media) { Fabricate(:status, created_at: 1.year.ago, account: account) } let!(:status_with_media) { Fabricate(:status, created_at: 1.year.ago, account: account) }
let!(:faved4) { Fabricate(:status, created_at: 1.year.ago, account: account) } let!(:faved_primary) { Fabricate(:status, created_at: 1.year.ago, account: account) }
let!(:faved5) { Fabricate(:status, created_at: 1.year.ago, account: account) } let!(:faved_secondary) { Fabricate(:status, created_at: 1.year.ago, account: account) }
let!(:reblogged4) { Fabricate(:status, created_at: 1.year.ago, account: account) } let!(:reblogged_primary) { Fabricate(:status, created_at: 1.year.ago, account: account) }
let!(:reblogged5) { Fabricate(:status, created_at: 1.year.ago, account: account) } let!(:reblogged_secondary) { Fabricate(:status, created_at: 1.year.ago, account: account) }
let!(:recent_status) { Fabricate(:status, created_at: 2.days.ago, account: account) } let!(:recent_status) { Fabricate(:status, created_at: 2.days.ago, account: account) }
let!(:media_attachment) { Fabricate(:media_attachment, account: account, status: status_with_media) } let!(:media_attachment) { Fabricate(:media_attachment, account: account, status: status_with_media) }
@ -280,10 +280,10 @@ RSpec.describe AccountStatusesCleanupPolicy do
let(:account_statuses_cleanup_policy) { Fabricate(:account_statuses_cleanup_policy, account: account) } let(:account_statuses_cleanup_policy) { Fabricate(:account_statuses_cleanup_policy, account: account) }
before do before do
4.times { faved4.increment_count!(:favourites_count) } 4.times { faved_primary.increment_count!(:favourites_count) }
5.times { faved5.increment_count!(:favourites_count) } 5.times { faved_secondary.increment_count!(:favourites_count) }
4.times { reblogged4.increment_count!(:reblogs_count) } 4.times { reblogged_primary.increment_count!(:reblogs_count) }
5.times { reblogged5.increment_count!(:reblogs_count) } 5.times { reblogged_secondary.increment_count!(:reblogs_count) }
end end
context 'when passed a max_id' do context 'when passed a max_id' do
@ -359,7 +359,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'returns every other old status for deletion' do it 'returns every other old status for deletion' do
expect(subject.pluck(:id)).to include(very_old_status.id, pinned_status.id, self_faved.id, self_bookmarked.id, status_with_poll.id, status_with_media.id, faved4.id, faved5.id, reblogged4.id, reblogged5.id) expect(subject.pluck(:id)).to include(very_old_status.id, pinned_status.id, self_faved.id, self_bookmarked.id, status_with_poll.id, status_with_media.id, faved_primary.id, faved_secondary.id, reblogged_primary.id, reblogged_secondary.id)
end end
end end
@ -378,7 +378,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'returns every other old status for deletion' do it 'returns every other old status for deletion' do
expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, pinned_status.id, self_faved.id, status_with_poll.id, status_with_media.id, faved4.id, faved5.id, reblogged4.id, reblogged5.id) expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, pinned_status.id, self_faved.id, status_with_poll.id, status_with_media.id, faved_primary.id, faved_secondary.id, reblogged_primary.id, reblogged_secondary.id)
end end
end end
@ -397,7 +397,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'returns every other old status for deletion' do it 'returns every other old status for deletion' do
expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, pinned_status.id, self_bookmarked.id, status_with_poll.id, status_with_media.id, faved4.id, faved5.id, reblogged4.id, reblogged5.id) expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, pinned_status.id, self_bookmarked.id, status_with_poll.id, status_with_media.id, faved_primary.id, faved_secondary.id, reblogged_primary.id, reblogged_secondary.id)
end end
end end
@ -416,7 +416,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'returns every other old status for deletion' do it 'returns every other old status for deletion' do
expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, pinned_status.id, self_faved.id, self_bookmarked.id, status_with_poll.id, faved4.id, faved5.id, reblogged4.id, reblogged5.id) expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, pinned_status.id, self_faved.id, self_bookmarked.id, status_with_poll.id, faved_primary.id, faved_secondary.id, reblogged_primary.id, reblogged_secondary.id)
end end
end end
@ -435,7 +435,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'returns every other old status for deletion' do it 'returns every other old status for deletion' do
expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, pinned_status.id, self_faved.id, self_bookmarked.id, status_with_media.id, faved4.id, faved5.id, reblogged4.id, reblogged5.id) expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, pinned_status.id, self_faved.id, self_bookmarked.id, status_with_media.id, faved_primary.id, faved_secondary.id, reblogged_primary.id, reblogged_secondary.id)
end end
end end
@ -454,7 +454,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'returns every other old status for deletion' do it 'returns every other old status for deletion' do
expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, self_faved.id, self_bookmarked.id, status_with_poll.id, status_with_media.id, faved4.id, faved5.id, reblogged4.id, reblogged5.id) expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, self_faved.id, self_bookmarked.id, status_with_poll.id, status_with_media.id, faved_primary.id, faved_secondary.id, reblogged_primary.id, reblogged_secondary.id)
end end
end end
@ -477,7 +477,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'returns every other old status for deletion' do it 'returns every other old status for deletion' do
expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, pinned_status.id, self_faved.id, self_bookmarked.id, status_with_poll.id, status_with_media.id, faved4.id, faved5.id, reblogged4.id, reblogged5.id) expect(subject.pluck(:id)).to include(direct_message.id, very_old_status.id, pinned_status.id, self_faved.id, self_bookmarked.id, status_with_poll.id, status_with_media.id, faved_primary.id, faved_secondary.id, reblogged_primary.id, reblogged_secondary.id)
end end
end end
@ -496,7 +496,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'returns only normal statuses for deletion' do it 'returns only normal statuses for deletion' do
expect(subject.pluck(:id)).to contain_exactly(very_old_status.id, faved4.id, faved5.id, reblogged4.id, reblogged5.id) expect(subject.pluck(:id)).to contain_exactly(very_old_status.id, faved_primary.id, faved_secondary.id, reblogged_primary.id, reblogged_secondary.id)
end end
end end
@ -510,7 +510,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'does not return the toot reblogged 5 times' do it 'does not return the toot reblogged 5 times' do
expect(subject.pluck(:id)).to_not include(reblogged5.id) expect(subject.pluck(:id)).to_not include(reblogged_secondary.id)
end end
it 'does not return the unrelated toot' do it 'does not return the unrelated toot' do
@ -518,7 +518,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'returns old statuses not reblogged as much' do it 'returns old statuses not reblogged as much' do
expect(subject.pluck(:id)).to include(very_old_status.id, faved4.id, faved5.id, reblogged4.id) expect(subject.pluck(:id)).to include(very_old_status.id, faved_primary.id, faved_secondary.id, reblogged_primary.id)
end end
end end
@ -532,7 +532,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'does not return the toot faved 5 times' do it 'does not return the toot faved 5 times' do
expect(subject.pluck(:id)).to_not include(faved5.id) expect(subject.pluck(:id)).to_not include(faved_secondary.id)
end end
it 'does not return the unrelated toot' do it 'does not return the unrelated toot' do
@ -540,7 +540,7 @@ RSpec.describe AccountStatusesCleanupPolicy do
end end
it 'returns old statuses not faved as much' do it 'returns old statuses not faved as much' do
expect(subject.pluck(:id)).to include(very_old_status.id, faved4.id, reblogged4.id, reblogged5.id) expect(subject.pluck(:id)).to include(very_old_status.id, faved_primary.id, reblogged_primary.id, reblogged_secondary.id)
end end
end end
end end

View File

@ -560,17 +560,17 @@ describe AccountInteractions do
describe '#remote_followers_hash' do describe '#remote_followers_hash' do
let(:me) { Fabricate(:account, username: 'Me') } let(:me) { Fabricate(:account, username: 'Me') }
let(:remote_1) { Fabricate(:account, username: 'alice', domain: 'example.org', uri: 'https://example.org/users/alice') } let(:remote_alice) { Fabricate(:account, username: 'alice', domain: 'example.org', uri: 'https://example.org/users/alice') }
let(:remote_2) { Fabricate(:account, username: 'bob', domain: 'example.org', uri: 'https://example.org/users/bob') } let(:remote_bob) { Fabricate(:account, username: 'bob', domain: 'example.org', uri: 'https://example.org/users/bob') }
let(:remote_3) { Fabricate(:account, username: 'instance-actor', domain: 'example.org', uri: 'https://example.org') } let(:remote_instance_actor) { Fabricate(:account, username: 'instance-actor', domain: 'example.org', uri: 'https://example.org') }
let(:remote_4) { Fabricate(:account, username: 'eve', domain: 'foo.org', uri: 'https://foo.org/users/eve') } let(:remote_eve) { Fabricate(:account, username: 'eve', domain: 'foo.org', uri: 'https://foo.org/users/eve') }
before do before do
remote_1.follow!(me) remote_alice.follow!(me)
remote_2.follow!(me) remote_bob.follow!(me)
remote_3.follow!(me) remote_instance_actor.follow!(me)
remote_4.follow!(me) remote_eve.follow!(me)
me.follow!(remote_1) me.follow!(remote_alice)
end end
it 'returns correct hash for remote domains' do it 'returns correct hash for remote domains' do
@ -582,33 +582,33 @@ describe AccountInteractions do
it 'invalidates cache as needed when removing or adding followers' do it 'invalidates cache as needed when removing or adding followers' do
expect(me.remote_followers_hash('https://example.org/')).to eq '20aecbe774b3d61c25094370baf370012b9271c5b172ecedb05caff8d79ef0c7' expect(me.remote_followers_hash('https://example.org/')).to eq '20aecbe774b3d61c25094370baf370012b9271c5b172ecedb05caff8d79ef0c7'
remote_3.unfollow!(me) remote_instance_actor.unfollow!(me)
expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec' expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec'
remote_1.unfollow!(me) remote_alice.unfollow!(me)
expect(me.remote_followers_hash('https://example.org/')).to eq '241b00794ce9b46aa864f3220afadef128318da2659782985bac5ed5bd436bff' expect(me.remote_followers_hash('https://example.org/')).to eq '241b00794ce9b46aa864f3220afadef128318da2659782985bac5ed5bd436bff'
remote_1.follow!(me) remote_alice.follow!(me)
expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec' expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec'
end end
end end
describe '#local_followers_hash' do describe '#local_followers_hash' do
let(:me) { Fabricate(:account, username: 'Me') } let(:me) { Fabricate(:account, username: 'Me') }
let(:remote_1) { Fabricate(:account, username: 'alice', domain: 'example.org', uri: 'https://example.org/users/alice') } let(:remote_alice) { Fabricate(:account, username: 'alice', domain: 'example.org', uri: 'https://example.org/users/alice') }
before do before do
me.follow!(remote_1) me.follow!(remote_alice)
end end
it 'returns correct hash for local users' do it 'returns correct hash for local users' do
expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me)) expect(remote_alice.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
end end
it 'invalidates cache as needed when removing or adding followers' do it 'invalidates cache as needed when removing or adding followers' do
expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me)) expect(remote_alice.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
me.unfollow!(remote_1) me.unfollow!(remote_alice)
expect(remote_1.local_followers_hash).to eq '0000000000000000000000000000000000000000000000000000000000000000' expect(remote_alice.local_followers_hash).to eq '0000000000000000000000000000000000000000000000000000000000000000'
me.follow!(remote_1) me.follow!(remote_alice)
expect(remote_1.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me)) expect(remote_alice.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
end end
end end

View File

@ -8,40 +8,40 @@ describe StatusThreadingConcern do
let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') } let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') }
let!(:jeff) { Fabricate(:account, username: 'jeff') } let!(:jeff) { Fabricate(:account, username: 'jeff') }
let!(:status) { Fabricate(:status, account: alice) } let!(:status) { Fabricate(:status, account: alice) }
let!(:reply1) { Fabricate(:status, thread: status, account: jeff) } let!(:reply_to_status) { Fabricate(:status, thread: status, account: jeff) }
let!(:reply2) { Fabricate(:status, thread: reply1, account: bob) } let!(:reply_to_first_reply) { Fabricate(:status, thread: reply_to_status, account: bob) }
let!(:reply3) { Fabricate(:status, thread: reply2, account: alice) } let!(:reply_to_second_reply) { Fabricate(:status, thread: reply_to_first_reply, account: alice) }
let!(:viewer) { Fabricate(:account, username: 'viewer') } let!(:viewer) { Fabricate(:account, username: 'viewer') }
it 'returns conversation history' do it 'returns conversation history' do
expect(reply3.ancestors(4)).to include(status, reply1, reply2) expect(reply_to_second_reply.ancestors(4)).to include(status, reply_to_status, reply_to_first_reply)
end end
it 'does not return conversation history user is not allowed to see' do it 'does not return conversation history user is not allowed to see' do
reply1.update(visibility: :private) reply_to_status.update(visibility: :private)
status.update(visibility: :direct) status.update(visibility: :direct)
expect(reply3.ancestors(4, viewer)).to_not include(reply1, status) expect(reply_to_second_reply.ancestors(4, viewer)).to_not include(reply_to_status, status)
end end
it 'does not return conversation history from blocked users' do it 'does not return conversation history from blocked users' do
viewer.block!(jeff) viewer.block!(jeff)
expect(reply3.ancestors(4, viewer)).to_not include(reply1) expect(reply_to_second_reply.ancestors(4, viewer)).to_not include(reply_to_status)
end end
it 'does not return conversation history from muted users' do it 'does not return conversation history from muted users' do
viewer.mute!(jeff) viewer.mute!(jeff)
expect(reply3.ancestors(4, viewer)).to_not include(reply1) expect(reply_to_second_reply.ancestors(4, viewer)).to_not include(reply_to_status)
end end
it 'does not return conversation history from silenced and not followed users' do it 'does not return conversation history from silenced and not followed users' do
jeff.silence! jeff.silence!
expect(reply3.ancestors(4, viewer)).to_not include(reply1) expect(reply_to_second_reply.ancestors(4, viewer)).to_not include(reply_to_status)
end end
it 'does not return conversation history from blocked domains' do it 'does not return conversation history from blocked domains' do
viewer.block_domain!('example.com') viewer.block_domain!('example.com')
expect(reply3.ancestors(4, viewer)).to_not include(reply2) expect(reply_to_second_reply.ancestors(4, viewer)).to_not include(reply_to_first_reply)
end end
it 'ignores deleted records' do it 'ignores deleted records' do
@ -83,40 +83,40 @@ describe StatusThreadingConcern do
let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') } let!(:bob) { Fabricate(:account, username: 'bob', domain: 'example.com') }
let!(:jeff) { Fabricate(:account, username: 'jeff') } let!(:jeff) { Fabricate(:account, username: 'jeff') }
let!(:status) { Fabricate(:status, account: alice) } let!(:status) { Fabricate(:status, account: alice) }
let!(:reply1) { Fabricate(:status, thread: status, account: alice) } let!(:reply_to_status_from_alice) { Fabricate(:status, thread: status, account: alice) }
let!(:reply2) { Fabricate(:status, thread: status, account: bob) } let!(:reply_to_status_from_bob) { Fabricate(:status, thread: status, account: bob) }
let!(:reply3) { Fabricate(:status, thread: reply1, account: jeff) } let!(:reply_to_alice_reply_from_jeff) { Fabricate(:status, thread: reply_to_status_from_alice, account: jeff) }
let!(:viewer) { Fabricate(:account, username: 'viewer') } let!(:viewer) { Fabricate(:account, username: 'viewer') }
it 'returns replies' do it 'returns replies' do
expect(status.descendants(4)).to include(reply1, reply2, reply3) expect(status.descendants(4)).to include(reply_to_status_from_alice, reply_to_status_from_bob, reply_to_alice_reply_from_jeff)
end end
it 'does not return replies user is not allowed to see' do it 'does not return replies user is not allowed to see' do
reply1.update(visibility: :private) reply_to_status_from_alice.update(visibility: :private)
reply3.update(visibility: :direct) reply_to_alice_reply_from_jeff.update(visibility: :direct)
expect(status.descendants(4, viewer)).to_not include(reply1, reply3) expect(status.descendants(4, viewer)).to_not include(reply_to_status_from_alice, reply_to_alice_reply_from_jeff)
end end
it 'does not return replies from blocked users' do it 'does not return replies from blocked users' do
viewer.block!(jeff) viewer.block!(jeff)
expect(status.descendants(4, viewer)).to_not include(reply3) expect(status.descendants(4, viewer)).to_not include(reply_to_alice_reply_from_jeff)
end end
it 'does not return replies from muted users' do it 'does not return replies from muted users' do
viewer.mute!(jeff) viewer.mute!(jeff)
expect(status.descendants(4, viewer)).to_not include(reply3) expect(status.descendants(4, viewer)).to_not include(reply_to_alice_reply_from_jeff)
end end
it 'does not return replies from silenced and not followed users' do it 'does not return replies from silenced and not followed users' do
jeff.silence! jeff.silence!
expect(status.descendants(4, viewer)).to_not include(reply3) expect(status.descendants(4, viewer)).to_not include(reply_to_alice_reply_from_jeff)
end end
it 'does not return replies from blocked domains' do it 'does not return replies from blocked domains' do
viewer.block_domain!('example.com') viewer.block_domain!('example.com')
expect(status.descendants(4, viewer)).to_not include(reply2) expect(status.descendants(4, viewer)).to_not include(reply_to_status_from_bob)
end end
it 'promotes self-replies to the top while leaving the rest in order' do it 'promotes self-replies to the top while leaving the rest in order' do

View File

@ -6,9 +6,9 @@ RSpec.describe CustomEmojiFilter do
describe '#results' do describe '#results' do
subject { described_class.new(params).results } subject { described_class.new(params).results }
let!(:custom_emoji_0) { Fabricate(:custom_emoji, domain: 'a') } let!(:custom_emoji_domain_a) { Fabricate(:custom_emoji, domain: 'a') }
let!(:custom_emoji_1) { Fabricate(:custom_emoji, domain: 'b') } let!(:custom_emoji_domain_b) { Fabricate(:custom_emoji, domain: 'b') }
let!(:custom_emoji_2) { Fabricate(:custom_emoji, domain: nil, shortcode: 'hoge') } let!(:custom_emoji_domain_nil) { Fabricate(:custom_emoji, domain: nil, shortcode: 'hoge') }
context 'when params have values' do context 'when params have values' do
context 'when local' do context 'when local' do
@ -16,7 +16,7 @@ RSpec.describe CustomEmojiFilter do
it 'returns ActiveRecord::Relation' do it 'returns ActiveRecord::Relation' do
expect(subject).to be_a(ActiveRecord::Relation) expect(subject).to be_a(ActiveRecord::Relation)
expect(subject).to contain_exactly(custom_emoji_2) expect(subject).to contain_exactly(custom_emoji_domain_nil)
end end
end end
@ -25,7 +25,7 @@ RSpec.describe CustomEmojiFilter do
it 'returns ActiveRecord::Relation' do it 'returns ActiveRecord::Relation' do
expect(subject).to be_a(ActiveRecord::Relation) expect(subject).to be_a(ActiveRecord::Relation)
expect(subject).to contain_exactly(custom_emoji_0, custom_emoji_1) expect(subject).to contain_exactly(custom_emoji_domain_a, custom_emoji_domain_b)
end end
end end
@ -34,7 +34,7 @@ RSpec.describe CustomEmojiFilter do
it 'returns ActiveRecord::Relation' do it 'returns ActiveRecord::Relation' do
expect(subject).to be_a(ActiveRecord::Relation) expect(subject).to be_a(ActiveRecord::Relation)
expect(subject).to contain_exactly(custom_emoji_0) expect(subject).to contain_exactly(custom_emoji_domain_a)
end end
end end
@ -43,7 +43,7 @@ RSpec.describe CustomEmojiFilter do
it 'returns ActiveRecord::Relation' do it 'returns ActiveRecord::Relation' do
expect(subject).to be_a(ActiveRecord::Relation) expect(subject).to be_a(ActiveRecord::Relation)
expect(subject).to contain_exactly(custom_emoji_2) expect(subject).to contain_exactly(custom_emoji_domain_nil)
end end
end end
@ -63,7 +63,7 @@ RSpec.describe CustomEmojiFilter do
it 'returns ActiveRecord::Relation' do it 'returns ActiveRecord::Relation' do
expect(subject).to be_a(ActiveRecord::Relation) expect(subject).to be_a(ActiveRecord::Relation)
expect(subject).to contain_exactly(custom_emoji_0, custom_emoji_1, custom_emoji_2) expect(subject).to contain_exactly(custom_emoji_domain_a, custom_emoji_domain_b, custom_emoji_domain_nil)
end end
end end
end end

View File

@ -254,82 +254,82 @@ RSpec.describe Status do
end end
describe '.tagged_with' do describe '.tagged_with' do
let(:tag1) { Fabricate(:tag) } let(:tag_cats) { Fabricate(:tag, name: 'cats') }
let(:tag2) { Fabricate(:tag) } let(:tag_dogs) { Fabricate(:tag, name: 'dogs') }
let(:tag3) { Fabricate(:tag) } let(:tag_zebras) { Fabricate(:tag, name: 'zebras') }
let!(:status1) { Fabricate(:status, tags: [tag1]) } let!(:status_with_tag_cats) { Fabricate(:status, tags: [tag_cats]) }
let!(:status2) { Fabricate(:status, tags: [tag2]) } let!(:status_with_tag_dogs) { Fabricate(:status, tags: [tag_dogs]) }
let!(:status3) { Fabricate(:status, tags: [tag3]) } let!(:status_tagged_with_zebras) { Fabricate(:status, tags: [tag_zebras]) }
let!(:status4) { Fabricate(:status, tags: []) } let!(:status_without_tags) { Fabricate(:status, tags: []) }
let!(:status5) { Fabricate(:status, tags: [tag1, tag2, tag3]) } let!(:status_with_all_tags) { Fabricate(:status, tags: [tag_cats, tag_dogs, tag_zebras]) }
context 'when given one tag' do context 'when given one tag' do
it 'returns the expected statuses' do it 'returns the expected statuses' do
expect(described_class.tagged_with([tag1.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status5.id) expect(described_class.tagged_with([tag_cats.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_cats.id, status_with_all_tags.id)
expect(described_class.tagged_with([tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status2.id, status5.id) expect(described_class.tagged_with([tag_dogs.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_dogs.id, status_with_all_tags.id)
expect(described_class.tagged_with([tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status3.id, status5.id) expect(described_class.tagged_with([tag_zebras.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_tagged_with_zebras.id, status_with_all_tags.id)
end end
end end
context 'when given multiple tags' do context 'when given multiple tags' do
it 'returns the expected statuses' do it 'returns the expected statuses' do
expect(described_class.tagged_with([tag1.id, tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status2.id, status5.id) expect(described_class.tagged_with([tag_cats.id, tag_dogs.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_cats.id, status_with_tag_dogs.id, status_with_all_tags.id)
expect(described_class.tagged_with([tag1.id, tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status3.id, status5.id) expect(described_class.tagged_with([tag_cats.id, tag_zebras.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_cats.id, status_tagged_with_zebras.id, status_with_all_tags.id)
expect(described_class.tagged_with([tag2.id, tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status2.id, status3.id, status5.id) expect(described_class.tagged_with([tag_dogs.id, tag_zebras.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_dogs.id, status_tagged_with_zebras.id, status_with_all_tags.id)
end end
end end
end end
describe '.tagged_with_all' do describe '.tagged_with_all' do
let(:tag1) { Fabricate(:tag) } let(:tag_cats) { Fabricate(:tag, name: 'cats') }
let(:tag2) { Fabricate(:tag) } let(:tag_dogs) { Fabricate(:tag, name: 'dogs') }
let(:tag3) { Fabricate(:tag) } let(:tag_zebras) { Fabricate(:tag, name: 'zebras') }
let!(:status1) { Fabricate(:status, tags: [tag1]) } let!(:status_with_tag_cats) { Fabricate(:status, tags: [tag_cats]) }
let!(:status2) { Fabricate(:status, tags: [tag2]) } let!(:status_with_tag_dogs) { Fabricate(:status, tags: [tag_dogs]) }
let!(:status3) { Fabricate(:status, tags: [tag3]) } let!(:status_tagged_with_zebras) { Fabricate(:status, tags: [tag_zebras]) }
let!(:status4) { Fabricate(:status, tags: []) } let!(:status_without_tags) { Fabricate(:status, tags: []) }
let!(:status5) { Fabricate(:status, tags: [tag1, tag2]) } let!(:status_with_all_tags) { Fabricate(:status, tags: [tag_cats, tag_dogs]) }
context 'when given one tag' do context 'when given one tag' do
it 'returns the expected statuses' do it 'returns the expected statuses' do
expect(described_class.tagged_with_all([tag1.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status5.id) expect(described_class.tagged_with_all([tag_cats.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_cats.id, status_with_all_tags.id)
expect(described_class.tagged_with_all([tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status2.id, status5.id) expect(described_class.tagged_with_all([tag_dogs.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_dogs.id, status_with_all_tags.id)
expect(described_class.tagged_with_all([tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status3.id) expect(described_class.tagged_with_all([tag_zebras.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_tagged_with_zebras.id)
end end
end end
context 'when given multiple tags' do context 'when given multiple tags' do
it 'returns the expected statuses' do it 'returns the expected statuses' do
expect(described_class.tagged_with_all([tag1.id, tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status5.id) expect(described_class.tagged_with_all([tag_cats.id, tag_dogs.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_all_tags.id)
expect(described_class.tagged_with_all([tag1.id, tag3.id]).reorder(:id).pluck(:id).uniq).to eq [] expect(described_class.tagged_with_all([tag_cats.id, tag_zebras.id]).reorder(:id).pluck(:id).uniq).to eq []
expect(described_class.tagged_with_all([tag2.id, tag3.id]).reorder(:id).pluck(:id).uniq).to eq [] expect(described_class.tagged_with_all([tag_dogs.id, tag_zebras.id]).reorder(:id).pluck(:id).uniq).to eq []
end end
end end
end end
describe '.tagged_with_none' do describe '.tagged_with_none' do
let(:tag1) { Fabricate(:tag) } let(:tag_cats) { Fabricate(:tag, name: 'cats') }
let(:tag2) { Fabricate(:tag) } let(:tag_dogs) { Fabricate(:tag, name: 'dogs') }
let(:tag3) { Fabricate(:tag) } let(:tag_zebras) { Fabricate(:tag, name: 'zebras') }
let!(:status1) { Fabricate(:status, tags: [tag1]) } let!(:status_with_tag_cats) { Fabricate(:status, tags: [tag_cats]) }
let!(:status2) { Fabricate(:status, tags: [tag2]) } let!(:status_with_tag_dogs) { Fabricate(:status, tags: [tag_dogs]) }
let!(:status3) { Fabricate(:status, tags: [tag3]) } let!(:status_tagged_with_zebras) { Fabricate(:status, tags: [tag_zebras]) }
let!(:status4) { Fabricate(:status, tags: []) } let!(:status_without_tags) { Fabricate(:status, tags: []) }
let!(:status5) { Fabricate(:status, tags: [tag1, tag2, tag3]) } let!(:status_with_all_tags) { Fabricate(:status, tags: [tag_cats, tag_dogs, tag_zebras]) }
context 'when given one tag' do context 'when given one tag' do
it 'returns the expected statuses' do it 'returns the expected statuses' do
expect(described_class.tagged_with_none([tag1.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status2.id, status3.id, status4.id) expect(described_class.tagged_with_none([tag_cats.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_dogs.id, status_tagged_with_zebras.id, status_without_tags.id)
expect(described_class.tagged_with_none([tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status3.id, status4.id) expect(described_class.tagged_with_none([tag_dogs.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_cats.id, status_tagged_with_zebras.id, status_without_tags.id)
expect(described_class.tagged_with_none([tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status2.id, status4.id) expect(described_class.tagged_with_none([tag_zebras.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_cats.id, status_with_tag_dogs.id, status_without_tags.id)
end end
end end
context 'when given multiple tags' do context 'when given multiple tags' do
it 'returns the expected statuses' do it 'returns the expected statuses' do
expect(described_class.tagged_with_none([tag1.id, tag2.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status3.id, status4.id) expect(described_class.tagged_with_none([tag_cats.id, tag_dogs.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_tagged_with_zebras.id, status_without_tags.id)
expect(described_class.tagged_with_none([tag1.id, tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status2.id, status4.id) expect(described_class.tagged_with_none([tag_cats.id, tag_zebras.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_dogs.id, status_without_tags.id)
expect(described_class.tagged_with_none([tag2.id, tag3.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status1.id, status4.id) expect(described_class.tagged_with_none([tag_dogs.id, tag_zebras.id]).reorder(:id).pluck(:id).uniq).to contain_exactly(status_with_tag_cats.id, status_without_tags.id)
end end
end end
end end

View File

@ -5,65 +5,65 @@ require 'rails_helper'
describe TagFeed, type: :service do describe TagFeed, type: :service do
describe '#get' do describe '#get' do
let(:account) { Fabricate(:account) } let(:account) { Fabricate(:account) }
let(:tag1) { Fabricate(:tag) } let(:tag_cats) { Fabricate(:tag, name: 'cats') }
let(:tag2) { Fabricate(:tag) } let(:tag_dogs) { Fabricate(:tag, name: 'dogs') }
let!(:status1) { Fabricate(:status, tags: [tag1]) } let!(:status_tagged_with_cats) { Fabricate(:status, tags: [tag_cats]) }
let!(:status2) { Fabricate(:status, tags: [tag2]) } let!(:status_tagged_with_dogs) { Fabricate(:status, tags: [tag_dogs]) }
let!(:both) { Fabricate(:status, tags: [tag1, tag2]) } let!(:both) { Fabricate(:status, tags: [tag_cats, tag_dogs]) }
it 'can add tags in "any" mode' do it 'can add tags in "any" mode' do
results = described_class.new(tag1, nil, any: [tag2.name]).get(20) results = described_class.new(tag_cats, nil, any: [tag_dogs.name]).get(20)
expect(results).to include status1 expect(results).to include status_tagged_with_cats
expect(results).to include status2 expect(results).to include status_tagged_with_dogs
expect(results).to include both expect(results).to include both
end end
it 'can remove tags in "all" mode' do it 'can remove tags in "all" mode' do
results = described_class.new(tag1, nil, all: [tag2.name]).get(20) results = described_class.new(tag_cats, nil, all: [tag_dogs.name]).get(20)
expect(results).to_not include status1 expect(results).to_not include status_tagged_with_cats
expect(results).to_not include status2 expect(results).to_not include status_tagged_with_dogs
expect(results).to include both expect(results).to include both
end end
it 'can remove tags in "none" mode' do it 'can remove tags in "none" mode' do
results = described_class.new(tag1, nil, none: [tag2.name]).get(20) results = described_class.new(tag_cats, nil, none: [tag_dogs.name]).get(20)
expect(results).to include status1 expect(results).to include status_tagged_with_cats
expect(results).to_not include status2 expect(results).to_not include status_tagged_with_dogs
expect(results).to_not include both expect(results).to_not include both
end end
it 'ignores an invalid mode' do it 'ignores an invalid mode' do
results = described_class.new(tag1, nil, wark: [tag2.name]).get(20) results = described_class.new(tag_cats, nil, wark: [tag_dogs.name]).get(20)
expect(results).to include status1 expect(results).to include status_tagged_with_cats
expect(results).to_not include status2 expect(results).to_not include status_tagged_with_dogs
expect(results).to include both expect(results).to include both
end end
it 'handles being passed non existent tag names' do it 'handles being passed non existent tag names' do
results = described_class.new(tag1, nil, any: ['wark']).get(20) results = described_class.new(tag_cats, nil, any: ['wark']).get(20)
expect(results).to include status1 expect(results).to include status_tagged_with_cats
expect(results).to_not include status2 expect(results).to_not include status_tagged_with_dogs
expect(results).to include both expect(results).to include both
end end
it 'can restrict to an account' do it 'can restrict to an account' do
BlockService.new.call(account, status1.account) BlockService.new.call(account, status_tagged_with_cats.account)
results = described_class.new(tag1, account, none: [tag2.name]).get(20) results = described_class.new(tag_cats, account, none: [tag_dogs.name]).get(20)
expect(results).to_not include status1 expect(results).to_not include status_tagged_with_cats
end end
it 'can restrict to local' do it 'can restrict to local' do
status1.account.update(domain: 'example.com') status_tagged_with_cats.account.update(domain: 'example.com')
status1.update(local: false, uri: 'example.com/toot') status_tagged_with_cats.update(local: false, uri: 'example.com/toot')
results = described_class.new(tag1, nil, any: [tag2.name], local: true).get(20) results = described_class.new(tag_cats, nil, any: [tag_dogs.name], local: true).get(20)
expect(results).to_not include status1 expect(results).to_not include status_tagged_with_cats
end end
it 'allows replies to be included' do it 'allows replies to be included' do
original = Fabricate(:status) original = Fabricate(:status)
status = Fabricate(:status, tags: [tag1], in_reply_to_id: original.id) status = Fabricate(:status, tags: [tag_cats], in_reply_to_id: original.id)
results = described_class.new(tag1, nil).get(20) results = described_class.new(tag_cats, nil).get(20)
expect(results).to include(status) expect(results).to include(status)
end end
end end

View File

@ -11,12 +11,12 @@ RSpec.describe Trends::Statuses do
let!(:query) { subject.query } let!(:query) { subject.query }
let!(:today) { at_time } let!(:today) { at_time }
let!(:status1) { Fabricate(:status, text: 'Foo', language: 'en', trendable: true, created_at: today) } let!(:status_foo) { Fabricate(:status, text: 'Foo', language: 'en', trendable: true, created_at: today) }
let!(:status2) { Fabricate(:status, text: 'Bar', language: 'en', trendable: true, created_at: today) } let!(:status_bar) { Fabricate(:status, text: 'Bar', language: 'en', trendable: true, created_at: today) }
before do before do
default_threshold_value.times { reblog(status1, today) } default_threshold_value.times { reblog(status_foo, today) }
default_threshold_value.times { reblog(status2, today) } default_threshold_value.times { reblog(status_bar, today) }
subject.refresh(today) subject.refresh(today)
end end
@ -29,18 +29,18 @@ RSpec.describe Trends::Statuses do
end end
it 'filters out blocked accounts' do it 'filters out blocked accounts' do
account.block!(status1.account) account.block!(status_foo.account)
expect(query.filtered_for(account).to_a).to eq [status2] expect(query.filtered_for(account).to_a).to eq [status_bar]
end end
it 'filters out muted accounts' do it 'filters out muted accounts' do
account.mute!(status2.account) account.mute!(status_bar.account)
expect(query.filtered_for(account).to_a).to eq [status1] expect(query.filtered_for(account).to_a).to eq [status_foo]
end end
it 'filters out blocked-by accounts' do it 'filters out blocked-by accounts' do
status1.account.block!(account) status_foo.account.block!(account)
expect(query.filtered_for(account).to_a).to eq [status2] expect(query.filtered_for(account).to_a).to eq [status_bar]
end end
end end
end end
@ -71,14 +71,14 @@ RSpec.describe Trends::Statuses do
let!(:today) { at_time } let!(:today) { at_time }
let!(:yesterday) { today - 1.day } let!(:yesterday) { today - 1.day }
let!(:status1) { Fabricate(:status, text: 'Foo', language: 'en', trendable: true, created_at: yesterday) } let!(:status_foo) { Fabricate(:status, text: 'Foo', language: 'en', trendable: true, created_at: yesterday) }
let!(:status2) { Fabricate(:status, text: 'Bar', language: 'en', trendable: true, created_at: today) } let!(:status_bar) { Fabricate(:status, text: 'Bar', language: 'en', trendable: true, created_at: today) }
let!(:status3) { Fabricate(:status, text: 'Baz', language: 'en', trendable: true, created_at: today) } let!(:status_baz) { Fabricate(:status, text: 'Baz', language: 'en', trendable: true, created_at: today) }
before do before do
default_threshold_value.times { reblog(status1, today) } default_threshold_value.times { reblog(status_foo, today) }
default_threshold_value.times { reblog(status2, today) } default_threshold_value.times { reblog(status_bar, today) }
(default_threshold_value - 1).times { reblog(status3, today) } (default_threshold_value - 1).times { reblog(status_baz, today) }
end end
context 'when status trends are refreshed' do context 'when status trends are refreshed' do
@ -89,17 +89,17 @@ RSpec.describe Trends::Statuses do
it 'returns correct statuses from query' do it 'returns correct statuses from query' do
results = subject.query.limit(10).to_a results = subject.query.limit(10).to_a
expect(results).to eq [status2, status1] expect(results).to eq [status_bar, status_foo]
expect(results).to_not include(status3) expect(results).to_not include(status_baz)
end end
end end
it 'decays scores' do it 'decays scores' do
subject.refresh(today) subject.refresh(today)
original_score = status2.trend.score original_score = status_bar.trend.score
expect(original_score).to be_a Float expect(original_score).to be_a Float
subject.refresh(today + subject.options[:score_halflife]) subject.refresh(today + subject.options[:score_halflife])
decayed_score = status2.trend.reload.score decayed_score = status_bar.trend.reload.score
expect(decayed_score).to be <= original_score / 2 expect(decayed_score).to be <= original_score / 2
end end
end end

View File

@ -33,15 +33,15 @@ RSpec.describe Trends::Tags do
let!(:today) { at_time } let!(:today) { at_time }
let!(:yesterday) { today - 1.day } let!(:yesterday) { today - 1.day }
let!(:tag1) { Fabricate(:tag, name: 'Catstodon', trendable: true) } let!(:tag_cats) { Fabricate(:tag, name: 'Catstodon', trendable: true) }
let!(:tag2) { Fabricate(:tag, name: 'DogsOfMastodon', trendable: true) } let!(:tag_dogs) { Fabricate(:tag, name: 'DogsOfMastodon', trendable: true) }
let!(:tag3) { Fabricate(:tag, name: 'OCs', trendable: true) } let!(:tag_ocs) { Fabricate(:tag, name: 'OCs', trendable: true) }
before do before do
2.times { |i| subject.add(tag1, i, yesterday) } 2.times { |i| subject.add(tag_cats, i, yesterday) }
13.times { |i| subject.add(tag3, i, yesterday) } 13.times { |i| subject.add(tag_ocs, i, yesterday) }
16.times { |i| subject.add(tag1, i, today) } 16.times { |i| subject.add(tag_cats, i, today) }
4.times { |i| subject.add(tag2, i, today) } 4.times { |i| subject.add(tag_dogs, i, today) }
end end
context 'when tag trends are refreshed' do context 'when tag trends are refreshed' do
@ -51,20 +51,20 @@ RSpec.describe Trends::Tags do
end end
it 'calculates and re-calculates scores' do it 'calculates and re-calculates scores' do
expect(subject.query.limit(10).to_a).to eq [tag1, tag3] expect(subject.query.limit(10).to_a).to eq [tag_cats, tag_ocs]
end end
it 'omits hashtags below threshold' do it 'omits hashtags below threshold' do
expect(subject.query.limit(10).to_a).to_not include(tag2) expect(subject.query.limit(10).to_a).to_not include(tag_dogs)
end end
end end
it 'decays scores' do it 'decays scores' do
subject.refresh(yesterday + 12.hours) subject.refresh(yesterday + 12.hours)
original_score = subject.score(tag3.id) original_score = subject.score(tag_ocs.id)
expect(original_score).to eq 144.0 expect(original_score).to eq 144.0
subject.refresh(yesterday + 12.hours + subject.options[:max_score_halflife]) subject.refresh(yesterday + 12.hours + subject.options[:max_score_halflife])
decayed_score = subject.score(tag3.id) decayed_score = subject.score(tag_ocs.id)
expect(decayed_score).to be <= original_score / 2 expect(decayed_score).to be <= original_score / 2
end end
end end

View File

@ -8,11 +8,11 @@ describe ActivityPub::NoteSerializer do
let!(:account) { Fabricate(:account) } let!(:account) { Fabricate(:account) }
let!(:other) { Fabricate(:account) } let!(:other) { Fabricate(:account) }
let!(:parent) { Fabricate(:status, account: account, visibility: :public) } let!(:parent) { Fabricate(:status, account: account, visibility: :public) }
let!(:reply1) { Fabricate(:status, account: account, thread: parent, visibility: :public) } let!(:reply_by_account_first) { Fabricate(:status, account: account, thread: parent, visibility: :public) }
let!(:reply2) { Fabricate(:status, account: account, thread: parent, visibility: :public) } let!(:reply_by_account_next) { Fabricate(:status, account: account, thread: parent, visibility: :public) }
let!(:reply3) { Fabricate(:status, account: other, thread: parent, visibility: :public) } let!(:reply_by_other_first) { Fabricate(:status, account: other, thread: parent, visibility: :public) }
let!(:reply4) { Fabricate(:status, account: account, thread: parent, visibility: :public) } let!(:reply_by_account_third) { Fabricate(:status, account: account, thread: parent, visibility: :public) }
let!(:reply5) { Fabricate(:status, account: account, thread: parent, visibility: :direct) } let!(:reply_by_account_visibility_direct) { Fabricate(:status, account: account, thread: parent, visibility: :direct) }
before(:each) do before(:each) do
@serialization = ActiveModelSerializers::SerializableResource.new(parent, serializer: described_class, adapter: ActivityPub::Adapter) @serialization = ActiveModelSerializers::SerializableResource.new(parent, serializer: described_class, adapter: ActivityPub::Adapter)
@ -31,14 +31,14 @@ describe ActivityPub::NoteSerializer do
end end
it 'includes public self-replies in its replies collection' do it 'includes public self-replies in its replies collection' do
expect(subject['replies']['first']['items']).to include(reply1.uri, reply2.uri, reply4.uri) expect(subject['replies']['first']['items']).to include(reply_by_account_first.uri, reply_by_account_next.uri, reply_by_account_third.uri)
end end
it 'does not include replies from others in its replies collection' do it 'does not include replies from others in its replies collection' do
expect(subject['replies']['first']['items']).to_not include(reply3.uri) expect(subject['replies']['first']['items']).to_not include(reply_by_other_first.uri)
end end
it 'does not include replies with direct visibility in its replies collection' do it 'does not include replies with direct visibility in its replies collection' do
expect(subject['replies']['first']['items']).to_not include(reply5.uri) expect(subject['replies']['first']['items']).to_not include(reply_by_account_visibility_direct.uri)
end end
end end

View File

@ -9,33 +9,33 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do
let!(:known_status) { Fabricate(:status, account: actor, uri: 'https://example.com/account/pinned/1') } let!(:known_status) { Fabricate(:status, account: actor, uri: 'https://example.com/account/pinned/1') }
let(:status_json_1) do let(:status_json_pinned_known) do
{ {
'@context': 'https://www.w3.org/ns/activitystreams', '@context': 'https://www.w3.org/ns/activitystreams',
type: 'Note', type: 'Note',
id: 'https://example.com/account/pinned/1', id: 'https://example.com/account/pinned/known',
content: 'foo', content: 'foo',
attributedTo: actor.uri, attributedTo: actor.uri,
to: 'https://www.w3.org/ns/activitystreams#Public', to: 'https://www.w3.org/ns/activitystreams#Public',
} }
end end
let(:status_json_2) do let(:status_json_pinned_unknown_inlined) do
{ {
'@context': 'https://www.w3.org/ns/activitystreams', '@context': 'https://www.w3.org/ns/activitystreams',
type: 'Note', type: 'Note',
id: 'https://example.com/account/pinned/2', id: 'https://example.com/account/pinned/unknown-inlined',
content: 'foo', content: 'foo',
attributedTo: actor.uri, attributedTo: actor.uri,
to: 'https://www.w3.org/ns/activitystreams#Public', to: 'https://www.w3.org/ns/activitystreams#Public',
} }
end end
let(:status_json_4) do let(:status_json_pinned_unknown_unreachable) do
{ {
'@context': 'https://www.w3.org/ns/activitystreams', '@context': 'https://www.w3.org/ns/activitystreams',
type: 'Note', type: 'Note',
id: 'https://example.com/account/pinned/4', id: 'https://example.com/account/pinned/unknown-reachable',
content: 'foo', content: 'foo',
attributedTo: actor.uri, attributedTo: actor.uri,
to: 'https://www.w3.org/ns/activitystreams#Public', to: 'https://www.w3.org/ns/activitystreams#Public',
@ -44,10 +44,10 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do
let(:items) do let(:items) do
[ [
'https://example.com/account/pinned/1', # known 'https://example.com/account/pinned/known', # known
status_json_2, # unknown inlined status_json_pinned_unknown_inlined, # unknown inlined
'https://example.com/account/pinned/3', # unknown unreachable 'https://example.com/account/pinned/unknown-unreachable', # unknown unreachable
'https://example.com/account/pinned/4', # unknown reachable 'https://example.com/account/pinned/unknown-reachable', # unknown reachable
] ]
end end
@ -62,16 +62,20 @@ RSpec.describe ActivityPub::FetchFeaturedCollectionService, type: :service do
shared_examples 'sets pinned posts' do shared_examples 'sets pinned posts' do
before do before do
stub_request(:get, 'https://example.com/account/pinned/1').to_return(status: 200, body: Oj.dump(status_json_1)) stub_request(:get, 'https://example.com/account/pinned/known').to_return(status: 200, body: Oj.dump(status_json_pinned_known))
stub_request(:get, 'https://example.com/account/pinned/2').to_return(status: 200, body: Oj.dump(status_json_2)) stub_request(:get, 'https://example.com/account/pinned/unknown-inlined').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_inlined))
stub_request(:get, 'https://example.com/account/pinned/3').to_return(status: 404) stub_request(:get, 'https://example.com/account/pinned/unknown-unreachable').to_return(status: 404)
stub_request(:get, 'https://example.com/account/pinned/4').to_return(status: 200, body: Oj.dump(status_json_4)) stub_request(:get, 'https://example.com/account/pinned/unknown-reachable').to_return(status: 200, body: Oj.dump(status_json_pinned_unknown_unreachable))
subject.call(actor, note: true, hashtag: false) subject.call(actor, note: true, hashtag: false)
end end
it 'sets expected posts as pinned posts' do it 'sets expected posts as pinned posts' do
expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly('https://example.com/account/pinned/1', 'https://example.com/account/pinned/2', 'https://example.com/account/pinned/4') expect(actor.pinned_statuses.pluck(:uri)).to contain_exactly(
'https://example.com/account/pinned/known',
'https://example.com/account/pinned/unknown-inlined',
'https://example.com/account/pinned/unknown-reachable'
)
end end
end end

View File

@ -10,8 +10,8 @@ RSpec.describe BatchedRemoveStatusService, type: :service do
let!(:jeff) { Fabricate(:account) } let!(:jeff) { Fabricate(:account) }
let!(:hank) { Fabricate(:account, username: 'hank', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') } let!(:hank) { Fabricate(:account, username: 'hank', protocol: :activitypub, domain: 'example.com', inbox_url: 'http://example.com/inbox') }
let(:status1) { PostStatusService.new.call(alice, text: 'Hello @bob@example.com') } let(:status_alice_hello) { PostStatusService.new.call(alice, text: 'Hello @bob@example.com') }
let(:status2) { PostStatusService.new.call(alice, text: 'Another status') } let(:status_alice_other) { PostStatusService.new.call(alice, text: 'Another status') }
before do before do
allow(redis).to receive_messages(publish: nil) allow(redis).to receive_messages(publish: nil)
@ -22,23 +22,23 @@ RSpec.describe BatchedRemoveStatusService, type: :service do
jeff.follow!(alice) jeff.follow!(alice)
hank.follow!(alice) hank.follow!(alice)
status1 status_alice_hello
status2 status_alice_other
subject.call([status1, status2]) subject.call([status_alice_hello, status_alice_other])
end end
it 'removes statuses' do it 'removes statuses' do
expect { Status.find(status1.id) }.to raise_error ActiveRecord::RecordNotFound expect { Status.find(status_alice_hello.id) }.to raise_error ActiveRecord::RecordNotFound
expect { Status.find(status2.id) }.to raise_error ActiveRecord::RecordNotFound expect { Status.find(status_alice_other.id) }.to raise_error ActiveRecord::RecordNotFound
end end
it 'removes statuses from author\'s home feed' do it 'removes statuses from author\'s home feed' do
expect(HomeFeed.new(alice).get(10)).to_not include([status1.id, status2.id]) expect(HomeFeed.new(alice).get(10)).to_not include([status_alice_hello.id, status_alice_other.id])
end end
it 'removes statuses from local follower\'s home feed' do it 'removes statuses from local follower\'s home feed' do
expect(HomeFeed.new(jeff).get(10)).to_not include([status1.id, status2.id]) expect(HomeFeed.new(jeff).get(10)).to_not include([status_alice_hello.id, status_alice_other.id])
end end
it 'notifies streaming API of followers' do it 'notifies streaming API of followers' do

View File

@ -6,9 +6,9 @@ RSpec.describe BlockDomainService, type: :service do
subject { described_class.new } subject { described_class.new }
let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') } let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') }
let!(:bad_status1) { Fabricate(:status, account: bad_account, text: 'You suck') } let!(:bad_status_plain) { Fabricate(:status, account: bad_account, text: 'You suck') }
let!(:bad_status2) { Fabricate(:status, account: bad_account, text: 'Hahaha') } let!(:bad_status_with_attachment) { Fabricate(:status, account: bad_account, text: 'Hahaha') }
let!(:bad_attachment) { Fabricate(:media_attachment, account: bad_account, status: bad_status2, file: attachment_fixture('attachment.jpg')) } let!(:bad_attachment) { Fabricate(:media_attachment, account: bad_account, status: bad_status_with_attachment, file: attachment_fixture('attachment.jpg')) }
let!(:already_banned_account) { Fabricate(:account, username: 'badguy', domain: 'evil.org', suspended: true, silenced: true) } let!(:already_banned_account) { Fabricate(:account, username: 'badguy', domain: 'evil.org', suspended: true, silenced: true) }
describe 'for a suspension' do describe 'for a suspension' do
@ -37,8 +37,8 @@ RSpec.describe BlockDomainService, type: :service do
end end
it 'removes the remote accounts\'s statuses and media attachments' do it 'removes the remote accounts\'s statuses and media attachments' do
expect { bad_status1.reload }.to raise_exception ActiveRecord::RecordNotFound expect { bad_status_plain.reload }.to raise_exception ActiveRecord::RecordNotFound
expect { bad_status2.reload }.to raise_exception ActiveRecord::RecordNotFound expect { bad_status_with_attachment.reload }.to raise_exception ActiveRecord::RecordNotFound
expect { bad_attachment.reload }.to raise_exception ActiveRecord::RecordNotFound expect { bad_attachment.reload }.to raise_exception ActiveRecord::RecordNotFound
end end
end end
@ -69,8 +69,8 @@ RSpec.describe BlockDomainService, type: :service do
end end
it 'leaves the domains status and attachments, but clears media' do it 'leaves the domains status and attachments, but clears media' do
expect { bad_status1.reload }.to_not raise_error expect { bad_status_plain.reload }.to_not raise_error
expect { bad_status2.reload }.to_not raise_error expect { bad_status_with_attachment.reload }.to_not raise_error
expect { bad_attachment.reload }.to_not raise_error expect { bad_attachment.reload }.to_not raise_error
expect(bad_attachment.file.exists?).to be false expect(bad_attachment.file.exists?).to be false
end end

View File

@ -6,9 +6,9 @@ RSpec.describe ClearDomainMediaService, type: :service do
subject { described_class.new } subject { described_class.new }
let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') } let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') }
let!(:bad_status1) { Fabricate(:status, account: bad_account, text: 'You suck') } let!(:bad_status_plain) { Fabricate(:status, account: bad_account, text: 'You suck') }
let!(:bad_status2) { Fabricate(:status, account: bad_account, text: 'Hahaha') } let!(:bad_status_with_attachment) { Fabricate(:status, account: bad_account, text: 'Hahaha') }
let!(:bad_attachment) { Fabricate(:media_attachment, account: bad_account, status: bad_status2, file: attachment_fixture('attachment.jpg')) } let!(:bad_attachment) { Fabricate(:media_attachment, account: bad_account, status: bad_status_with_attachment, file: attachment_fixture('attachment.jpg')) }
describe 'for a silence with reject media' do describe 'for a silence with reject media' do
before do before do
@ -16,8 +16,8 @@ RSpec.describe ClearDomainMediaService, type: :service do
end end
it 'leaves the domains status and attachments, but clears media' do it 'leaves the domains status and attachments, but clears media' do
expect { bad_status1.reload }.to_not raise_error expect { bad_status_plain.reload }.to_not raise_error
expect { bad_status2.reload }.to_not raise_error expect { bad_status_with_attachment.reload }.to_not raise_error
expect { bad_attachment.reload }.to_not raise_error expect { bad_attachment.reload }.to_not raise_error
expect(bad_attachment.file.exists?).to be false expect(bad_attachment.file.exists?).to be false
end end

View File

@ -6,9 +6,9 @@ RSpec.describe PurgeDomainService, type: :service do
subject { described_class.new } subject { described_class.new }
let!(:old_account) { Fabricate(:account, domain: 'obsolete.org') } let!(:old_account) { Fabricate(:account, domain: 'obsolete.org') }
let!(:old_status1) { Fabricate(:status, account: old_account) } let!(:old_status_plain) { Fabricate(:status, account: old_account) }
let!(:old_status2) { Fabricate(:status, account: old_account) } let!(:old_status_with_attachment) { Fabricate(:status, account: old_account) }
let!(:old_attachment) { Fabricate(:media_attachment, account: old_account, status: old_status2, file: attachment_fixture('attachment.jpg')) } let!(:old_attachment) { Fabricate(:media_attachment, account: old_account, status: old_status_with_attachment, file: attachment_fixture('attachment.jpg')) }
describe 'for a suspension' do describe 'for a suspension' do
before do before do
@ -17,8 +17,8 @@ RSpec.describe PurgeDomainService, type: :service do
it 'removes the remote accounts\'s statuses and media attachments' do it 'removes the remote accounts\'s statuses and media attachments' do
expect { old_account.reload }.to raise_exception ActiveRecord::RecordNotFound expect { old_account.reload }.to raise_exception ActiveRecord::RecordNotFound
expect { old_status1.reload }.to raise_exception ActiveRecord::RecordNotFound expect { old_status_plain.reload }.to raise_exception ActiveRecord::RecordNotFound
expect { old_status2.reload }.to raise_exception ActiveRecord::RecordNotFound expect { old_status_with_attachment.reload }.to raise_exception ActiveRecord::RecordNotFound
expect { old_attachment.reload }.to raise_exception ActiveRecord::RecordNotFound expect { old_attachment.reload }.to raise_exception ActiveRecord::RecordNotFound
end end

View File

@ -6,9 +6,9 @@ RSpec.describe UnallowDomainService, type: :service do
subject { described_class.new } subject { described_class.new }
let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') } let!(:bad_account) { Fabricate(:account, username: 'badguy666', domain: 'evil.org') }
let!(:bad_status1) { Fabricate(:status, account: bad_account, text: 'You suck') } let!(:bad_status_harassment) { Fabricate(:status, account: bad_account, text: 'You suck') }
let!(:bad_status2) { Fabricate(:status, account: bad_account, text: 'Hahaha') } let!(:bad_status_mean) { Fabricate(:status, account: bad_account, text: 'Hahaha') }
let!(:bad_attachment) { Fabricate(:media_attachment, account: bad_account, status: bad_status2, file: attachment_fixture('attachment.jpg')) } let!(:bad_attachment) { Fabricate(:media_attachment, account: bad_account, status: bad_status_mean, file: attachment_fixture('attachment.jpg')) }
let!(:already_banned_account) { Fabricate(:account, username: 'badguy', domain: 'evil.org', suspended: true, silenced: true) } let!(:already_banned_account) { Fabricate(:account, username: 'badguy', domain: 'evil.org', suspended: true, silenced: true) }
let!(:domain_allow) { Fabricate(:domain_allow, domain: 'evil.org') } let!(:domain_allow) { Fabricate(:domain_allow, domain: 'evil.org') }
@ -31,8 +31,8 @@ RSpec.describe UnallowDomainService, type: :service do
end end
it 'removes the remote accounts\'s statuses and media attachments' do it 'removes the remote accounts\'s statuses and media attachments' do
expect { bad_status1.reload }.to raise_exception ActiveRecord::RecordNotFound expect { bad_status_harassment.reload }.to raise_exception ActiveRecord::RecordNotFound
expect { bad_status2.reload }.to raise_exception ActiveRecord::RecordNotFound expect { bad_status_mean.reload }.to raise_exception ActiveRecord::RecordNotFound
expect { bad_attachment.reload }.to raise_exception ActiveRecord::RecordNotFound expect { bad_attachment.reload }.to raise_exception ActiveRecord::RecordNotFound
end end
end end
@ -57,8 +57,8 @@ RSpec.describe UnallowDomainService, type: :service do
end end
it 'removes the remote accounts\'s statuses and media attachments' do it 'removes the remote accounts\'s statuses and media attachments' do
expect { bad_status1.reload }.to_not raise_error expect { bad_status_harassment.reload }.to_not raise_error
expect { bad_status2.reload }.to_not raise_error expect { bad_status_mean.reload }.to_not raise_error
expect { bad_attachment.reload }.to_not raise_error expect { bad_attachment.reload }.to_not raise_error
end end
end end

View File

@ -5,11 +5,11 @@ require 'rails_helper'
describe Scheduler::AccountsStatusesCleanupScheduler do describe Scheduler::AccountsStatusesCleanupScheduler do
subject { described_class.new } subject { described_class.new }
let!(:account1) { Fabricate(:account, domain: nil) } let!(:account_alice) { Fabricate(:account, domain: nil, username: 'alice') }
let!(:account2) { Fabricate(:account, domain: nil) } let!(:account_bob) { Fabricate(:account, domain: nil, username: 'bob') }
let!(:account3) { Fabricate(:account, domain: nil) } let!(:account_chris) { Fabricate(:account, domain: nil, username: 'chris') }
let!(:account4) { Fabricate(:account, domain: nil) } let!(:account_dave) { Fabricate(:account, domain: nil, username: 'dave') }
let!(:account5) { Fabricate(:account, domain: nil) } let!(:account_erin) { Fabricate(:account, domain: nil, username: 'erin') }
let!(:remote) { Fabricate(:account) } let!(:remote) { Fabricate(:account) }
let(:queue_size) { 0 } let(:queue_size) { 0 }
@ -77,26 +77,26 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
describe '#perform' do describe '#perform' do
before do before do
# Policies for the accounts # Policies for the accounts
Fabricate(:account_statuses_cleanup_policy, account: account1) Fabricate(:account_statuses_cleanup_policy, account: account_alice)
Fabricate(:account_statuses_cleanup_policy, account: account3) Fabricate(:account_statuses_cleanup_policy, account: account_chris)
Fabricate(:account_statuses_cleanup_policy, account: account4, enabled: false) Fabricate(:account_statuses_cleanup_policy, account: account_dave, enabled: false)
Fabricate(:account_statuses_cleanup_policy, account: account5) Fabricate(:account_statuses_cleanup_policy, account: account_erin)
# Create a bunch of old statuses # Create a bunch of old statuses
4.times do 4.times do
Fabricate(:status, account: account1, created_at: 3.years.ago) Fabricate(:status, account: account_alice, created_at: 3.years.ago)
Fabricate(:status, account: account2, created_at: 3.years.ago) Fabricate(:status, account: account_bob, created_at: 3.years.ago)
Fabricate(:status, account: account3, created_at: 3.years.ago) Fabricate(:status, account: account_chris, created_at: 3.years.ago)
Fabricate(:status, account: account4, created_at: 3.years.ago) Fabricate(:status, account: account_dave, created_at: 3.years.ago)
Fabricate(:status, account: account5, created_at: 3.years.ago) Fabricate(:status, account: account_erin, created_at: 3.years.ago)
Fabricate(:status, account: remote, created_at: 3.years.ago) Fabricate(:status, account: remote, created_at: 3.years.ago)
end end
# Create a bunch of newer statuses # Create a bunch of newer statuses
Fabricate(:status, account: account1, created_at: 3.minutes.ago) Fabricate(:status, account: account_alice, created_at: 3.minutes.ago)
Fabricate(:status, account: account2, created_at: 3.minutes.ago) Fabricate(:status, account: account_bob, created_at: 3.minutes.ago)
Fabricate(:status, account: account3, created_at: 3.minutes.ago) Fabricate(:status, account: account_chris, created_at: 3.minutes.ago)
Fabricate(:status, account: account4, created_at: 3.minutes.ago) Fabricate(:status, account: account_dave, created_at: 3.minutes.ago)
Fabricate(:status, account: remote, created_at: 3.minutes.ago) Fabricate(:status, account: remote, created_at: 3.minutes.ago)
end end
@ -106,8 +106,8 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
expect { subject.perform } expect { subject.perform }
.to change(Status, :count).by(-subject.compute_budget) # Cleanable statuses .to change(Status, :count).by(-subject.compute_budget) # Cleanable statuses
.and (not_change { account2.statuses.count }) # No cleanup policy for account .and (not_change { account_bob.statuses.count }) # No cleanup policy for account
.and(not_change { account4.statuses.count }) # Disabled cleanup policy .and(not_change { account_dave.statuses.count }) # Disabled cleanup policy
end end
it 'eventually deletes every deletable toot given enough runs' do it 'eventually deletes every deletable toot given enough runs' do
@ -122,9 +122,9 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
expect { 3.times { subject.perform } } expect { 3.times { subject.perform } }
.to change(Status, :count).by(-3 * 3) .to change(Status, :count).by(-3 * 3)
.and change { account1.statuses.count } .and change { account_alice.statuses.count }
.and change { account3.statuses.count } .and change { account_chris.statuses.count }
.and(change { account5.statuses.count }) .and(change { account_erin.statuses.count })
end end
context 'when given a big budget' do context 'when given a big budget' do
@ -156,7 +156,7 @@ describe Scheduler::AccountsStatusesCleanupScheduler do
def cleanable_statuses_count def cleanable_statuses_count
Status Status
.where(account_id: [account1, account3, account5]) # Accounts with enabled policies .where(account_id: [account_alice, account_chris, account_erin]) # Accounts with enabled policies
.where('created_at < ?', 2.weeks.ago) # Policy defaults is 2.weeks .where('created_at < ?', 2.weeks.ago) # Policy defaults is 2.weeks
.count .count
end end