~cytrogen/masto-fe

05f9e39b32f15d71eb9ec524d1ab871e5c0d03da — Matt Jankowski 2 years ago 38433cc
Fix `RSpec/VerifiedDoubles` cop (#25469)

50 files changed, 162 insertions(+), 172 deletions(-)

M .rubocop_todo.yml
M spec/controllers/admin/change_emails_controller_spec.rb
M spec/controllers/admin/confirmations_controller_spec.rb
M spec/controllers/admin/disputes/appeals_controller_spec.rb
M spec/controllers/admin/domain_allows_controller_spec.rb
M spec/controllers/admin/domain_blocks_controller_spec.rb
M spec/controllers/api/v1/reports_controller_spec.rb
M spec/controllers/api/web/embeds_controller_spec.rb
M spec/controllers/auth/sessions_controller_spec.rb
M spec/controllers/authorize_interactions_controller_spec.rb
M spec/controllers/disputes/appeals_controller_spec.rb
M spec/helpers/statuses_helper_spec.rb
M spec/lib/activitypub/activity/add_spec.rb
M spec/lib/activitypub/activity/move_spec.rb
M spec/lib/request_spec.rb
M spec/lib/suspicious_sign_in_detector_spec.rb
M spec/models/account/field_spec.rb
M spec/models/account_migration_spec.rb
M spec/models/session_activation_spec.rb
M spec/models/setting_spec.rb
M spec/services/account_search_service_spec.rb
M spec/services/bootstrap_timeline_service_spec.rb
M spec/services/bulk_import_service_spec.rb
M spec/services/fetch_resource_service_spec.rb
M spec/services/import_service_spec.rb
M spec/services/post_status_service_spec.rb
M spec/services/resolve_url_service_spec.rb
M spec/services/search_service_spec.rb
M spec/services/unsuspend_account_service_spec.rb
M spec/validators/blacklisted_email_validator_spec.rb
M spec/validators/disallowed_hashtags_validator_spec.rb
M spec/validators/email_mx_validator_spec.rb
M spec/validators/follow_limit_validator_spec.rb
M spec/validators/note_length_validator_spec.rb
M spec/validators/poll_validator_spec.rb
M spec/validators/status_length_validator_spec.rb
M spec/validators/status_pin_validator_spec.rb
M spec/validators/unique_username_validator_spec.rb
M spec/validators/unreserved_username_validator_spec.rb
M spec/validators/url_validator_spec.rb
M spec/views/statuses/show.html.haml_spec.rb
M spec/workers/activitypub/processing_worker_spec.rb
M spec/workers/admin/domain_purge_worker_spec.rb
M spec/workers/domain_block_worker_spec.rb
M spec/workers/domain_clear_media_worker_spec.rb
M spec/workers/feed_insert_worker_spec.rb
M spec/workers/move_worker_spec.rb
M spec/workers/publish_scheduled_announcement_worker_spec.rb
M spec/workers/refollow_worker_spec.rb
M spec/workers/regeneration_worker_spec.rb
M .rubocop_todo.yml => .rubocop_todo.yml +0 -39
@@ 437,45 437,6 @@ RSpec/SubjectStub:
    - 'spec/services/unallow_domain_service_spec.rb'
    - 'spec/validators/blacklisted_email_validator_spec.rb'

# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
RSpec/VerifiedDoubles:
  Exclude:
    - 'spec/controllers/admin/change_emails_controller_spec.rb'
    - 'spec/controllers/admin/confirmations_controller_spec.rb'
    - 'spec/controllers/admin/disputes/appeals_controller_spec.rb'
    - 'spec/controllers/admin/domain_allows_controller_spec.rb'
    - 'spec/controllers/admin/domain_blocks_controller_spec.rb'
    - 'spec/controllers/api/v1/reports_controller_spec.rb'
    - 'spec/controllers/api/web/embeds_controller_spec.rb'
    - 'spec/controllers/auth/sessions_controller_spec.rb'
    - 'spec/controllers/disputes/appeals_controller_spec.rb'
    - 'spec/helpers/statuses_helper_spec.rb'
    - 'spec/lib/suspicious_sign_in_detector_spec.rb'
    - 'spec/models/account/field_spec.rb'
    - 'spec/models/session_activation_spec.rb'
    - 'spec/models/setting_spec.rb'
    - 'spec/services/account_search_service_spec.rb'
    - 'spec/services/post_status_service_spec.rb'
    - 'spec/services/search_service_spec.rb'
    - 'spec/validators/blacklisted_email_validator_spec.rb'
    - 'spec/validators/disallowed_hashtags_validator_spec.rb'
    - 'spec/validators/email_mx_validator_spec.rb'
    - 'spec/validators/follow_limit_validator_spec.rb'
    - 'spec/validators/note_length_validator_spec.rb'
    - 'spec/validators/poll_validator_spec.rb'
    - 'spec/validators/status_length_validator_spec.rb'
    - 'spec/validators/status_pin_validator_spec.rb'
    - 'spec/validators/unique_username_validator_spec.rb'
    - 'spec/validators/unreserved_username_validator_spec.rb'
    - 'spec/validators/url_validator_spec.rb'
    - 'spec/views/statuses/show.html.haml_spec.rb'
    - 'spec/workers/activitypub/processing_worker_spec.rb'
    - 'spec/workers/admin/domain_purge_worker_spec.rb'
    - 'spec/workers/domain_block_worker_spec.rb'
    - 'spec/workers/domain_clear_media_worker_spec.rb'
    - 'spec/workers/feed_insert_worker_spec.rb'
    - 'spec/workers/regeneration_worker_spec.rb'

# This cop supports unsafe autocorrection (--autocorrect-all).
Rails/ApplicationController:
  Exclude:

M spec/controllers/admin/change_emails_controller_spec.rb => spec/controllers/admin/change_emails_controller_spec.rb +2 -1
@@ 23,7 23,8 @@ RSpec.describe Admin::ChangeEmailsController do

  describe 'GET #update' do
    before do
      allow(UserMailer).to receive(:confirmation_instructions).and_return(double('email', deliver_later: nil))
      allow(UserMailer).to receive(:confirmation_instructions)
        .and_return(instance_double(ActionMailer::MessageDelivery, deliver_later: nil))
    end

    it 'returns http success' do

M spec/controllers/admin/confirmations_controller_spec.rb => spec/controllers/admin/confirmations_controller_spec.rb +1 -1
@@ 38,7 38,7 @@ RSpec.describe Admin::ConfirmationsController do
    let!(:user) { Fabricate(:user, confirmed_at: confirmed_at) }

    before do
      allow(UserMailer).to receive(:confirmation_instructions) { double(:email, deliver_later: nil) }
      allow(UserMailer).to receive(:confirmation_instructions) { instance_double(ActionMailer::MessageDelivery, deliver_later: nil) }
    end

    context 'when email is not confirmed' do

M spec/controllers/admin/disputes/appeals_controller_spec.rb => spec/controllers/admin/disputes/appeals_controller_spec.rb +4 -2
@@ 19,7 19,8 @@ RSpec.describe Admin::Disputes::AppealsController do
    let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }

    before do
      allow(UserMailer).to receive(:appeal_approved).and_return(double('email', deliver_later: nil))
      allow(UserMailer).to receive(:appeal_approved)
        .and_return(instance_double(ActionMailer::MessageDelivery, deliver_later: nil))
      post :approve, params: { id: appeal.id }
    end



@@ 40,7 41,8 @@ RSpec.describe Admin::Disputes::AppealsController do
    let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }

    before do
      allow(UserMailer).to receive(:appeal_rejected).and_return(double('email', deliver_later: nil))
      allow(UserMailer).to receive(:appeal_rejected)
        .and_return(instance_double(ActionMailer::MessageDelivery, deliver_later: nil))
      post :reject, params: { id: appeal.id }
    end


M spec/controllers/admin/domain_allows_controller_spec.rb => spec/controllers/admin/domain_allows_controller_spec.rb +1 -1
@@ 37,7 37,7 @@ RSpec.describe Admin::DomainAllowsController do

  describe 'DELETE #destroy' do
    it 'disallows the domain' do
      service = double(call: true)
      service = instance_double(UnallowDomainService, call: true)
      allow(UnallowDomainService).to receive(:new).and_return(service)
      domain_allow = Fabricate(:domain_allow)
      delete :destroy, params: { id: domain_allow.id }

M spec/controllers/admin/domain_blocks_controller_spec.rb => spec/controllers/admin/domain_blocks_controller_spec.rb +1 -1
@@ 213,7 213,7 @@ RSpec.describe Admin::DomainBlocksController do

  describe 'DELETE #destroy' do
    it 'unblocks the domain' do
      service = double(call: true)
      service = instance_double(UnblockDomainService, call: true)
      allow(UnblockDomainService).to receive(:new).and_return(service)
      domain_block = Fabricate(:domain_block)
      delete :destroy, params: { id: domain_block.id }

M spec/controllers/api/v1/reports_controller_spec.rb => spec/controllers/api/v1/reports_controller_spec.rb +2 -1
@@ 23,7 23,8 @@ RSpec.describe Api::V1::ReportsController do
    let(:rule_ids) { nil }

    before do
      allow(AdminMailer).to receive(:new_report).and_return(double('email', deliver_later: nil))
      allow(AdminMailer).to receive(:new_report)
        .and_return(instance_double(ActionMailer::MessageDelivery, deliver_later: nil))
      post :create, params: { status_ids: [status.id], account_id: target_account.id, comment: 'reasons', category: category, rule_ids: rule_ids, forward: forward }
    end


M spec/controllers/api/web/embeds_controller_spec.rb => spec/controllers/api/web/embeds_controller_spec.rb +1 -1
@@ 26,7 26,7 @@ describe Api::Web::EmbedsController do

    context 'when fails to find status' do
      let(:url) { 'https://host.test/oembed.html' }
      let(:service_instance) { double('fetch_oembed_service') }
      let(:service_instance) { instance_double(FetchOEmbedService) }

      before do
        allow(FetchOEmbedService).to receive(:new) { service_instance }

M spec/controllers/auth/sessions_controller_spec.rb => spec/controllers/auth/sessions_controller_spec.rb +2 -1
@@ 127,7 127,8 @@ RSpec.describe Auth::SessionsController do

        before do
          allow_any_instance_of(ActionDispatch::Request).to receive(:remote_ip).and_return(current_ip)
          allow(UserMailer).to receive(:suspicious_sign_in).and_return(double('email', deliver_later!: nil))
          allow(UserMailer).to receive(:suspicious_sign_in)
            .and_return(instance_double(ActionMailer::MessageDelivery, deliver_later!: nil))
          user.update(current_sign_in_at: 1.month.ago)
          post :create, params: { user: { email: user.email, password: user.password } }
        end

M spec/controllers/authorize_interactions_controller_spec.rb => spec/controllers/authorize_interactions_controller_spec.rb +5 -5
@@ 28,7 28,7 @@ describe AuthorizeInteractionsController do
      end

      it 'renders error when account cant be found' do
        service = double
        service = instance_double(ResolveAccountService)
        allow(ResolveAccountService).to receive(:new).and_return(service)
        allow(service).to receive(:call).with('missing@hostname').and_return(nil)



@@ 40,7 40,7 @@ describe AuthorizeInteractionsController do

      it 'sets resource from url' do
        account = Fabricate(:account)
        service = double
        service = instance_double(ResolveURLService)
        allow(ResolveURLService).to receive(:new).and_return(service)
        allow(service).to receive(:call).with('http://example.com').and_return(account)



@@ 52,7 52,7 @@ describe AuthorizeInteractionsController do

      it 'sets resource from acct uri' do
        account = Fabricate(:account)
        service = double
        service = instance_double(ResolveAccountService)
        allow(ResolveAccountService).to receive(:new).and_return(service)
        allow(service).to receive(:call).with('found@hostname').and_return(account)



@@ 82,7 82,7 @@ describe AuthorizeInteractionsController do
      end

      it 'shows error when account not found' do
        service = double
        service = instance_double(ResolveAccountService)

        allow(ResolveAccountService).to receive(:new).and_return(service)
        allow(service).to receive(:call).with('user@hostname').and_return(nil)


@@ 94,7 94,7 @@ describe AuthorizeInteractionsController do

      it 'follows account when found' do
        target_account = Fabricate(:account)
        service = double
        service = instance_double(ResolveAccountService)

        allow(ResolveAccountService).to receive(:new).and_return(service)
        allow(service).to receive(:call).with('user@hostname').and_return(target_account)

M spec/controllers/disputes/appeals_controller_spec.rb => spec/controllers/disputes/appeals_controller_spec.rb +2 -1
@@ 14,7 14,8 @@ RSpec.describe Disputes::AppealsController do
    let(:strike) { Fabricate(:account_warning, target_account: current_user.account) }

    before do
      allow(AdminMailer).to receive(:new_appeal).and_return(double('email', deliver_later: nil))
      allow(AdminMailer).to receive(:new_appeal)
        .and_return(instance_double(ActionMailer::MessageDelivery, deliver_later: nil))
      post :create, params: { strike_id: strike.id, appeal: { text: 'Foo' } }
    end


M spec/helpers/statuses_helper_spec.rb => spec/helpers/statuses_helper_spec.rb +17 -17
@@ 117,42 117,42 @@ describe StatusesHelper do

  describe '#style_classes' do
    it do
      status = double(reblog?: false)
      status = instance_double(Status, reblog?: false)
      classes = helper.style_classes(status, false, false, false)

      expect(classes).to eq 'entry'
    end

    it do
      status = double(reblog?: true)
      status = instance_double(Status, reblog?: true)
      classes = helper.style_classes(status, false, false, false)

      expect(classes).to eq 'entry entry-reblog'
    end

    it do
      status = double(reblog?: false)
      status = instance_double(Status, reblog?: false)
      classes = helper.style_classes(status, true, false, false)

      expect(classes).to eq 'entry entry-predecessor'
    end

    it do
      status = double(reblog?: false)
      status = instance_double(Status, reblog?: false)
      classes = helper.style_classes(status, false, true, false)

      expect(classes).to eq 'entry entry-successor'
    end

    it do
      status = double(reblog?: false)
      status = instance_double(Status, reblog?: false)
      classes = helper.style_classes(status, false, false, true)

      expect(classes).to eq 'entry entry-center'
    end

    it do
      status = double(reblog?: true)
      status = instance_double(Status, reblog?: true)
      classes = helper.style_classes(status, true, true, true)

      expect(classes).to eq 'entry entry-predecessor entry-reblog entry-successor entry-center'


@@ 161,35 161,35 @@ describe StatusesHelper do

  describe '#microformats_classes' do
    it do
      status = double(reblog?: false)
      status = instance_double(Status, reblog?: false)
      classes = helper.microformats_classes(status, false, false)

      expect(classes).to eq ''
    end

    it do
      status = double(reblog?: false)
      status = instance_double(Status, reblog?: false)
      classes = helper.microformats_classes(status, true, false)

      expect(classes).to eq 'p-in-reply-to'
    end

    it do
      status = double(reblog?: false)
      status = instance_double(Status, reblog?: false)
      classes = helper.microformats_classes(status, false, true)

      expect(classes).to eq 'p-comment'
    end

    it do
      status = double(reblog?: true)
      status = instance_double(Status, reblog?: true)
      classes = helper.microformats_classes(status, true, false)

      expect(classes).to eq 'p-in-reply-to p-repost-of'
    end

    it do
      status = double(reblog?: true)
      status = instance_double(Status, reblog?: true)
      classes = helper.microformats_classes(status, true, true)

      expect(classes).to eq 'p-in-reply-to p-repost-of p-comment'


@@ 198,42 198,42 @@ describe StatusesHelper do

  describe '#microformats_h_class' do
    it do
      status = double(reblog?: false)
      status = instance_double(Status, reblog?: false)
      css_class = helper.microformats_h_class(status, false, false, false)

      expect(css_class).to eq 'h-entry'
    end

    it do
      status = double(reblog?: true)
      status = instance_double(Status, reblog?: true)
      css_class = helper.microformats_h_class(status, false, false, false)

      expect(css_class).to eq 'h-cite'
    end

    it do
      status = double(reblog?: false)
      status = instance_double(Status, reblog?: false)
      css_class = helper.microformats_h_class(status, true, false, false)

      expect(css_class).to eq 'h-cite'
    end

    it do
      status = double(reblog?: false)
      status = instance_double(Status, reblog?: false)
      css_class = helper.microformats_h_class(status, false, true, false)

      expect(css_class).to eq 'h-cite'
    end

    it do
      status = double(reblog?: false)
      status = instance_double(Status, reblog?: false)
      css_class = helper.microformats_h_class(status, false, false, true)

      expect(css_class).to eq ''
    end

    it do
      status = double(reblog?: true)
      status = instance_double(Status, reblog?: true)
      css_class = helper.microformats_h_class(status, true, true, true)

      expect(css_class).to eq 'h-cite'

M spec/lib/activitypub/activity/add_spec.rb => spec/lib/activitypub/activity/add_spec.rb +1 -1
@@ 26,7 26,7 @@ RSpec.describe ActivityPub::Activity::Add do
    end

    context 'when status was not known before' do
      let(:service_stub) { double }
      let(:service_stub) { instance_double(ActivityPub::FetchRemoteStatusService) }

      let(:json) do
        {

M spec/lib/activitypub/activity/move_spec.rb => spec/lib/activitypub/activity/move_spec.rb +1 -1
@@ 26,7 26,7 @@ RSpec.describe ActivityPub::Activity::Move do
    stub_request(:post, old_account.inbox_url).to_return(status: 200)
    stub_request(:post, new_account.inbox_url).to_return(status: 200)

    service_stub = double
    service_stub = instance_double(ActivityPub::FetchRemoteAccountService)
    allow(ActivityPub::FetchRemoteAccountService).to receive(:new).and_return(service_stub)
    allow(service_stub).to receive(:call).and_return(returned_account)
  end

M spec/lib/request_spec.rb => spec/lib/request_spec.rb +2 -2
@@ 48,7 48,7 @@ describe Request do
      end

      it 'executes a HTTP request when the first address is private' do
        resolver = double
        resolver = instance_double(Resolv::DNS)

        allow(resolver).to receive(:getaddresses).with('example.com').and_return(%w(0.0.0.0 2001:4860:4860::8844))
        allow(resolver).to receive(:timeouts=).and_return(nil)


@@ 83,7 83,7 @@ describe Request do
      end

      it 'raises Mastodon::ValidationError' do
        resolver = double
        resolver = instance_double(Resolv::DNS)

        allow(resolver).to receive(:getaddresses).with('example.com').and_return(%w(0.0.0.0 2001:db8::face))
        allow(resolver).to receive(:timeouts=).and_return(nil)

M spec/lib/suspicious_sign_in_detector_spec.rb => spec/lib/suspicious_sign_in_detector_spec.rb +1 -1
@@ 7,7 7,7 @@ RSpec.describe SuspiciousSignInDetector do
    subject { described_class.new(user).suspicious?(request) }

    let(:user) { Fabricate(:user, current_sign_in_at: 1.day.ago) }
    let(:request) { double(remote_ip: remote_ip) }
    let(:request) { instance_double(ActionDispatch::Request, remote_ip: remote_ip) }
    let(:remote_ip) { nil }

    context 'when user has 2FA enabled' do

M spec/models/account/field_spec.rb => spec/models/account/field_spec.rb +3 -3
@@ 6,7 6,7 @@ RSpec.describe Account::Field do
  describe '#verified?' do
    subject { described_class.new(account, 'name' => 'Foo', 'value' => 'Bar', 'verified_at' => verified_at) }

    let(:account) { double('Account', local?: true) }
    let(:account) { instance_double(Account, local?: true) }

    context 'when verified_at is set' do
      let(:verified_at) { Time.now.utc.iso8601 }


@@ 28,7 28,7 @@ RSpec.describe Account::Field do
  describe '#mark_verified!' do
    subject { described_class.new(account, original_hash) }

    let(:account) { double('Account', local?: true) }
    let(:account) { instance_double(Account, local?: true) }
    let(:original_hash) { { 'name' => 'Foo', 'value' => 'Bar' } }

    before do


@@ 47,7 47,7 @@ RSpec.describe Account::Field do
  describe '#verifiable?' do
    subject { described_class.new(account, 'name' => 'Foo', 'value' => value) }

    let(:account) { double('Account', local?: local) }
    let(:account) { instance_double(Account, local?: local) }

    context 'with local accounts' do
      let(:local) { true }

M spec/models/account_migration_spec.rb => spec/models/account_migration_spec.rb +2 -2
@@ 15,7 15,7 @@ RSpec.describe AccountMigration do
      before do
        target_account.aliases.create!(acct: source_account.acct)

        service_double = double
        service_double = instance_double(ResolveAccountService)
        allow(ResolveAccountService).to receive(:new).and_return(service_double)
        allow(service_double).to receive(:call).with(target_acct, anything).and_return(target_account)
      end


@@ 29,7 29,7 @@ RSpec.describe AccountMigration do
      let(:target_acct) { 'target@remote' }

      before do
        service_double = double
        service_double = instance_double(ResolveAccountService)
        allow(ResolveAccountService).to receive(:new).and_return(service_double)
        allow(service_double).to receive(:call).with(target_acct, anything).and_return(nil)
      end

M spec/models/session_activation_spec.rb => spec/models/session_activation_spec.rb +2 -2
@@ 16,7 16,7 @@ RSpec.describe SessionActivation do
      allow(session_activation).to receive(:detection).and_return(detection)
    end

    let(:detection)          { double(id: 1) }
    let(:detection)          { instance_double(Browser::Chrome, id: 1) }
    let(:session_activation) { Fabricate(:session_activation) }

    it 'returns detection.id' do


@@ 30,7 30,7 @@ RSpec.describe SessionActivation do
    end

    let(:session_activation) { Fabricate(:session_activation) }
    let(:detection)          { double(platform: double(id: 1)) }
    let(:detection)          { instance_double(Browser::Chrome, platform: instance_double(Browser::Platform, id: 1)) }

    it 'returns detection.platform.id' do
      expect(session_activation.platform).to be 1

M spec/models/setting_spec.rb => spec/models/setting_spec.rb +1 -1
@@ 62,7 62,7 @@ RSpec.describe Setting do

        context 'when RailsSettings::Settings.object returns truthy' do
          let(:object) { db_val }
          let(:db_val) { double(value: 'db_val') }
          let(:db_val) { instance_double(described_class, value: 'db_val') }

          context 'when default_value is a Hash' do
            let(:default_value) { { default_value: 'default_value' } }

M spec/services/account_search_service_spec.rb => spec/services/account_search_service_spec.rb +2 -2
@@ 53,7 53,7 @@ describe AccountSearchService, type: :service do

    context 'when there is a domain but no exact match' do
      it 'follows the remote account when resolve is true' do
        service = double(call: nil)
        service = instance_double(ResolveAccountService, call: nil)
        allow(ResolveAccountService).to receive(:new).and_return(service)

        results = subject.call('newuser@remote.com', nil, limit: 10, resolve: true)


@@ 61,7 61,7 @@ describe AccountSearchService, type: :service do
      end

      it 'does not follow the remote account when resolve is false' do
        service = double(call: nil)
        service = instance_double(ResolveAccountService, call: nil)
        allow(ResolveAccountService).to receive(:new).and_return(service)

        results = subject.call('newuser@remote.com', nil, limit: 10, resolve: false)

M spec/services/bootstrap_timeline_service_spec.rb => spec/services/bootstrap_timeline_service_spec.rb +1 -1
@@ 6,7 6,7 @@ RSpec.describe BootstrapTimelineService, type: :service do
  subject { described_class.new }

  context 'when the new user has registered from an invite' do
    let(:service)    { double }
    let(:service)    { instance_double(FollowService) }
    let(:autofollow) { false }
    let(:inviter)    { Fabricate(:user, confirmed_at: 2.days.ago) }
    let(:invite)     { Fabricate(:invite, user: inviter, max_uses: nil, expires_at: 1.hour.from_now, autofollow: autofollow) }

M spec/services/bulk_import_service_spec.rb => spec/services/bulk_import_service_spec.rb +8 -8
@@ 47,7 47,7 @@ RSpec.describe BulkImportService do
      it 'requests to follow all the listed users once the workers have run' do
        subject.call(import)

        resolve_account_service_double = double
        resolve_account_service_double = instance_double(ResolveAccountService)
        allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double)
        allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) }
        allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) }


@@ 95,7 95,7 @@ RSpec.describe BulkImportService do
      it 'requests to follow all the expected users once the workers have run' do
        subject.call(import)

        resolve_account_service_double = double
        resolve_account_service_double = instance_double(ResolveAccountService)
        allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double)
        allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) }
        allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) }


@@ 133,7 133,7 @@ RSpec.describe BulkImportService do
      it 'blocks all the listed users once the workers have run' do
        subject.call(import)

        resolve_account_service_double = double
        resolve_account_service_double = instance_double(ResolveAccountService)
        allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double)
        allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) }
        allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) }


@@ 177,7 177,7 @@ RSpec.describe BulkImportService do
      it 'requests to follow all the expected users once the workers have run' do
        subject.call(import)

        resolve_account_service_double = double
        resolve_account_service_double = instance_double(ResolveAccountService)
        allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double)
        allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) }
        allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) }


@@ 215,7 215,7 @@ RSpec.describe BulkImportService do
      it 'mutes all the listed users once the workers have run' do
        subject.call(import)

        resolve_account_service_double = double
        resolve_account_service_double = instance_double(ResolveAccountService)
        allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double)
        allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) }
        allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) }


@@ 263,7 263,7 @@ RSpec.describe BulkImportService do
      it 'requests to follow all the expected users once the workers have run' do
        subject.call(import)

        resolve_account_service_double = double
        resolve_account_service_double = instance_double(ResolveAccountService)
        allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service_double)
        allow(resolve_account_service_double).to receive(:call).with('user@foo.bar', any_args) { Fabricate(:account, username: 'user', domain: 'foo.bar', protocol: :activitypub) }
        allow(resolve_account_service_double).to receive(:call).with('unknown@unknown.bar', any_args) { Fabricate(:account, username: 'unknown', domain: 'unknown.bar', protocol: :activitypub) }


@@ 360,7 360,7 @@ RSpec.describe BulkImportService do
      it 'updates the bookmarks as expected once the workers have run' do
        subject.call(import)

        service_double = double
        service_double = instance_double(ActivityPub::FetchRemoteStatusService)
        allow(ActivityPub::FetchRemoteStatusService).to receive(:new).and_return(service_double)
        allow(service_double).to receive(:call).with('https://domain.unknown/foo') { Fabricate(:status, uri: 'https://domain.unknown/foo') }
        allow(service_double).to receive(:call).with('https://domain.unknown/private') { Fabricate(:status, uri: 'https://domain.unknown/private', visibility: :direct) }


@@ 403,7 403,7 @@ RSpec.describe BulkImportService do
      it 'updates the bookmarks as expected once the workers have run' do
        subject.call(import)

        service_double = double
        service_double = instance_double(ActivityPub::FetchRemoteStatusService)
        allow(ActivityPub::FetchRemoteStatusService).to receive(:new).and_return(service_double)
        allow(service_double).to receive(:call).with('https://domain.unknown/foo') { Fabricate(:status, uri: 'https://domain.unknown/foo') }
        allow(service_double).to receive(:call).with('https://domain.unknown/private') { Fabricate(:status, uri: 'https://domain.unknown/private', visibility: :direct) }

M spec/services/fetch_resource_service_spec.rb => spec/services/fetch_resource_service_spec.rb +2 -2
@@ 24,7 24,7 @@ RSpec.describe FetchResourceService, type: :service do

    context 'when OpenSSL::SSL::SSLError is raised' do
      before do
        request = double
        request = instance_double(Request)
        allow(Request).to receive(:new).and_return(request)
        allow(request).to receive(:add_headers)
        allow(request).to receive(:on_behalf_of)


@@ 36,7 36,7 @@ RSpec.describe FetchResourceService, type: :service do

    context 'when HTTP::ConnectionError is raised' do
      before do
        request = double
        request = instance_double(Request)
        allow(Request).to receive(:new).and_return(request)
        allow(request).to receive(:add_headers)
        allow(request).to receive(:on_behalf_of)

M spec/services/import_service_spec.rb => spec/services/import_service_spec.rb +1 -1
@@ 219,7 219,7 @@ RSpec.describe ImportService, type: :service do
    end

    before do
      service = double
      service = instance_double(ActivityPub::FetchRemoteStatusService)
      allow(ActivityPub::FetchRemoteStatusService).to receive(:new).and_return(service)
      allow(service).to receive(:call).with('https://unknown-remote.com/users/bar/statuses/1') do
        Fabricate(:status, uri: 'https://unknown-remote.com/users/bar/statuses/1')

M spec/services/post_status_service_spec.rb => spec/services/post_status_service_spec.rb +2 -2
@@ 132,7 132,7 @@ RSpec.describe PostStatusService, type: :service do
  end

  it 'processes mentions' do
    mention_service = double(:process_mentions_service)
    mention_service = instance_double(ProcessMentionsService)
    allow(mention_service).to receive(:call)
    allow(ProcessMentionsService).to receive(:new).and_return(mention_service)
    account = Fabricate(:account)


@@ 163,7 163,7 @@ RSpec.describe PostStatusService, type: :service do
  end

  it 'processes hashtags' do
    hashtags_service = double(:process_hashtags_service)
    hashtags_service = instance_double(ProcessHashtagsService)
    allow(hashtags_service).to receive(:call)
    allow(ProcessHashtagsService).to receive(:new).and_return(hashtags_service)
    account = Fabricate(:account)

M spec/services/resolve_url_service_spec.rb => spec/services/resolve_url_service_spec.rb +2 -2
@@ 9,7 9,7 @@ describe ResolveURLService, type: :service do
    it 'returns nil when there is no resource url' do
      url           = 'http://example.com/missing-resource'
      known_account = Fabricate(:account, uri: url)
      service = double
      service = instance_double(FetchResourceService)

      allow(FetchResourceService).to receive(:new).and_return service
      allow(service).to receive(:response_code).and_return(404)


@@ 21,7 21,7 @@ describe ResolveURLService, type: :service do
    it 'returns known account on temporary error' do
      url           = 'http://example.com/missing-resource'
      known_account = Fabricate(:account, uri: url)
      service = double
      service = instance_double(FetchResourceService)

      allow(FetchResourceService).to receive(:new).and_return service
      allow(service).to receive(:response_code).and_return(500)

M spec/services/search_service_spec.rb => spec/services/search_service_spec.rb +4 -4
@@ 25,7 25,7 @@ describe SearchService, type: :service do

      context 'when it does not find anything' do
        it 'returns the empty results' do
          service = double(call: nil)
          service = instance_double(ResolveURLService, call: nil)
          allow(ResolveURLService).to receive(:new).and_return(service)
          results = subject.call(@query, nil, 10, resolve: true)



@@ 37,7 37,7 @@ describe SearchService, type: :service do
      context 'when it finds an account' do
        it 'includes the account in the results' do
          account = Account.new
          service = double(call: account)
          service = instance_double(ResolveURLService, call: account)
          allow(ResolveURLService).to receive(:new).and_return(service)

          results = subject.call(@query, nil, 10, resolve: true)


@@ 49,7 49,7 @@ describe SearchService, type: :service do
      context 'when it finds a status' do
        it 'includes the status in the results' do
          status = Status.new
          service = double(call: status)
          service = instance_double(ResolveURLService, call: status)
          allow(ResolveURLService).to receive(:new).and_return(service)

          results = subject.call(@query, nil, 10, resolve: true)


@@ 64,7 64,7 @@ describe SearchService, type: :service do
        it 'includes the account in the results' do
          query = 'username'
          account = Account.new
          service = double(call: [account])
          service = instance_double(AccountSearchService, call: [account])
          allow(AccountSearchService).to receive(:new).and_return(service)

          results = subject.call(query, nil, 10)

M spec/services/unsuspend_account_service_spec.rb => spec/services/unsuspend_account_service_spec.rb +1 -1
@@ 63,7 63,7 @@ RSpec.describe UnsuspendAccountService, type: :service do
  describe 'unsuspending a remote account' do
    include_examples 'with common context' do
      let!(:account)                 { Fabricate(:account, domain: 'bob.com', uri: 'https://bob.com', inbox_url: 'https://bob.com/inbox', protocol: :activitypub) }
      let!(:resolve_account_service) { double }
      let!(:resolve_account_service) { instance_double(ResolveAccountService) }

      before do
        allow(ResolveAccountService).to receive(:new).and_return(resolve_account_service)

M spec/validators/blacklisted_email_validator_spec.rb => spec/validators/blacklisted_email_validator_spec.rb +2 -2
@@ 6,8 6,8 @@ RSpec.describe BlacklistedEmailValidator, type: :validator do
  describe '#validate' do
    subject { described_class.new.validate(user); errors }

    let(:user)   { double(email: 'info@mail.com', sign_up_ip: '1.2.3.4', errors: errors) }
    let(:errors) { double(add: nil) }
    let(:user)   { instance_double(User, email: 'info@mail.com', sign_up_ip: '1.2.3.4', errors: errors) }
    let(:errors) { instance_double(ActiveModel::Errors, add: nil) }

    before do
      allow(user).to receive(:valid_invitation?).and_return(false)

M spec/validators/disallowed_hashtags_validator_spec.rb => spec/validators/disallowed_hashtags_validator_spec.rb +2 -2
@@ 11,8 11,8 @@ RSpec.describe DisallowedHashtagsValidator, type: :validator do
      described_class.new.validate(status)
    end

    let(:status) { double(errors: errors, local?: local, reblog?: reblog, text: disallowed_tags.map { |x| "##{x}" }.join(' ')) }
    let(:errors) { double(add: nil) }
    let(:status) { instance_double(Status, errors: errors, local?: local, reblog?: reblog, text: disallowed_tags.map { |x| "##{x}" }.join(' ')) }
    let(:errors) { instance_double(ActiveModel::Errors, add: nil) }

    context 'with a remote reblog' do
      let(:local)  { false }

M spec/validators/email_mx_validator_spec.rb => spec/validators/email_mx_validator_spec.rb +18 -14
@@ 4,7 4,7 @@ require 'rails_helper'

describe EmailMxValidator do
  describe '#validate' do
    let(:user) { double(email: 'foo@example.com', sign_up_ip: '1.2.3.4', errors: double(add: nil)) }
    let(:user) { instance_double(User, email: 'foo@example.com', sign_up_ip: '1.2.3.4', errors: instance_double(ActiveModel::Errors, add: nil)) }

    context 'with an e-mail domain that is explicitly allowed' do
      around do |block|


@@ 15,7 15,7 @@ describe EmailMxValidator do
      end

      it 'does not add errors if there are no DNS records' do
        resolver = double
        resolver = instance_double(Resolv::DNS)

        allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([])
        allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([])


@@ 29,7 29,7 @@ describe EmailMxValidator do
    end

    it 'adds no error if there are DNS records for the e-mail domain' do
      resolver = double
      resolver = instance_double(Resolv::DNS)

      allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([])
      allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([Resolv::DNS::Resource::IN::A.new('192.0.2.42')])


@@ 46,19 46,19 @@ describe EmailMxValidator do
      allow(TagManager).to receive(:instance).and_return(double)
      allow(double).to receive(:normalize_domain).with('example.com').and_raise(Addressable::URI::InvalidURIError)

      user = double(email: 'foo@example.com', errors: double(add: nil))
      user = instance_double(User, email: 'foo@example.com', errors: instance_double(ActiveModel::Errors, add: nil))
      subject.validate(user)
      expect(user.errors).to have_received(:add)
    end

    it 'adds an error if the domain email portion is blank' do
      user = double(email: 'foo@', errors: double(add: nil))
      user = instance_double(User, email: 'foo@', errors: instance_double(ActiveModel::Errors, add: nil))
      subject.validate(user)
      expect(user.errors).to have_received(:add)
    end

    it 'adds an error if the email domain name contains empty labels' do
      resolver = double
      resolver = instance_double(Resolv::DNS)

      allow(resolver).to receive(:getresources).with('example..com', Resolv::DNS::Resource::IN::MX).and_return([])
      allow(resolver).to receive(:getresources).with('example..com', Resolv::DNS::Resource::IN::A).and_return([Resolv::DNS::Resource::IN::A.new('192.0.2.42')])


@@ 66,13 66,13 @@ describe EmailMxValidator do
      allow(resolver).to receive(:timeouts=).and_return(nil)
      allow(Resolv::DNS).to receive(:open).and_yield(resolver)

      user = double(email: 'foo@example..com', sign_up_ip: '1.2.3.4', errors: double(add: nil))
      user = instance_double(User, email: 'foo@example..com', sign_up_ip: '1.2.3.4', errors: instance_double(ActiveModel::Errors, add: nil))
      subject.validate(user)
      expect(user.errors).to have_received(:add)
    end

    it 'adds an error if there are no DNS records for the e-mail domain' do
      resolver = double
      resolver = instance_double(Resolv::DNS)

      allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([])
      allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([])


@@ 85,9 85,11 @@ describe EmailMxValidator do
    end

    it 'adds an error if a MX record does not lead to an IP' do
      resolver = double
      resolver = instance_double(Resolv::DNS)

      allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([double(exchange: 'mail.example.com')])
      allow(resolver).to receive(:getresources)
        .with('example.com', Resolv::DNS::Resource::IN::MX)
        .and_return([instance_double(Resolv::DNS::Resource::MX, exchange: 'mail.example.com')])
      allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([])
      allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([])
      allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::A).and_return([])


@@ 101,13 103,15 @@ describe EmailMxValidator do

    it 'adds an error if the MX record is blacklisted' do
      EmailDomainBlock.create!(domain: 'mail.example.com')
      resolver = double
      resolver = instance_double(Resolv::DNS)

      allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::MX).and_return([double(exchange: 'mail.example.com')])
      allow(resolver).to receive(:getresources)
        .with('example.com', Resolv::DNS::Resource::IN::MX)
        .and_return([instance_double(Resolv::DNS::Resource::MX, exchange: 'mail.example.com')])
      allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::A).and_return([])
      allow(resolver).to receive(:getresources).with('example.com', Resolv::DNS::Resource::IN::AAAA).and_return([])
      allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::A).and_return([double(address: '2.3.4.5')])
      allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::AAAA).and_return([double(address: 'fd00::2')])
      allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::A).and_return([instance_double(Resolv::DNS::Resource::IN::A, address: '2.3.4.5')])
      allow(resolver).to receive(:getresources).with('mail.example.com', Resolv::DNS::Resource::IN::AAAA).and_return([instance_double(Resolv::DNS::Resource::IN::A, address: 'fd00::2')])
      allow(resolver).to receive(:timeouts=).and_return(nil)
      allow(Resolv::DNS).to receive(:open).and_yield(resolver)


M spec/validators/follow_limit_validator_spec.rb => spec/validators/follow_limit_validator_spec.rb +3 -3
@@ 12,9 12,9 @@ RSpec.describe FollowLimitValidator, type: :validator do
      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(:follow)  { instance_double(Follow, account: account, errors: errors) }
    let(:errors)  { instance_double(ActiveModel::Errors, add: nil) }
    let(:account) { instance_double(Account, nil?: _nil, local?: local, following_count: 0, followers_count: 0) }
    let(:_nil)    { true }
    let(:local)   { false }


M spec/validators/note_length_validator_spec.rb => spec/validators/note_length_validator_spec.rb +9 -3
@@ 8,7 8,7 @@ describe NoteLengthValidator do
  describe '#validate' do
    it 'adds an error when text is over 500 characters' do
      text = 'a' * 520
      account = double(note: text, errors: double(add: nil))
      account = instance_double(Account, note: text, errors: activemodel_errors)

      subject.validate_each(account, 'note', text)
      expect(account.errors).to have_received(:add)


@@ 16,7 16,7 @@ describe NoteLengthValidator do

    it 'counts URLs as 23 characters flat' do
      text = ('a' * 476) + " http://#{'b' * 30}.com/example"
      account = double(note: text, errors: double(add: nil))
      account = instance_double(Account, note: text, errors: activemodel_errors)

      subject.validate_each(account, 'note', text)
      expect(account.errors).to_not have_received(:add)


@@ 24,10 24,16 @@ describe NoteLengthValidator do

    it 'does not count non-autolinkable URLs as 23 characters flat' do
      text = ('a' * 476) + "http://#{'b' * 30}.com/example"
      account = double(note: text, errors: double(add: nil))
      account = instance_double(Account, note: text, errors: activemodel_errors)

      subject.validate_each(account, 'note', text)
      expect(account.errors).to have_received(:add)
    end

    private

    def activemodel_errors
      instance_double(ActiveModel::Errors, add: nil)
    end
  end
end

M spec/validators/poll_validator_spec.rb => spec/validators/poll_validator_spec.rb +2 -2
@@ 9,8 9,8 @@ RSpec.describe PollValidator, type: :validator do
    end

    let(:validator) { described_class.new }
    let(:poll) { double(options: options, expires_at: expires_at, errors: errors) }
    let(:errors) { double(add: nil) }
    let(:poll) { instance_double(Poll, options: options, expires_at: expires_at, errors: errors) }
    let(:errors) { instance_double(ActiveModel::Errors, add: nil) }
    let(:options) { %w(foo bar) }
    let(:expires_at) { 1.day.from_now }


M spec/validators/status_length_validator_spec.rb => spec/validators/status_length_validator_spec.rb +16 -10
@@ 5,38 5,38 @@ require 'rails_helper'
describe StatusLengthValidator do
  describe '#validate' do
    it 'does not add errors onto remote statuses' do
      status = double(local?: false)
      status = instance_double(Status, local?: false)
      subject.validate(status)
      expect(status).to_not receive(:errors)
    end

    it 'does not add errors onto local reblogs' do
      status = double(local?: false, reblog?: true)
      status = instance_double(Status, local?: false, reblog?: true)
      subject.validate(status)
      expect(status).to_not receive(:errors)
    end

    it 'adds an error when content warning is over 500 characters' do
      status = double(spoiler_text: 'a' * 520, text: '', errors: double(add: nil), local?: true, reblog?: false)
      status = instance_double(Status, spoiler_text: 'a' * 520, text: '', errors: activemodel_errors, local?: true, reblog?: false)
      subject.validate(status)
      expect(status.errors).to have_received(:add)
    end

    it 'adds an error when text is over 500 characters' do
      status = double(spoiler_text: '', text: 'a' * 520, errors: double(add: nil), local?: true, reblog?: false)
      status = instance_double(Status, spoiler_text: '', text: 'a' * 520, errors: activemodel_errors, local?: true, reblog?: false)
      subject.validate(status)
      expect(status.errors).to have_received(:add)
    end

    it 'adds an error when text and content warning are over 500 characters total' do
      status = double(spoiler_text: 'a' * 250, text: 'b' * 251, errors: double(add: nil), local?: true, reblog?: false)
      status = instance_double(Status, spoiler_text: 'a' * 250, text: 'b' * 251, errors: activemodel_errors, local?: true, reblog?: false)
      subject.validate(status)
      expect(status.errors).to have_received(:add)
    end

    it 'counts URLs as 23 characters flat' do
      text   = ('a' * 476) + " http://#{'b' * 30}.com/example"
      status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false)
      status = instance_double(Status, spoiler_text: '', text: text, errors: activemodel_errors, local?: true, reblog?: false)

      subject.validate(status)
      expect(status.errors).to_not have_received(:add)


@@ 44,7 44,7 @@ describe StatusLengthValidator do

    it 'does not count non-autolinkable URLs as 23 characters flat' do
      text   = ('a' * 476) + "http://#{'b' * 30}.com/example"
      status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false)
      status = instance_double(Status, spoiler_text: '', text: text, errors: activemodel_errors, local?: true, reblog?: false)

      subject.validate(status)
      expect(status.errors).to have_received(:add)


@@ 52,14 52,14 @@ describe StatusLengthValidator do

    it 'does not count overly long URLs as 23 characters flat' do
      text = "http://example.com/valid?#{'#foo?' * 1000}"
      status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false)
      status = instance_double(Status, spoiler_text: '', text: text, errors: activemodel_errors, local?: true, reblog?: false)
      subject.validate(status)
      expect(status.errors).to have_received(:add)
    end

    it 'counts only the front part of remote usernames' do
      text   = ('a' * 475) + " @alice@#{'b' * 30}.com"
      status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false)
      status = instance_double(Status, spoiler_text: '', text: text, errors: activemodel_errors, local?: true, reblog?: false)

      subject.validate(status)
      expect(status.errors).to_not have_received(:add)


@@ 67,10 67,16 @@ describe StatusLengthValidator do

    it 'does count both parts of remote usernames for overly long domains' do
      text   = "@alice@#{'b' * 500}.com"
      status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false)
      status = instance_double(Status, spoiler_text: '', text: text, errors: activemodel_errors, local?: true, reblog?: false)

      subject.validate(status)
      expect(status.errors).to have_received(:add)
    end
  end

  private

  def activemodel_errors
    instance_double(ActiveModel::Errors, add: nil)
  end
end

M spec/validators/status_pin_validator_spec.rb => spec/validators/status_pin_validator_spec.rb +5 -5
@@ 8,11 8,11 @@ RSpec.describe StatusPinValidator, type: :validator 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, direct_visibility?: visibility == 'direct') }
    let(:account)     { double(status_pins: status_pins, local?: local) }
    let(:status_pins) { double(count: count) }
    let(:errors)      { double(add: nil) }
    let(:pin) { instance_double(StatusPin, account: account, errors: errors, status: status, account_id: pin_account_id) }
    let(:status) { instance_double(Status, reblog?: reblog, account_id: status_account_id, visibility: visibility, direct_visibility?: visibility == 'direct') }
    let(:account)     { instance_double(Account, status_pins: status_pins, local?: local) }
    let(:status_pins) { instance_double(Array, count: count) }
    let(:errors)      { instance_double(ActiveModel::Errors, add: nil) }
    let(:pin_account_id)    { 1 }
    let(:status_account_id) { 1 }
    let(:visibility)  { 'public' }

M spec/validators/unique_username_validator_spec.rb => spec/validators/unique_username_validator_spec.rb +13 -7
@@ 6,7 6,7 @@ describe UniqueUsernameValidator do
  describe '#validate' do
    context 'when local account' do
      it 'does not add errors if username is nil' do
        account = double(username: nil, domain: nil, persisted?: false, errors: double(add: nil))
        account = instance_double(Account, username: nil, domain: nil, persisted?: false, errors: activemodel_errors)
        subject.validate(account)
        expect(account.errors).to_not have_received(:add)
      end


@@ 18,14 18,14 @@ describe UniqueUsernameValidator do

      it 'adds an error when the username is already used with ignoring cases' do
        Fabricate(:account, username: 'ABCdef')
        account = double(username: 'abcDEF', domain: nil, persisted?: false, errors: double(add: nil))
        account = instance_double(Account, username: 'abcDEF', domain: nil, persisted?: false, errors: activemodel_errors)
        subject.validate(account)
        expect(account.errors).to have_received(:add)
      end

      it 'does not add errors when same username remote account exists' do
        Fabricate(:account, username: 'abcdef', domain: 'example.com')
        account = double(username: 'abcdef', domain: nil, persisted?: false, errors: double(add: nil))
        account = instance_double(Account, username: 'abcdef', domain: nil, persisted?: false, errors: activemodel_errors)
        subject.validate(account)
        expect(account.errors).to_not have_received(:add)
      end


@@ 34,7 34,7 @@ describe UniqueUsernameValidator do

  context 'when remote account' do
    it 'does not add errors if username is nil' do
      account = double(username: nil, domain: 'example.com', persisted?: false, errors: double(add: nil))
      account = instance_double(Account, username: nil, domain: 'example.com', persisted?: false, errors: activemodel_errors)
      subject.validate(account)
      expect(account.errors).to_not have_received(:add)
    end


@@ 46,23 46,29 @@ describe UniqueUsernameValidator do

    it 'adds an error when the username is already used with ignoring cases' do
      Fabricate(:account, username: 'ABCdef', domain: 'example.com')
      account = double(username: 'abcDEF', domain: 'example.com', persisted?: false, errors: double(add: nil))
      account = instance_double(Account, username: 'abcDEF', domain: 'example.com', persisted?: false, errors: activemodel_errors)
      subject.validate(account)
      expect(account.errors).to have_received(:add)
    end

    it 'adds an error when the domain is already used with ignoring cases' do
      Fabricate(:account, username: 'ABCdef', domain: 'example.com')
      account = double(username: 'ABCdef', domain: 'EXAMPLE.COM', persisted?: false, errors: double(add: nil))
      account = instance_double(Account, username: 'ABCdef', domain: 'EXAMPLE.COM', persisted?: false, errors: activemodel_errors)
      subject.validate(account)
      expect(account.errors).to have_received(:add)
    end

    it 'does not add errors when account with the same username and another domain exists' do
      Fabricate(:account, username: 'abcdef', domain: 'example.com')
      account = double(username: 'abcdef', domain: 'example2.com', persisted?: false, errors: double(add: nil))
      account = instance_double(Account, username: 'abcdef', domain: 'example2.com', persisted?: false, errors: activemodel_errors)
      subject.validate(account)
      expect(account.errors).to_not have_received(:add)
    end
  end

  private

  def activemodel_errors
    instance_double(ActiveModel::Errors, add: nil)
  end
end

M spec/validators/unreserved_username_validator_spec.rb => spec/validators/unreserved_username_validator_spec.rb +2 -2
@@ 10,8 10,8 @@ RSpec.describe UnreservedUsernameValidator, type: :validator do
    end

    let(:validator) { described_class.new }
    let(:account)   { double(username: username, errors: errors) }
    let(:errors) { double(add: nil) }
    let(:account)   { instance_double(Account, username: username, errors: errors) }
    let(:errors) { instance_double(ActiveModel::Errors, add: nil) }

    context 'when @username is blank?' do
      let(:username) { nil }

M spec/validators/url_validator_spec.rb => spec/validators/url_validator_spec.rb +2 -2
@@ 10,8 10,8 @@ RSpec.describe URLValidator, type: :validator do
    end

    let(:validator) { described_class.new(attributes: [attribute]) }
    let(:record)    { double(errors: errors) }
    let(:errors)    { double(add: nil) }
    let(:record)    { instance_double(Webhook, errors: errors) }
    let(:errors)    { instance_double(ActiveModel::Errors, add: nil) }
    let(:value)     { '' }
    let(:attribute) { :foo }


M spec/views/statuses/show.html.haml_spec.rb => spec/views/statuses/show.html.haml_spec.rb +1 -1
@@ 4,7 4,7 @@ require 'rails_helper'

describe 'statuses/show.html.haml', without_verify_partial_doubles: true do
  before do
    double(api_oembed_url: '')
    allow(view).to receive(:api_oembed_url).and_return('')
    allow(view).to receive(:show_landing_strip?).and_return(true)
    allow(view).to receive(:site_title).and_return('example site')
    allow(view).to receive(:site_hostname).and_return('example.com')

M spec/workers/activitypub/processing_worker_spec.rb => spec/workers/activitypub/processing_worker_spec.rb +2 -1
@@ 9,7 9,8 @@ describe ActivityPub::ProcessingWorker do

  describe '#perform' do
    it 'delegates to ActivityPub::ProcessCollectionService' do
      allow(ActivityPub::ProcessCollectionService).to receive(:new).and_return(double(:service, call: nil))
      allow(ActivityPub::ProcessCollectionService).to receive(:new)
        .and_return(instance_double(ActivityPub::ProcessCollectionService, call: nil))
      subject.perform(account.id, '')
      expect(ActivityPub::ProcessCollectionService).to have_received(:new)
    end

M spec/workers/admin/domain_purge_worker_spec.rb => spec/workers/admin/domain_purge_worker_spec.rb +1 -1
@@ 7,7 7,7 @@ describe Admin::DomainPurgeWorker do

  describe 'perform' do
    it 'calls domain purge service for relevant domain block' do
      service = double(call: nil)
      service = instance_double(PurgeDomainService, call: nil)
      allow(PurgeDomainService).to receive(:new).and_return(service)
      result = subject.perform('example.com')


M spec/workers/domain_block_worker_spec.rb => spec/workers/domain_block_worker_spec.rb +1 -1
@@ 9,7 9,7 @@ describe DomainBlockWorker do
    let(:domain_block) { Fabricate(:domain_block) }

    it 'calls domain block service for relevant domain block' do
      service = double(call: nil)
      service = instance_double(BlockDomainService, call: nil)
      allow(BlockDomainService).to receive(:new).and_return(service)
      result = subject.perform(domain_block.id)


M spec/workers/domain_clear_media_worker_spec.rb => spec/workers/domain_clear_media_worker_spec.rb +1 -1
@@ 9,7 9,7 @@ describe DomainClearMediaWorker do
    let(:domain_block) { Fabricate(:domain_block, severity: :silence, reject_media: true) }

    it 'calls domain clear media service for relevant domain block' do
      service = double(call: nil)
      service = instance_double(ClearDomainMediaService, call: nil)
      allow(ClearDomainMediaService).to receive(:new).and_return(service)
      result = subject.perform(domain_block.id)


M spec/workers/feed_insert_worker_spec.rb => spec/workers/feed_insert_worker_spec.rb +4 -4
@@ 11,7 11,7 @@ describe FeedInsertWorker do

    context 'when there are no records' do
      it 'skips push with missing status' do
        instance = double(push_to_home: nil)
        instance = instance_double(FeedManager, push_to_home: nil)
        allow(FeedManager).to receive(:instance).and_return(instance)
        result = subject.perform(nil, follower.id)



@@ 20,7 20,7 @@ describe FeedInsertWorker do
      end

      it 'skips push with missing account' do
        instance = double(push_to_home: nil)
        instance = instance_double(FeedManager, push_to_home: nil)
        allow(FeedManager).to receive(:instance).and_return(instance)
        result = subject.perform(status.id, nil)



@@ 31,7 31,7 @@ describe FeedInsertWorker do

    context 'when there are real records' do
      it 'skips the push when there is a filter' do
        instance = double(push_to_home: nil, filter?: true)
        instance = instance_double(FeedManager, push_to_home: nil, filter?: true)
        allow(FeedManager).to receive(:instance).and_return(instance)
        result = subject.perform(status.id, follower.id)



@@ 40,7 40,7 @@ describe FeedInsertWorker do
      end

      it 'pushes the status onto the home timeline without filter' do
        instance = double(push_to_home: nil, filter?: false)
        instance = instance_double(FeedManager, push_to_home: nil, filter?: false)
        allow(FeedManager).to receive(:instance).and_return(instance)
        result = subject.perform(status.id, follower.id)


M spec/workers/move_worker_spec.rb => spec/workers/move_worker_spec.rb +1 -1
@@ 15,7 15,7 @@ describe MoveWorker do
  let!(:account_note)    { Fabricate(:account_note, account: local_user.account, target_account: source_account, comment: comment) }
  let(:list)             { Fabricate(:list, account: local_follower) }

  let(:block_service) { double }
  let(:block_service) { instance_double(BlockService) }

  before do
    stub_request(:post, 'https://example.org/a/inbox').to_return(status: 200)

M spec/workers/publish_scheduled_announcement_worker_spec.rb => spec/workers/publish_scheduled_announcement_worker_spec.rb +1 -1
@@ 12,7 12,7 @@ describe PublishScheduledAnnouncementWorker do

  describe 'perform' do
    before do
      service = double
      service = instance_double(FetchRemoteStatusService)
      allow(FetchRemoteStatusService).to receive(:new).and_return(service)
      allow(service).to receive(:call).with('https://domain.com/users/foo/12345') { remote_status.reload }


M spec/workers/refollow_worker_spec.rb => spec/workers/refollow_worker_spec.rb +1 -1
@@ 10,7 10,7 @@ describe RefollowWorker do
  let(:bob)     { Fabricate(:account, domain: nil, username: 'bob') }

  describe 'perform' do
    let(:service) { double }
    let(:service) { instance_double(FollowService) }

    before do
      allow(FollowService).to receive(:new).and_return(service)

M spec/workers/regeneration_worker_spec.rb => spec/workers/regeneration_worker_spec.rb +1 -1
@@ 9,7 9,7 @@ describe RegenerationWorker do
    let(:account) { Fabricate(:account) }

    it 'calls the precompute feed service for the account' do
      service = double(call: nil)
      service = instance_double(PrecomputeFeedService, call: nil)
      allow(PrecomputeFeedService).to receive(:new).and_return(service)
      result = subject.perform(account.id)