diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/api/v1/accounts_controller_spec.rb | 34 | ||||
-rw-r--r-- | spec/fabricators/user_fabricator.rb | 1 | ||||
-rw-r--r-- | spec/lib/activitypub/activity/block_spec.rb | 67 | ||||
-rw-r--r-- | spec/mailers/notification_mailer_spec.rb | 14 | ||||
-rw-r--r-- | spec/models/user_spec.rb | 14 | ||||
-rw-r--r-- | spec/services/activitypub/process_collection_service_spec.rb | 6 | ||||
-rw-r--r-- | spec/services/app_sign_up_service_spec.rb | 41 | ||||
-rw-r--r-- | spec/services/post_status_service_spec.rb | 7 | ||||
-rw-r--r-- | spec/validators/blacklisted_email_validator_spec.rb | 31 | ||||
-rw-r--r-- | spec/validators/disallowed_hashtags_validator_spec.rb | 46 | ||||
-rw-r--r-- | spec/validators/follow_limit_validator_spec.rb | 51 | ||||
-rw-r--r-- | spec/validators/status_length_validator_spec.rb | 13 | ||||
-rw-r--r-- | spec/validators/status_pin_validator_spec.rb | 57 |
13 files changed, 352 insertions, 30 deletions
diff --git a/spec/controllers/api/v1/accounts_controller_spec.rb b/spec/controllers/api/v1/accounts_controller_spec.rb index c506fb5f0..f5f65c000 100644 --- a/spec/controllers/api/v1/accounts_controller_spec.rb +++ b/spec/controllers/api/v1/accounts_controller_spec.rb @@ -19,6 +19,40 @@ RSpec.describe Api::V1::AccountsController, type: :controller do end end + describe 'POST #create' do + let(:app) { Fabricate(:application) } + let(:token) { Doorkeeper::AccessToken.find_or_create_for(app, nil, 'read write', nil, false) } + let(:agreement) { nil } + + before do + post :create, params: { username: 'test', password: '12345678', email: 'hello@world.tld', agreement: agreement } + end + + context 'given truthy agreement' do + let(:agreement) { 'true' } + + it 'returns http success' do + expect(response).to have_http_status(200) + end + + it 'returns a new access token as JSON' do + expect(body_as_json[:access_token]).to_not be_blank + end + + it 'creates a user' do + user = User.find_by(email: 'hello@world.tld') + expect(user).to_not be_nil + expect(user.created_by_application_id).to eq app.id + end + end + + context 'given no agreement' do + it 'returns http unprocessable entity' do + expect(response).to have_http_status(422) + end + end + end + describe 'GET #show' do let(:scopes) { 'read:accounts' } diff --git a/spec/fabricators/user_fabricator.rb b/spec/fabricators/user_fabricator.rb index 7dfbdb52d..8f5956501 100644 --- a/spec/fabricators/user_fabricator.rb +++ b/spec/fabricators/user_fabricator.rb @@ -3,4 +3,5 @@ Fabricator(:user) do email { sequence(:email) { |i| "#{i}#{Faker::Internet.email}" } } password "123456789" confirmed_at { Time.zone.now } + agreement true end diff --git a/spec/lib/activitypub/activity/block_spec.rb b/spec/lib/activitypub/activity/block_spec.rb index 23c8cc31c..94d37356d 100644 --- a/spec/lib/activitypub/activity/block_spec.rb +++ b/spec/lib/activitypub/activity/block_spec.rb @@ -14,15 +14,72 @@ RSpec.describe ActivityPub::Activity::Block do }.with_indifferent_access end - describe '#perform' do - subject { described_class.new(json, sender) } + context 'when the recipient does not follow the sender' do + describe '#perform' do + subject { described_class.new(json, sender) } + + before do + subject.perform + end + + it 'creates a block from sender to recipient' do + expect(sender.blocking?(recipient)).to be true + end + end + end + + context 'when the recipient follows the sender' do + before do + recipient.follow!(sender) + end + + describe '#perform' do + subject { described_class.new(json, sender) } + + before do + subject.perform + end + + it 'creates a block from sender to recipient' do + expect(sender.blocking?(recipient)).to be true + end + + it 'ensures recipient is not following sender' do + expect(recipient.following?(sender)).to be false + end + end + end + + context 'when a matching undo has been received first' do + let(:undo_json) do + { + '@context': 'https://www.w3.org/ns/activitystreams', + id: 'bar', + type: 'Undo', + actor: ActivityPub::TagManager.instance.uri_for(sender), + object: json, + }.with_indifferent_access + end before do - subject.perform + recipient.follow!(sender) + ActivityPub::Activity::Undo.new(undo_json, sender).perform end - it 'creates a block from sender to recipient' do - expect(sender.blocking?(recipient)).to be true + describe '#perform' do + subject { described_class.new(json, sender) } + + before do + subject.perform + end + + it 'does not create a block from sender to recipient' do + expect(sender.blocking?(recipient)).to be false + end + + it 'ensures recipient is not following sender' do + expect(recipient.following?(sender)).to be false + end end end end diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index 1be01e8ba..38916b54f 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -126,19 +126,7 @@ RSpec.describe NotificationMailer, type: :mailer do end end - it 'includes activities since the date specified by :since option' do - receiver.update!(last_emailed_at: '2000-02-01T00:00:00Z', current_sign_in_at: '2000-03-01T00:00:00Z') - mail = NotificationMailer.digest(receiver.account, since: Time.parse('2000-01-01T00:00:00Z')) - expect(mail.body.encoded).to include 'Jan 01, 2000, 00:00' - end - - it 'includes activities since the receiver was last emailed if :since option is unavailable' do - receiver.update!(last_emailed_at: '2000-02-01T00:00:00Z', current_sign_in_at: '2000-03-01T00:00:00Z') - mail = NotificationMailer.digest(receiver.account) - expect(mail.body.encoded).to include 'Feb 01, 2000, 00:00' - end - - it 'includes activities since the receiver last signed in if :since option and the last emailed date are unavailable' do + it 'includes activities since the receiver last signed in' do receiver.update!(last_emailed_at: nil, current_sign_in_at: '2000-03-01T00:00:00Z') mail = NotificationMailer.digest(receiver.account) expect(mail.body.encoded).to include 'Mar 01, 2000, 00:00' diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index c82919597..856254ce4 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -106,19 +106,19 @@ RSpec.describe User, type: :model do end it 'should allow a non-blacklisted user to be created' do - user = User.new(email: 'foo@example.com', account: account, password: password) + user = User.new(email: 'foo@example.com', account: account, password: password, agreement: true) expect(user.valid?).to be_truthy end it 'should not allow a blacklisted user to be created' do - user = User.new(email: 'foo@mvrht.com', account: account, password: password) + user = User.new(email: 'foo@mvrht.com', account: account, password: password, agreement: true) expect(user.valid?).to be_falsey end it 'should not allow a subdomain blacklisted user to be created' do - user = User.new(email: 'foo@mvrht.com.topdomain.tld', account: account, password: password) + user = User.new(email: 'foo@mvrht.com.topdomain.tld', account: account, password: password, agreement: true) expect(user.valid?).to be_falsey end @@ -210,17 +210,17 @@ RSpec.describe User, type: :model do end it 'should not allow a user to be created unless they are whitelisted' do - user = User.new(email: 'foo@example.com', account: account, password: password) + user = User.new(email: 'foo@example.com', account: account, password: password, agreement: true) expect(user.valid?).to be_falsey end it 'should allow a user to be created if they are whitelisted' do - user = User.new(email: 'foo@mastodon.space', account: account, password: password) + user = User.new(email: 'foo@mastodon.space', account: account, password: password, agreement: true) expect(user.valid?).to be_truthy end it 'should not allow a user with a whitelisted top domain as subdomain in their email address to be created' do - user = User.new(email: 'foo@mastodon.space.userdomain.com', account: account, password: password) + user = User.new(email: 'foo@mastodon.space.userdomain.com', account: account, password: password, agreement: true) expect(user.valid?).to be_falsey end @@ -242,7 +242,7 @@ RSpec.describe User, type: :model do it_behaves_like 'Settings-extended' do def create! - User.create!(account: Fabricate(:account), email: 'foo@mastodon.space', password: 'abcd1234') + User.create!(account: Fabricate(:account), email: 'foo@mastodon.space', password: 'abcd1234', agreement: true) end def fabricate diff --git a/spec/services/activitypub/process_collection_service_spec.rb b/spec/services/activitypub/process_collection_service_spec.rb index bbe97d211..b3baf6b6b 100644 --- a/spec/services/activitypub/process_collection_service_spec.rb +++ b/spec/services/activitypub/process_collection_service_spec.rb @@ -26,9 +26,9 @@ RSpec.describe ActivityPub::ProcessCollectionService, type: :service do context 'when actor differs from sender' do let(:forwarder) { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/other_account') } - it 'processes payload with sender if no signature exists' do - expect_any_instance_of(ActivityPub::LinkedDataSignature).not_to receive(:verify_account!) - expect(ActivityPub::Activity).to receive(:factory).with(instance_of(Hash), forwarder, instance_of(Hash)) + it 'does not process payload if no signature exists' do + expect_any_instance_of(ActivityPub::LinkedDataSignature).to receive(:verify_account!).and_return(nil) + expect(ActivityPub::Activity).not_to receive(:factory) subject.call(json, forwarder) end diff --git a/spec/services/app_sign_up_service_spec.rb b/spec/services/app_sign_up_service_spec.rb new file mode 100644 index 000000000..d480df348 --- /dev/null +++ b/spec/services/app_sign_up_service_spec.rb @@ -0,0 +1,41 @@ +require 'rails_helper' + +RSpec.describe AppSignUpService, type: :service do + let(:app) { Fabricate(:application, scopes: 'read write') } + let(:good_params) { { username: 'alice', password: '12345678', email: 'good@email.com', agreement: true } } + + subject { described_class.new } + + describe '#call' do + it 'returns nil when registrations are closed' do + Setting.open_registrations = false + expect(subject.call(app, good_params)).to be_nil + end + + it 'raises an error when params are missing' do + expect { subject.call(app, {}) }.to raise_error ActiveRecord::RecordInvalid + end + + it 'creates an unconfirmed user with access token' do + access_token = subject.call(app, good_params) + expect(access_token).to_not be_nil + user = User.find_by(id: access_token.resource_owner_id) + expect(user).to_not be_nil + expect(user.confirmed?).to be false + end + + it 'creates access token with the app\'s scopes' do + access_token = subject.call(app, good_params) + expect(access_token).to_not be_nil + expect(access_token.scopes.to_s).to eq 'read write' + end + + it 'creates an account' do + access_token = subject.call(app, good_params) + expect(access_token).to_not be_nil + user = User.find_by(id: access_token.resource_owner_id) + expect(user).to_not be_nil + expect(user.account).to_not be_nil + end + end +end diff --git a/spec/services/post_status_service_spec.rb b/spec/services/post_status_service_spec.rb index 349ad861b..8f3552224 100644 --- a/spec/services/post_status_service_spec.rb +++ b/spec/services/post_status_service_spec.rb @@ -68,6 +68,13 @@ RSpec.describe PostStatusService, type: :service do expect(status.visibility).to eq "private" end + it 'creates a status with limited visibility for silenced users' do + status = subject.call(Fabricate(:account, silenced: true), 'test', nil, visibility: :public) + + expect(status).to be_persisted + expect(status.visibility).to eq "unlisted" + end + it 'creates a status for the given application' do application = Fabricate(:application) diff --git a/spec/validators/blacklisted_email_validator_spec.rb b/spec/validators/blacklisted_email_validator_spec.rb new file mode 100644 index 000000000..d2e442f4a --- /dev/null +++ b/spec/validators/blacklisted_email_validator_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe BlacklistedEmailValidator, type: :validator do + describe '#validate' do + let(:user) { double(email: 'info@mail.com', errors: errors) } + let(:errors) { double(add: nil) } + + before do + allow_any_instance_of(described_class).to receive(:blocked_email?) { blocked_email } + described_class.new.validate(user) + end + + context 'blocked_email?' do + let(:blocked_email) { true } + + it 'calls errors.add' do + expect(errors).to have_received(:add).with(:email, I18n.t('users.invalid_email')) + end + end + + context '!blocked_email?' do + let(:blocked_email) { false } + + it 'not calls errors.add' do + expect(errors).not_to have_received(:add).with(:email, I18n.t('users.invalid_email')) + end + end + end +end diff --git a/spec/validators/disallowed_hashtags_validator_spec.rb b/spec/validators/disallowed_hashtags_validator_spec.rb new file mode 100644 index 000000000..8ec1302ab --- /dev/null +++ b/spec/validators/disallowed_hashtags_validator_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe DisallowedHashtagsValidator, type: :validator do + describe '#validate' do + before do + allow_any_instance_of(described_class).to receive(:select_tags) { tags } + described_class.new.validate(status) + end + + let(:status) { double(errors: errors, local?: local, reblog?: reblog, text: '') } + let(:errors) { double(add: nil) } + + context 'unless status.local? && !status.reblog?' do + let(:local) { false } + let(:reblog) { true } + + it 'not calls errors.add' do + expect(errors).not_to have_received(:add).with(:text, any_args) + end + end + + context 'status.local? && !status.reblog?' do + let(:local) { true } + let(:reblog) { false } + + context 'tags.empty?' do + let(:tags) { [] } + + it 'not calls errors.add' do + expect(errors).not_to have_received(:add).with(:text, any_args) + end + end + + context '!tags.empty?' do + let(:tags) { %w(a b c) } + + it 'calls errors.add' do + expect(errors).to have_received(:add) + .with(:text, I18n.t('statuses.disallowed_hashtags', tags: tags.join(', '), count: tags.size)) + end + end + end + end +end diff --git a/spec/validators/follow_limit_validator_spec.rb b/spec/validators/follow_limit_validator_spec.rb new file mode 100644 index 000000000..cc8fbb631 --- /dev/null +++ b/spec/validators/follow_limit_validator_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe FollowLimitValidator, type: :validator do + describe '#validate' do + before do + allow_any_instance_of(described_class).to receive(:limit_reached?).with(account) do + limit_reached + end + + described_class.new.validate(follow) + end + + let(:follow) { double(account: account, errors: errors) } + let(:errors) { double(add: nil) } + let(:account) { double(nil?: _nil, local?: local, following_count: 0, followers_count: 0) } + let(:_nil) { true } + let(:local) { false } + + context 'follow.account.nil? || !follow.account.local?' do + let(:_nil) { true } + + it 'not calls errors.add' do + expect(errors).not_to have_received(:add).with(:base, any_args) + end + end + + context '!(follow.account.nil? || !follow.account.local?)' do + let(:_nil) { false } + let(:local) { true } + + context 'limit_reached?' do + let(:limit_reached) { true } + + it 'calls errors.add' do + expect(errors).to have_received(:add) + .with(:base, I18n.t('users.follow_limit_reached', limit: FollowLimitValidator::LIMIT)) + end + end + + context '!limit_reached?' do + let(:limit_reached) { false } + + it 'not calls errors.add' do + expect(errors).not_to have_received(:add).with(:base, any_args) + end + end + end + end +end diff --git a/spec/validators/status_length_validator_spec.rb b/spec/validators/status_length_validator_spec.rb index 9355c7e3f..62791cd2f 100644 --- a/spec/validators/status_length_validator_spec.rb +++ b/spec/validators/status_length_validator_spec.rb @@ -4,8 +4,17 @@ require 'rails_helper' describe StatusLengthValidator do describe '#validate' do - it 'does not add errors onto remote statuses' - it 'does not add errors onto local reblogs' + it 'does not add errors onto remote statuses' do + status = double(local?: false) + subject.validate(status) + expect(status).not_to receive(:errors) + end + + it 'does not add errors onto local reblogs' do + status = double(local?: false, reblog?: true) + subject.validate(status) + expect(status).not_to receive(:errors) + end it 'adds an error when content warning is over MAX_CHARS characters' do chars = StatusLengthValidator::MAX_CHARS + 1 diff --git a/spec/validators/status_pin_validator_spec.rb b/spec/validators/status_pin_validator_spec.rb new file mode 100644 index 000000000..06532e5b3 --- /dev/null +++ b/spec/validators/status_pin_validator_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe StatusPinValidator, type: :validator do + describe '#validate' do + before do + subject.validate(pin) + end + + let(:pin) { double(account: account, errors: errors, status: status, account_id: pin_account_id) } + let(:status) { double(reblog?: reblog, account_id: status_account_id, visibility: visibility) } + let(:account) { double(status_pins: status_pins, local?: local) } + let(:status_pins) { double(count: count) } + let(:errors) { double(add: nil) } + let(:pin_account_id) { 1 } + let(:status_account_id) { 1 } + let(:visibility) { 'public' } + let(:local) { false } + let(:reblog) { false } + let(:count) { 0 } + + context 'pin.status.reblog?' do + let(:reblog) { true } + + it 'calls errors.add' do + expect(errors).to have_received(:add).with(:base, I18n.t('statuses.pin_errors.reblog')) + end + end + + context 'pin.account_id != pin.status.account_id' do + let(:pin_account_id) { 1 } + let(:status_account_id) { 2 } + + it 'calls errors.add' do + expect(errors).to have_received(:add).with(:base, I18n.t('statuses.pin_errors.ownership')) + end + end + + context 'unless %w(public unlisted).include?(pin.status.visibility)' do + let(:visibility) { '' } + + it 'calls errors.add' do + expect(errors).to have_received(:add).with(:base, I18n.t('statuses.pin_errors.private')) + end + end + + context 'pin.account.status_pins.count > 4 && pin.account.local?' do + let(:count) { 5 } + let(:local) { true } + + it 'calls errors.add' do + expect(errors).to have_received(:add).with(:base, I18n.t('statuses.pin_errors.limit')) + end + end + end +end |